2015-02-08 53 views
0

我試圖實現一個簡單的2D卷積(在這種情況下的平均濾波器)。但是當我將我的結果與opencv的filter2D函數生成的圖像進行比較時,我發現很多不同之處。我當前的代碼是:二維卷積 - 與opencv的輸出相比錯誤的結果

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; 
} 

的五個核尺寸的結果是(1 OpenCV的,我2執行):

1. image opencv, 2. my results

我將不勝感激,如果有人可以給我解釋一下什麼我做錯了。

+0

您可能應該在'if'中使用'&&'而不是'||'。 – SleuthEye 2015-02-08 00:54:27

+0

對我來說似乎很合理,但這並不影響內部圖像區域中缺失的細節和人工製品。 – 2015-02-08 00:59:36

+0

人工製品很可能是由於飽和度過高造成的。嘗試限制值的範圍,使其不超過uint8_t(255)的最大值。此外,每次將部分結果投影到'sum'的'uint8_t'時,您可能會失去分辨率。考慮用float計算總和,並且限制結果。 – SleuthEye 2015-02-08 01:04:30

回答

1

用於起動器,你的情況考慮邊緣應使用&&代替||像這樣:

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

這應該有點幫助去除邊緣周圍的文物。

然後,在內部區域的文物,你應該確保總和停留在0-255的範圍內,並儘量避免每次投的部分結果回uint8_t時間失去分辨率分配給sum

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);