我正在自学边缘探测器,我正在尝试使用OpenCV的filter2D
来实现我自己的渐变计算器,类似于cv2.Sobel()
。在OpenCV的Python界面中,cv2.filter2D()
允许用户使用自定义过滤器卷积图像。在OpenCV命名法中,此过滤器称为“内核”。
使用per00001.png中的图片(MIT pedestrian dataset),我发现cv2.Sobel()
会产生合理的输出效果。 (代码如下,output image is here。)
#OpenCV's Sobel code (outputs nice-looking gradient)
import cv2, numpy
img = cv2.imread("./per00001.png")
gradientX = cv2.Sobel(img, -1, 1, 0)
compression_params = [cv2.cv.CV_IMWRITE_PNG_COMPRESSION, 9]
cv2.imwrite("gradientX.png", gradientX, compression_params)
↑GOOD
↓BROKEN
当我尝试实现自己的Sobel()
代码(如下)时,我得到all-black image。我猜测问题是我传入horizontalSobelMtx
的内核参数(cv2.filter2D()
)的数据类型。但是,我无法找到有关cv2.filter2D()
的内核数据类型的任何文档。
#Custom Sobel code (outputs all-black image)
import cv2, numpy
img = cv2.imread("./per00001.png")
horizontalSobelMtx = [[-1,0,1],[-2,0,2],[-1,0,1]]
horizontalSobelMtx = numpy.asanyarray(horizontalSobelMtx) #guessing about appropriate datatype.
gradientX_customSobel = cv2.filter2D(img, -1, horizontalSobelMtx)
compression_params = [cv2.cv.CV_IMWRITE_PNG_COMPRESSION, 9]
cv2.imwrite("gradientX_customSobel.png", gradientX_customSobel, compression_params)
所以,这是我的问题:
1)cv2.filter2D(..., kernel, ...)
参数kernel
期望的数据类型是什么?
2)如果kernel
的数据类型不是问题,那么是什么导致我的自定义Sobel代码输出空白图像?
答案 0 :(得分:3)
卷积核的系数应该总是浮动的 - 点数。这意味着在分配该矩阵时应该使用CV_32FC1。 在此特定示例中,请尝试:
horizontalSobelMtx = [[-1,0,1],[-2,0,2],[-1,0,1]]
horizontalSobelMtx = numpy.asanyarray(horizontalSobelMtx, np.float32)
答案 1 :(得分:1)
我有同样的问题,但我相信我有一个部分答案。基本上,你需要加权你的内核。过滤器算法的工作方式是使用过滤器,将其相乘,然后将所有值相加并将它们用作新值。关键是ADDING部分。添加8个不同的值(一些是负的,一些是正的)通常会导致大量的,并且显示为黑色(或者在我的情况下,全部为白色)。 所以你必须补偿增加。将内核中的所有值除以内核的大小/区域。请参阅示例here并注意
行 kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
他们通过kernel_size平方来划分所有内容。
我自己,我做了这件事,它有所帮助(显示的东西),但它已被淘汰,所以我通过将其添加到我的代码中找到了我的完美体重:
int d2weight = 1;
//... start loop, make your Mat kernel
kernel = kernel / d2weight; //put right before your filter2d() call
createTrackbar("kernel", "kernel", &d2weight, 255, NULL);
并摆弄了酒吧,右边是d2weight = 140我的照片'弹出'进入视野。