手动实现OpenCV Sobel功能

时间:2014-08-19 20:20:55

标签: c++ opencv image-processing

My image

如果我有图像并用

调用OpenCV Sobel功能
Sobel(Img,gradX,CV_16S,1,0,3);
convertScaleAbs(gradX,absGradX);
imshow("Gradient Image",absGradX);

我得到一个漂亮的渐变图像

我想使用带有自定义内核的filter2D来计算我的x渐变。我的索贝尔内核是 1 0 -1 2 0 -2 1 0 -1 现在,当我尝试这个时,我只得到一张全黑的图像

float  xVals[9] = {.125,0,-.125,.25,0,-.25,.125,0,-.125};
Mat xKernel = Mat(3,3,CV_32F,xVals);
Mat gradXManual,absGradXManual;
filter2D(Img,gradXManual,-1,xKernel,Point(-1,-1),0,BORDER_DEFAULT);
convertScaleAbs(gradXManual,absGradXManual);
imshow("Manual Gradient",absGradXManual);

生成的渐变图像全黑。我有什么想法,我做错了什么? 感谢

1 个答案:

答案 0 :(得分:2)

我实际上从您创建的自定义内核中获得了输出。我使用Python OpenCV来做到这一点,但是在OpenCV中调用函数的方式几乎是一样的。要自包含,这是我使用Sobel和您的自定义内核为您的图像调用的Python代码:

import cv2
import numpy as np
im = cv2.imread('Nj9fM.png'); #// Save image to computer first

#// Call using built-in Sobel
out1 = cv2.Sobel(im, cv2.CV_16S, 0, 1, 3)
out1 = cv2.convertScaleAbs(out1.copy())

#// Create custom kernel
xVals = np.array([0.125,0,-0.125,0.25,0,-0.25,0.125,0,-0.125]).reshape(3,3)

#// Call filter2D
out2 = cv2.filter2D(im, cv2.CV_32F, xVals, None, (-1,-1), 0, cv2.BORDER_DEFAULT)
out2 = cv2.convertScaleAbs(out2.copy())

cv2.imshow('Output 1', out1)
cv2.imshow('Output 2', out2)
cv2.waitKey(0)
cv2.destroyAllWindows()

如果您运行此代码,您实际上会看到两个图像,其中第一个使用内置Sobel,而另一个使用您的自定义内核。我在Sobel实现与渐变之间看到的主要区别在于,您通过将每个元素除以8来获取Sobel内核。因此,您检测到的任何渐变,您都会得到对比度降低,这就是我所看到的。实际上,您基本上是采用渐变结果并除以8,因此您将输出强度降低了8倍。尝试执行:float xVals2[9] = {1f,0f,-1f,2f,0f,-2f,1f,0f,-1f};实际的Sobel内核,然后再次运行代码。你应该看到对比度更高的提升。对于Python,这将是:

xVals2 = np.array([1.,0.,-1.,2.,0,-2.,1.,0,-1.]).reshape(3,3)

如果使用此内核运行代码,您会发现对比度更高。你会发现有更多的噪音,因为渐变值更大。