在C++

2016-05-30 6 views
1

如果我使用scipy.ndimage.filters.convole在Python應用索貝爾過濾器的圖像,我得到有意義的結果應用內核與OpenCV的,例如,對於這個簡單的輸入圖像img在C++

0 255 0 
0 255 0 
0 255 0 

卷積

dimage.filters.convolve(img, Kx) 

Kx

-1 0 1 
-2 0 2 
-1 0 1 

返回MEA在X方向ningful梯度:

-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 

似乎有一個n溢出問題,但我不知道爲什麼。試圖從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是不是應該對圖像進行二維卷積,爲什麼當用<double>尋址輸出像素時會出現奇怪的值?謝謝。

+0

'CV_32F'是一個'float'。 – beaker

+0

@beaker謝謝,我把它改成浮動..現在把它打印出零矩陣... – TheWaveLad

+0

現在看起來你遇到了邊界類型的問題。我會在一秒內發佈答案。 – beaker

回答

4

好,這與修正的類型代碼(我還添加了多個參數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] 

如果你看看頂部在filtering的文檔頁面上,您將看到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]