簡體   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