2016-08-01 50 views
0

由於某些原因,我必須自己編寫濾波器函數。以下是我的卷積函數。cv :: filter2D和Gabor濾波器上獨立卷積的差別

void Convolve (cv::Mat& f, cv::Mat& w, cv::Mat& output) 
{ 
    output = f.clone(); 

    int height = f.rows; 
    int width = f.cols; 
    int a = (w.rows - 1)/2; 
    int b = (w.cols- 1)/2; 

    cv::Mat f2 = f.clone(); 

    for (int x = a; x < height - a; ++x) 
    { 
    for (int y = b; y < width - b; ++y) 
    { 
     float sum = 0.0; 
     for (int s = -a; s <= a; ++s) 
     { 
     for (int t = -b; t <= b; ++t) 
     { 
      sum += w.at<float>(s+a, t+b) * f2.at<float>(x+s, y+t); 
     } 
     } 
     output.at<float>(x, y) = sum; 
    } 
    } 
} 

然後我用這個函數和cv :: filter2D函數進行比較,發現它們在過濾之後是不同的。當θ和psi爲零而沒有其他時,過濾後的圖像幾乎相同。

int main() 
{ 
    cv::Mat in = cv::imread("something.jpg", 0); 
    cv::Mat dest, dest1; 
    cv::Mat src_f; 
    in.convertTo(src_f, CV_32F); 

    int kernel_size = 31; 
    double sig = 1.0, th = 0.2, lm = 1.0, gm = 0.02, ps = 0.0; 

    cv::Mat kernel = cv::getGaborKernel(cv::Size(kernel_size,kernel_size), sig, th, lm, gm, ps); 

    cv::filter2D(src_f, dest1, CV_32F, kernel); 
    Convolve(src_f, kernel, dest); 

    cv::Mat viz; 
    dest.convertTo(viz, CV_8U, 1.0/255.0); 
    cv::Mat viz1; 
    dest1.convertTo(viz1, CV_8U, 1.0/255.0); 
    imshow("my dest", viz); 
    imshow("k dest", viz1); 
    cv::waitKey(); 
} 

對自包含卷積的任何建議?零填充部分被忽略。

+0

「由於某種原因」:D – GameOfThrows

+0

:D用於學習。 –

回答

0

您可以在卷積實現中以浮點矩陣的形式訪問內核,但它由雙精度組成(根據doc,默認情況下,ksize設置爲CV_64F)。它看起來像OpenCV足夠聰明地檢測它,並在不同元素類型的矩陣卷積過程中自己執行轉換/正確的內存訪問,這就是爲什麼它產生正確的結果。

爲了固定您的代碼段我添加了一行

kernel.convertTo(kernel, CV_32F); 

這產生了視覺上相同的結果(最高填充)。

另一種選擇是明確地將ktype設置爲CV_32F。另外,當使用大內核(~11x11或更大)工作時,OpenCV的filter2D實現使用基於DFT的算法(頻域中)執行卷積,因此您可能會得到稍微不同的結果和計時。