3

我正在自学边缘检测器,我正在尝试使用 OpenCVfilter2D来实现我自己的梯度计算器,类似于cv2.Sobel(). 在 OpenCV 的 Python 接口中,cv2.filter2D()允许用户使用自定义过滤器对图像进行卷积。在 OpenCV 命名法中,此过滤器称为“内核”。

使用来自MIT 行人数据集的图像( per00001.png),我发现它产生了一个看起来合理的输出。(代码在下面,输出图像在这里。)cv2.Sobel()

#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)

↑ 好


↓ 坏了

当我尝试实现自己的Sobel()类似代码(如下)时,我得到一个全黑图像。我推测问题出在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)

所以,这是我的问题:

cv2.filter2D(..., kernel, ...)1) 参数期望什么数据类型kernel

2)如果这里的数据类型kernel不是问题,那么是什么导致我的自定义 Sobel 代码输出空白图像?

4

2 回答 2

4

卷积核的系数应始终为浮点数。这意味着您应该在分配该矩阵时使用 CV_32FC1。在此特定示例中,请尝试:

horizontalSobelMtx = [[-1,0,1],[-2,0,2],[-1,0,1]]
horizontalSobelMtx = numpy.asanyarray(horizontalSobelMtx, np.float32)
于 2013-08-26T23:32:20.393 回答
1

我有同样的问题,但我相信我有部分答案。基本上,您需要对内核进行加权。过滤器算法的工作方式是将您的过滤器相乘,然后将所有值相加并将它们用作新值。关键是添加部分。添加 8 个不同的值(一些是负的,一些是正的)通常会产生一个很大的数字,并且显示为黑色(或者在我的情况下,全白)。所以你必须补偿加法。将内核中的所有值除以内核的大小/面积。请参阅此处的示例并注意该行

  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 附近摆弄酒吧,我的照片“弹出”到视野中。

于 2012-12-20T06:25:12.160 回答