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