<>一、问题描述

今天在实现sobel算子时,用了cv的filter2D函数以后,报了如下错误
cv2.error: OpenCV(4.5.5) :-1: error: (-5:Bad argument) in function 'imshow' >
Overload resolution failed:> - mat data type = 23 is not supported > - Expected
Ptr<cv::cuda::GpuMat> for argument 'mat' > - Expected Ptr<cv::UMat> for argument
'mat'
报错代码段:
v = cv.filter2D(img_i, -1, G_x) h = cv.filter2D(img_i, -1, G_y) img = np.sqrt(v
**2 + h**2) # 此处省略阈值处理 cv.namedWindow("Image_Sobel", cv.WINDOW_NORMAL) cv.imshow
("Image_Sobel", img) cv.waitKey(0) cv.destroyAllWindows()
<>二、解决

看到报错里面有 data type = 23 ,猜测是图像的数据类型有问题,输出一看发现img中元素的数据类型是float16,现在看看imshow的要求。
opencv的官方注释指出:根据图像的深度,imshow函数会自动对其显示灰度值进行缩放,规则如下:

* 如果图像数据类型是8U(8位无符号),则直接显示。
*
如果图像数据类型是16U(16位无符号)或32S(32位有符号整数),则imshow函数内部会自动将每个像素值除以256并显示,即将原图像素值的范围由[0~
255*256]映射到[0~255]
*
如果图像数据类型是32F(32位浮点数)或64F(64位浮点数),则imshow函数内部会自动将每个像素值乘以255并显示,即将原图像素值的范围由[0~
1]映射到[0~255](注意:原图像素值必须要归一化)
可以发现,16F是非法的,因此 需要将其转化为32F或者64F,如以下代码中的第4行所示(转成了64F)
v = cv.filter2D(img_i, -1, G_x) h = cv.filter2D(img_i, -1, G_y) img = np.sqrt(v
**2 + h**2) img = img.astype(float) # 此处省略阈值处理 cv.namedWindow("Image_Sobel", cv.
WINDOW_NORMAL) cv.imshow("Image_Sobel", img) cv.waitKey(0) cv.destroyAllWindows(
)

至此,已经不会报错了,但是图像经过阈值化处理,输出是全黑的,开方应该是没有问题的,猜测是cv.filter2D的问题。直接说结论,cv.filter2D函数的第二个参数是ddepth,英文是
desired
depth,即期望深度,值为-1说明输出的数据类型和输入相同,问题就出在这,输入的图像是uint8的,所以原本卷积之后是负值的全被抹掉了,后面第三行平方相加也会溢出,,,所以应该把ddepth设为CV_32F,ddepth取值表如下所示(来自官方文档)

最终的代码:
v = cv.filter2D(img_i, cv.CV_32F, G_x) h = cv.filter2D(img_i, cv.CV_32F, G_y)
img= np.sqrt(v**2 + h**2) # 此处省略阈值处理 cv.namedWindow("Image_Sobel", cv.
WINDOW_NORMAL) cv.imshow("Image_Sobel", img) cv.waitKey(0) cv.destroyAllWindows(
)
最后的输出的图像:

技术
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:766591547
关注微信