如果我有图像并使用以下命令调用OpenCV Sobel函数

Sobel(Img,gradX,CV_16S,1,0,3);
convertScaleAbs(gradX,absGradX);
imshow("Gradient Image",absGradX);

我得到一个不错的渐变图像

我想将filter2D与自定义内核一起使用来计算x梯度。我的sobel内核是
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);

所得的渐变图像全为黑色。有什么想法我做错了吗?
谢谢

最佳答案

我实际上从您创建的自定义内核中获得了输出。我使用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()

就C++而言:
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char* argv[])
{
    Mat im = imread("Nj9fM.png", CV_LOAD_IMAGE_COLOR); // Save image to computer first

    // Call using built-in Sobel
    Mat out1, out2;
    Sobel(img, out1, CV_16S, 1, 0, 3);
    convertScaleAbs(out1, out2);

    // Create custom kernel
    Mat xVals = Mat_<float>(3, 3) << 0.125, 0, -0.125, 0.25, 0, -0.25, 0.125, 0, -0.125;

    // Call filter2D
    filter2D(im, out2, -1, xVals, Point(-1,-1), 0 ,BORDER_DEFAULT);
    convertScaleAbs(out2, out2);

    imshow("Output 1", out1);
    imshow("Output 2", out1);
    waitKey(0);
    destroyWindow("Output 1");
    destroyWindow("Output 2");
}

如果运行此代码,则实际上会看到两个图像,其中第一个使用内置的Sobel,而另一个使用您的自定义内核。我看到的Sobel实现和渐变之间的主要区别在于,您将Sobel内核除以8就是每个元素。这样,您检测到的任何渐变都会使对比度降低,这就是我所看到的。实际上,您基本上是将梯度结果除以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)

同样在C++中:
Mat xVals2 = Mat_<float>(3, 3) << 1f, 0f, -1f, 2f, 0f, -2f, 1f, 0f, -1f;

如果使用此内核运行代码,则会发现对比度更高。您会发现,随着梯度值的增加,会有更多的噪音。

关于python - 手动执行OpenCV Sobel功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25392314/

10-12 22:45