2016-08-01 87 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的算法(频域中)执行卷积,因此您可能会得到稍微不同的结果和计时。