【问题标题】:Difference of cv::filter2D and self-contained convolution on Gabor filterGabor 滤波器上 cv::filter2D 和自包含卷积的区别
【发布时间】:2016-12-06 15:33:16
【问题描述】:

由于某种原因,我必须自己编写过滤器功能。以下是我的卷积函数。

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函数比较,过滤后发现它们是不同的。当 theta 和 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();
}

对自包含卷积有什么建议吗?零填充部分被忽略。

【问题讨论】:

  • “由于某种原因”:D

标签: image algorithm matlab opencv image-processing


【解决方案1】:

您在卷积实现中以浮点矩阵的形式访问内核,但它由双精度数组成(ksize 默认设置为 CV_64F,根据 doc)。看起来 OpenCV 足够聪明,可以在具有不同元素类型的矩阵的卷积过程中检测到它并自行执行转换/正确的内存访问,这就是它产生正确结果的原因。

为了修复你的 sn-p 我添加了一行

kernel.convertTo(kernel, CV_32F);

这会产生视觉上等效的结果(直到填充)。

另一种选择是将ktype 显式设置为CV_32F

此外,当使用大内核(~11x11 和更大)时,OpenCV 的 filter2D 实现使用基于 DFT 的算法(在频域中)执行卷积,因此您可能会得到略有不同的结果和时序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 2019-08-30
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    相关资源
    最近更新 更多