Ошибка утверждения blobFromImage с использованием OpenCV в Python - PullRequest
0 голосов
/ 26 мая 2020

Я пытаюсь запустить (не тренируя) сеть Caffe с использованием OpenCV в Python.

Мое изображение (img) является одноканальным ndarray из (48,118).

# single channel to RGB like
frame = np.zeros((img.shape[0], img.shape[1], 3))
frame[:,:,0] = img
frame[:,:,1] = img
frame[:,:,2] = img

Затем я нормализую его до 0-1.

frame /= np.max(frame)

Наконец, я использовал функцию blobFromImage, чтобы создать «каплю», а затем скормить net.

inpBlob = cv2.dnn.blobFromImage(frame, size=(368,368), mean=(0,0,0), swapRB=False, crop=False)

Проблема возникает после использования строки выше. Это вызывает ошибку утверждения:

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
c:\Users\helde\code\main.py in 
----> 67 inpBlob = cv2.dnn.blobFromImage(frame, size=(368,368), mean=(0,0,0), swapRB=False, crop=False)

error: OpenCV(3.4.2) C:\Miniconda3\conda-bld\opencv-suite_1534379934306\work\modules\dnn\src\dnn.cpp:177: 
error: (-215:Assertion failed) image.depth() == 5 in function 'cv::dnn::experimental_dnn_v5::blobFromImages'

Кто-нибудь знает, что могло вызвать эту ошибку?

1 Ответ

0 голосов
/ 27 мая 2020

Я действительно не люблю отвечать на свой вопрос, но я на случай, если у кого-то будет такая же проблема.

Решение довольно простое, OpenCV blobFromImage нуждается в изображении в uint8 формат.

Итак, в моем случае переменная frame имеет оттенки серого, и ранее я масштабировал ее до 0-1:

frame /= np.max(frame)

в данном случае новый кадр это float.

Правильное ожидание, чтобы работать с blobFromImage, включив его в uint8, будет:

img = ((frame / np.max(frame)) * 255).astype('uint8')

вам нужно это ....astype('uint8') иначе вы есть что-то со значениями пикселей от 0 до 255, НО все еще в формате float.

Пример: изображение в оттенках серого

Предположим, у нас есть изображение float (img), которое мы хотим предварительная обработка с помощью blobFromImage с размерами 100x100:

print(img.shape, type(img), img.dtype)
(48, 118) <class 'numpy.ndarray'> float64

Теперь конвертируем его в оттенки серого, как упоминалось ранее

img = ((img / np.max(img)) * 255).astype('uint8')

Просто для проверки:

print(img.shape, type(img), img.dtype)
(48, 118) <class 'numpy.ndarray'> uint8

Теперь мы можем применить blobFromImage:

inpBlob = cv2.dnn.blobFromImage(img, 
                                size=(368,368), 
                                mean=(0,0,0), 
                                swapRB=False, 
                                crop=False)

Теперь у вас должно быть что-то 4D:

print(inpBlob.shape, type(inpBlob), inpBlob.dtype)
(1, 1, 368, 368) <class 'numpy.ndarray'> float32

check!

Пример: изображение RGB

* 1 047 * Часть от float до uint8 почти такая же, с той лишь разницей, что репликация изображения имеет 3 канала RGB. Я собираюсь поместить весь код и указать на часть репликации:
# we start with the same float image (img) as before

# converting to uint8. Still one channel
img = ((img / np.max(img)) * 255).astype('uint8')

print(img.shape, type(img), img.dtype)
(48, 118) <class 'numpy.ndarray'> uint8

# replicating the only channel 3 times. There are other ways to do this:
img_rgb = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
img_rgb[:,:,0], img_rgb[:,:,1], img_rgb[:,:,2] = img, img, img

# now you'll see a thrid dimension in the shape
print(img_rgb.shape, type(img_rgb), img_rgb.dtype)
(48, 118, 3) <class 'numpy.ndarray'> uint8

# applying the blobFromImage function
inpBlob = cv2.dnn.blobFromImage(img_rgb, 
                                size=(368,368), 
                                mean=(0,0,0), 
                                swapRB=False, 
                                crop=False)

# checking...
print(inpBlob.shape, type(inpBlob), inpBlob.dtype)
(1, 3, 368, 368) <class 'numpy.ndarray'> float32
# the 3 channels are reflected in the second component of inpBlop's shape.

Как вы видели, это довольно просто, ЕСЛИ вы раньше изменили значение на uint8.

...