[英]Applying a kernel with OpenCV in C++
如果我使用scipy.ndimage.filters.convole
将Sobel滤镜应用于Python中的图像,例如,对于此简单的输入图像img
,我将获得有意义的结果。
0 255 0
0 255 0
0 255 0
卷积
dimage.filters.convolve(img, Kx)
用Kx
-1 0 1
-2 0 2
-1 0 1
在x方向上返回有意义的渐变:
-1020 0 1020
-1020 0 1020
-1020 0 1020
我不知道如何在C ++中使用openCV2获得等效的结果。 当我通过定义输入图像时
int image_data[9] = {0, 255, 0, 0, 255, 0, 0, 255, 0};
cv::Mat image = cv::Mat(3, 3, CV_32F, image_data);
并通过以下方式应用内核
cv::Mat gradientx;
double sobelx_data[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
cv::Mat sobelx = cv::Mat(3, 3, CV_32F, sobelx_data);
cv::filter2D(image, gradientx, -1, sobelx);
我得到以下结果
for(int row=0; row<gradientx.rows; row++) {
for(int col=0; col<gradientx.cols; col++) {
std::cout << gradientx.at<int>(row,col) << std::endl;
}
}
它返回以下图像
478 -2147482660 478
478 -2147482660 478
478 -2147482660 478
似乎有一个溢出问题,但我不知道为什么。 尝试从gradientx.at<double>(row,col)
获取值会产生
-1.68911e-311 8.10602e-312 8.11663e-312
-1.68911e-311 8.10602e-312 8.11663e-312
-1.68911e-311 2.122e-314 8.54412e-72
有人可以告诉我为什么吗? filter2D
不应该在图像上进行2D卷积吗?为什么用<double>
寻址输出像素时会得到怪异的值? 谢谢。
好的,这是校正了类型的代码(我还向filter2D
添加了更多参数):
float image_data[9] = {0, 255, 0, 0, 255, 0, 0, 255, 0};
cv::Mat image = cv::Mat(3, 3, CV_32F, image_data);
std::cout << "image = " << std::endl << image << std::endl;
cv::Mat gradientx;
float sobelx_data[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
cv::Mat sobelx = cv::Mat(3, 3, CV_32F, sobelx_data);
std::cout << "sobelx = " << std::endl << sobelx << std::endl;
cv::filter2D(image, gradientx, -1, sobelx, cv::Point(-1, -1), 0,
cv::BORDER_DEFAULT);
std::cout << "gradientx = " << std::endl << gradientx << std::endl;
结果是:
image =
[0, 255, 0;
0, 255, 0;
0, 255, 0]
sobelx =
[-1, 0, 1;
-2, 0, 2;
-1, 0, 1]
gradientx =
[0, 0, 0;
0, 0, 0;
0, 0, 0]
如果查看有关过滤的文档页面的顶部,则会看到OpenCV使用的所有边框类型。 默认情况下, filter2D
使用BORDER_REFLECT_101
。 这可能不是我们想要的,所以让我们将其更改为BORDER_REPLICATE
。
cv::filter2D(image, gradientx, -1, sobelx, cv::Point(-1, -1), 0,
cv::BORDER_REPLICATE);
结果:
image =
[0, 255, 0;
0, 255, 0;
0, 255, 0]
sobelx =
[-1, 0, 1;
-2, 0, 2;
-1, 0, 1]
gradientx =
[1020, 0, -1020;
1020, 0, -1020;
1020, 0, -1020]
更好,但是值被翻转了。 如果查看filter2D
的功能描述的底部,您会发现它实际上是在计算互相关而不是卷积。 因此,我们需要翻转内核以获得正确的结果。
cv::Mat sobelxflip;
cv::flip(sobelx, sobelxflip, -1);
cv::filter2D(image, gradientx, -1, sobelxflip, cv::Point(-1, -1), 0,
cv::BORDER_REPLICATE);
std::cout << "gradientx = " << std::endl << gradientx << std::endl;
结果:
gradientx =
[-1020, 0, 1020;
-1020, 0, 1020;
-1020, 0, 1020]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.