2D 卷积 - 与 opencv 的输出相比,结果错误

Posted

技术标签:

【中文标题】2D 卷积 - 与 opencv 的输出相比,结果错误【英文标题】:2D convolution - wrong results compared to opencv's output 【发布时间】:2015-02-08 00:43:43 【问题描述】:

我正在尝试实现一个简单的 2D 卷积(在这种情况下为均值滤波器)。但是当我将我的结果与 opencv 的 filter2D 函数生成的图像进行比较时,我发现了很多差异。我当前的代码是:

cv::Mat filter2D(cv::Mat& image, uint32_t kernelSize = 3)

    float divider = kernelSize*kernelSize;
    cv::Mat kernel = cv::Mat::ones(kernelSize,kernelSize,CV_32F) / divider;

    int kHalf = kernelSize/2.f;
    cv::Mat smoothedImage = cv::Mat::ones(image.rows,image.cols,image.type());

    for (int32_t y = 0; y<image.rows; ++y) 
    for (int32_t x = 0; x<image.cols; ++x) 
        uint8_t sum = 0;
        for (int m = -kHalf; m <= kHalf; ++m) 
        for (int n = -kHalf; n <= kHalf; ++n) 
            if (x+n >= 0 || x+n <= image.cols || y+m >= 0 || y <= image.rows) 
                sum += kernel.at<float>(m+kHalf, n+kHalf)*image.at<uint8_t>(y-m+1, x-n+1);
             else 
                // Zero padding - nothing to do
            
        
        
        smoothedImage.at<uint8_t>(y,x) = sum;
    
    
    return smoothedImage;

内核大小为 5 的结果是(1.opencv,2.我的实现):

如果有人能解释我做错了什么,我将不胜感激。

【问题讨论】:

您可能应该在您的if 中使用&amp;&amp; 而不是|| 对我来说似乎是合理的,但这并不影响内部图像区域中缺失的细节和伪影。 伪影很可能是由于过饱和造成的。尝试限制值的范围,使其不超过 uint8_t (255) 的最大值。此外,每次将部分结果转换为uint8_tsum 时,您可能都会失去分辨率。考虑用浮点数计算总和,并限制结果。 这正是解决方案。感谢您指出这一点。 【参考方案1】:

首先,考虑边缘的条件应使用&amp;&amp; 而不是||,如下所示:

if (x+n >= 0 && x+n <= image.cols && y+m >= 0 && y <= image.rows)

这应该有助于去除边缘周围的伪影。

然后,对于内部区域的伪影,您应该确保总和保持在 0-255 范围内,并尽量避免每次将部分结果转换回 uint8_t 时失去分辨率,因为您分配给 @ 987654325@:

float sum = 0;
for (int m = -kHalf; m <= kHalf; ++m) 
  for (int n = -kHalf; n <= kHalf; ++n) 
    if (x+n >= 0 && x+n <= image.cols && y+m >= 0 && y <= image.rows) 
      sum += kernel.at<float>(m+kHalf, n+kHalf)*image.at<uint8_t>(y-m+1, x-n+1);
     else 
      // Zero padding - nothing to do
    
  

smoothedImage.at<uint8_t>(y,x) = std::min(std::max(0.0f, sum), 255.0f);

【讨论】:

以上是关于2D 卷积 - 与 opencv 的输出相比,结果错误的主要内容,如果未能解决你的问题,请参考以下文章

卷积处理过程模拟:用Python实现OpenCV函数filter2D等效的卷积功能

OpenCV filter2D和sepFilter2D

opencv filter2D()函数(卷积)计算原理

二维卷积运算tf.conv2d介绍

[OpenCV-Python] OpenCV 中的图像处理 部分 IV (二)

卷积神经网络原理及其C++/Opencv实现