高斯濾波


高斯濾波

一、目的與原理

(1)目的:用於消除高斯噪聲;

(2)原理:高斯噪聲的特點是噪聲分布服從正態分布,要消除這樣分布的噪聲那么處理的方法也需要有正態分布的思想,即對於圖像而言,着重於處理圖像中心,其次再稍微處理邊緣,因為正態分布的特點是中間部分多,外側比較少。所以卷積核的設計思路是中間點的權值最大,越靠近中間點的權值越大。

 

公式①:

 是一個常數,由於我們最終需要對高斯模板歸一化,而常數不影響數值比例,所以可以忽略掉。我們實際要計算的部分是:

 

 

 

 

 

 

高斯濾波的步驟:

假定中心點的坐標是(0,0),那么距離它最近的8個點的坐標如下:

y軸水平向上,x軸水平向右。

 

根據二維高斯函數:,設定 的值,假設其=1.5可得權重矩陣:

 

 

 

歸一化:

 

 

 

 

假設有九個點,灰度值如下圖:

 

 

 

 

每個點乘以權重后的結果:

 

 

 

 

可得:

 這九個點的累加就是中心點的高斯模糊值。

 

 

二、算法步驟

(1)建立坐標系關系

(2)根據高斯函數計算出坐標矩陣的值

(3)對矩陣的值歸一化

(4)卷積求和獲得輸出圖像的灰度值

(5)將結果賦值到輸出圖像

(6)顯示圖像

 

三、偽代碼

輸入:卷積核大小wsize,高斯函數的sigma

輸出:高斯模板Mask

void generateGaussMask(cv::Mat& Mask, cv::Size wsize, double sigma)

{

       for(循環處理點,生成各個坐標點){

              根據高斯函數算出坐標點對應的值

              對上一步的值歸一化

              生成高斯模板Mask

  }  

}

 

輸入:原圖src,高斯模板Mask

輸出:結果圖dst

void GaussianFilter(cv::Mat& src, cv::Mat& dst, cv::Mat Mask)

{

       for(循環處理原圖src像素點){

              if(圖片為單通道){

      根據高斯模板Mask卷積求核獲得輸出圖像的灰度值

      將灰度值賦值到輸出圖像中

    }

              if(圖片為多通道){

      根據通道數,用高斯模板Mask卷積求核獲得輸出圖像的各個通道的值

      將各個通道值賦值到輸出圖像中

    }     

  }

}

 

四、源碼:

// 按二維高斯函數實現高斯濾波

void GaussianFilter(cv::Mat& src, cv::Mat& dst, cv::Mat kernel) {

    int hh = (kernel.rows - 1) / 2;

    int hw = (kernel.cols - 1) / 2;

    dst = cv::Mat::zeros(src.size(), src.type());

    //邊界填充

    cv::Mat Newsrc;

    cv::copyMakeBorder(src, Newsrc,hh, hh, hw, hw, cv::BORDER_REPLICATE);//邊界復制

 

    //高斯濾波

    for (int i = hh; i < src.rows + hh; ++i) {

        for (int j = hw; j < src.cols + hw; ++j) {

            double sum[3] = { 0 };

 

            for (int r = -hh; r <= hh; ++r) {

                for (int c = -hw; c <= hw; ++c) {

                    if (src.channels() == 1) {

                        sum[0] = sum[0] + Newsrc.at<uchar>(i + r, j + c) * kernel.at<double>(r + hh, c + hw);

                    }

                    else if (src.channels() == 3) {

                        cv::Vec3b rgb = Newsrc.at<cv::Vec3b>(i + r, j + c);

                        sum[0] = sum[0] + rgb[0] * kernel.at<double>(r + hh, c + hw);//B

                        sum[1] = sum[1] + rgb[1] * kernel.at<double>(r + hh, c + hw);//G

                        sum[2] = sum[2] + rgb[2] * kernel.at<double>(r + hh, c + hw);//R

                    }

                }

            }

 

            for (int k = 0; k < src.channels(); ++k) {

                if (sum[k] < 0)

                    sum[k] = 0;

                else if (sum[k] > 255)

                    sum[k] = 255;

            }

            if (src.channels() == 1)

            {

                dst.at<uchar>(i - hh, j - hw) = static_cast<uchar>(sum[0]);

            }

            else if (src.channels() == 3)

            {

                cv::Vec3b rgb = { static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2]) };

                dst.at<cv::Vec3b>(i - hh, j - hw) = rgb;

            }

 

        }

    }

}

// x,y方向聯合實現獲取高斯模板

void generateGaussMask(cv::Mat& Mask, cv::Size wsize, double sigma) {

    Mask.create(wsize, CV_64F);

    int h = wsize.height;

    int w = wsize.width;

    int center_h = (h - 1) / 2;

    int center_w = (w - 1) / 2;

    double sum = 0.0;

    double x, y;

    for (int i = 0; i < h; ++i) {

        y = pow(i - center_h, 2);

        for (int j = 0; j < w; ++j) {

            x = pow(j - center_w, 2);

            //因為最后都要歸一化的,常數部分可以不計算,也減少了運算量

            double g = exp(-(x + y) / (2 * sigma*sigma));

            Mask.at<double>(i, j) = g;

            sum += g;

        }

    }

    Mask = Mask / sum;

}

 

 

六、結果圖

高斯模板:

 

 

 

原圖、Opencv高斯函數處理結果、自定義高斯函數處理結果、原圖+噪聲、做差求算法區別:

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM