2017-01-30 227 views
2

我注意到C++中filter2D的OpenCV實現與相應內核的直接實現之間的差異。我已閱讀了以下問題:filter2D OpenCV函數C++

Opencv - how does the filter2D() method actually work?

這個問題,筆者曾試圖讓filter2D功能的工作落實。他聲稱使用規範化版本的過濾器會產生正確的結果。我測試了他的假設,發現只有當所有係數都是正數時,歸一化才能給出正確的答案。因此,使用filter2D函數可以成功實現平均濾波器[我們必須對內核進行規格化]。

但是,對於具有負係數的濾波器,例如Sobel,Laplacian和任何邊緣檢測濾波器,情況並非如此。這個問題的作者遇到了和我一樣的問題。

https://stackoverflow.com/users/2669614/bovaz

上面提到的用戶回答的鏈接的問題。他聲稱,如果內核的係數總和等於零,filter2D可能會修改它的實現。是這樣嗎?爲什麼在C +中實現filter2D會給直接實現帶來不同的結果?我已經在Python中檢查了filter2D,並且直接在C++中實現相應的內核,結果相同。

回答

0

這主要是因爲縮放和溢出問題。 filter2D的文檔沒有提及(至少我沒有找到)溢出值是否被剪切或適當縮放到最小 - 最大範圍。 這對於方向濾波器更爲重要,其中係數爲正數和負數,代數後 上面的鏈接中顯示的函數'myfilter2D'沒有縮放到最小最大範圍,應該是這種情況。

如果您可以發佈示例代碼,那麼它會更容易幫助。

我的建議是將矩陣轉換爲浮點數(並進行縮放)並執行代數運算,因爲這往往會保留結果值並且值不會由於溢出或飽和而丟失。 im2double() - >「執行代數運算」 - > im2uchar()用於顯示

void im2uchar(Mat & src, Mat & dest){ 
    double minVal, maxVal; 
    minMaxLoc(src, &minVal, &maxVal); //find minimum and maximum intensities 
    src.convertTo(dest, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal)); 
    } 

void im2float(Mat & src, Mat & dest){ 
    double minVal, maxVal; 
    minMaxLoc(src, &minVal, &maxVal); //find minimum and maximum intensities 
    src.convertTo(dest, CV_32F, 1.0/(maxVal - minVal), -minVal * 1.0/(maxVal - minVal)); 
    }