Python 中使用 OpenCV 的 blobFromImage 断言错误

blobFromImage Assertion error using OpenCV in Python

我正在尝试 运行(不是训练)在 Python 中使用 OpenCV 的 Caffe 网络。

我的图像 (img) 是 (48,118) 的单通道 ndarray

# 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函数创建了一个"blob"然后喂网

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'

有人知道是什么导致了这个错误吗?

我真的不想回答我自己的问题,但我会以防其他人遇到同样的问题。

解决方案非常简单,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

检查!

示例:RGB 图像

floatuint8 部分几乎相同,唯一的区别是复制图像时具有 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,则非常简单。