繁体   English   中英

在C ++中通过OpenCV应用内核

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM