日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

图像降噪算法——非局部均值降噪算法

發(fā)布時(shí)間:2025/3/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图像降噪算法——非局部均值降噪算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

圖像降噪算法——非局部均值降噪算法

  • 圖像降噪算法——非局部均值降噪算法
    • 1. 基本原理
    • 2. C++代碼實(shí)現(xiàn)
    • 3. 結(jié)論

圖像降噪算法——非局部均值降噪算法

1. 基本原理

非局部均值降噪算法(Non-Local Means)是空間降噪算法的一種,和中值濾波、高斯濾波這些局部濾波算法不同的是,非局部均值降噪算法是一種全局的算法,思路是利用整幅圖像中相似像素的灰度值來(lái)代替當(dāng)前像素的灰度值u^i(p)=1C(p)∑q∈B(p,r)ui(q)w(p,q)\hat{u}_{i}(p)=\frac{1}{C(p)} \sum_{q \in B(p, r)} u_{i}(q) w(p, q)u^i?(p)=C(p)1?qB(p,r)?ui?(q)w(p,q)其中,ui(q)u_{i}(q)ui?(q)是噪聲圖像像素qqq的灰度值;u^i(p)\hat{u}_{i}(p)u^i?(p)是降噪后圖像像素ppp的灰度值;w(p,q)w(p, q)w(p,q)是像素pppqqq之間的權(quán)重;B(p,r)B(p, r)B(p,r)為噪聲圖像中,以像素ppp為中心,寬為2r+12r+12r+1的區(qū)域,C(p)C(p)C(p)為權(quán)重歸一化系數(shù),計(jì)算公式為:C(p)=∑q∈B(p,r)w(p,q)C(p)=\sum_{q \in B(p, r)} w(p, q)C(p)=qB(p,r)?w(p,q)

公式很好理解,中間比較重要的就是權(quán)重如何設(shè)計(jì),權(quán)重需要描述兩個(gè)像素之間的相似度,而這個(gè)相似度通常是通過(guò)這兩個(gè)像素鄰域像素間的歐拉距離來(lái)描述:d2(B(p,f),B(q,f))=13(2f+1)2∑i=13∑j∈B(0,Ω)(ui(p+j)?ui(q+j))2d^{2}(B(p, f), B(q, f))=\frac{1}{3(2 f+1)^{2}} \sum_{i=1}^{3} \sum_{j \in B(0, \Omega)}\left(u_{i}(p+j)-u_{i}(q+j)\right)^{2}d2(B(p,f),B(q,f))=3(2f+1)21?i=13?jB(0,Ω)?(ui?(p+j)?ui?(q+j))2其中,333次求和是對(duì)于彩色圖而言的,B(p,f)B(p, f)B(p,f)為噪聲圖像中,以像素ppp為中心,寬為2f+12f+12f+1的區(qū)域,在這個(gè)基礎(chǔ)上,添加指數(shù)核函數(shù)來(lái)計(jì)算權(quán)值:w(p,q)=e?max?(d2?2σ2,0,0)h2w(p, q)=e^{-\frac{\max \left(d^{2}-2 \sigma^{2}, 0,0\right)}{h^{2}}}w(p,q)=e?h2max(d2?2σ2,0,0)?其中,σ\sigmaσhhh是我們?nèi)藶樵O(shè)定的參數(shù),以上就完成了非局部均值降噪算法的理論介紹。

2. C++代碼實(shí)現(xiàn)

這里我基于OpenCV完成了兩份代碼,其中第一份是我根據(jù)上面公式自己實(shí)現(xiàn),比較容易理解,但是運(yùn)行速度較慢。因?yàn)樘?#xff0c;所以我嘗試寫了第二份代碼。第二份是參考他人的代碼基于Mat指針實(shí)現(xiàn)的,因?yàn)槭侵羔槻僮?#xff0c;所以運(yùn)行速度會(huì)相對(duì)較快。

第一份代碼

Mat Denoise::NonLocalMeansFilter(const Mat &src, int searchWindowSize, int templateWindowSize, double sigma, double h) {Mat dst, pad;dst = Mat::zeros(src.rows, src.cols, CV_8UC1);//構(gòu)建邊界int padSize = (searchWindowSize+templateWindowSize)/2;copyMakeBorder(src, pad, padSize, padSize, padSize, padSize, cv::BORDER_CONSTANT);int tN = templateWindowSize*templateWindowSize;int sN = searchWindowSize*searchWindowSize;vector<double> gaussian(256*256, 0);for(int i = 0; i<256*256; i++){double g = exp(-max(i-2.0*sigma*sigma, 0.0))/(h*h);gaussian[i] = g;if(g<0.001)break;}//遍歷圖像上每一個(gè)像素for(int i = 0; i<src.rows; i++){for(int j = 0; j<src.cols; j++){cout<<i<<" "<<j<<endl;//遍歷搜索區(qū)域每一個(gè)像素int pX = i+searchWindowSize/2;int pY = j+searchWindowSize/2;vector<vector<double>> weight(searchWindowSize, vector<double>(searchWindowSize, 0));double weightSum = 0;for(int m = searchWindowSize-1; m>=0; m--){for(int n = searchWindowSize-1; n>=0; n--){int qX = i+m;int qY = j+n;int w = 0;for(int x = templateWindowSize-1; x>=0; x--){for(int y = templateWindowSize-1; y>=0; y--){w += pow(pad.at<uchar>(pX+x, pY+y) - pad.at<uchar>(qX+x, qY+y), 2);}}weight[m][n] = gaussian[(int)(w/tN)];weightSum += weight[m][n];}}dst.at<uchar>(i,j) = 0;double sum = 0;for(int m = 0; m<searchWindowSize; m++){for(int n = 0; n<searchWindowSize; n++){sum += pad.at<uchar>(i+templateWindowSize/2+m, j+templateWindowSize/2+n)*weight[m][n];}}dst.at<uchar>(i,j) = (uchar)(sum/weightSum);}}return dst; }

第二份代碼

Mat Denoise::NonLocalMeansFilter2(const Mat &src, int searchWindowSize, int templateWindowSize, double sigma, double h) {Mat dst, pad;dst = Mat::zeros(src.rows, src.cols, CV_8UC1);//構(gòu)建邊界int padSize = (searchWindowSize+templateWindowSize)/2;copyMakeBorder(src, pad, padSize, padSize, padSize, padSize, cv::BORDER_CONSTANT);int tN = templateWindowSize*templateWindowSize;int sN = searchWindowSize*searchWindowSize;int tR = templateWindowSize/2;int sR = searchWindowSize/2;vector<double> gaussian(256*256, 0);for(int i = 0; i<256*256; i++){double g = exp(-max(i-2.0*sigma*sigma, 0.0))/(h*h);gaussian[i] = g;if(g<0.001)break;}double* pGaussian = &gaussian[0];const int searchWindowStep = (int)pad.step - searchWindowSize;const int templateWindowStep = (int)pad.step - templateWindowSize;for(int i = 0; i < src.rows; i++){uchar* pDst = dst.ptr(i);for(int j = 0; j < src.cols; j++){cout<<i<<" "<<j<<endl;int *pVariance = new int[sN];double *pWeight = new double[sN];int cnt = sN-1;double weightSum = 0;uchar* pCenter = pad.data + pad.step * (sR + i) + (sR + j);//搜索區(qū)域中心指針uchar* pUpLeft = pad.data + pad.step * i + j;//搜索區(qū)域左上角指針for(int m = searchWindowSize; m>0; m--){uchar* pDownLeft = pUpLeft + pad.step * m;for(int n = searchWindowSize; n>0; n--){uchar* pC = pCenter;uchar* pD = pDownLeft + n;int w = 0;for(int k = templateWindowSize; k>0; k--){for(int l = templateWindowSize; l>0; l--){w += (*pC - *pD)*(*pC - *pD);pC++;pD++;}pC += templateWindowStep;pD += templateWindowStep;}w = (int)(w/tN);pVariance[cnt--] = w;weightSum += pGaussian[w];}}for(int m = 0; m<sN; m++){pWeight[m] = pGaussian[pVariance[m]]/weightSum;}double tmp = 0.0;uchar* pOrigin = pad.data + pad.step * (tR + i) + (tR + j);for(int m = searchWindowSize, cnt = 0; m>0; m--){for(int n = searchWindowSize; n>0; n--){tmp += *(pOrigin++) * pWeight[cnt++];}pOrigin += searchWindowStep;}*(pDst++) = (uchar)tmp;delete pWeight;delete pVariance;}}return dst; }

下面是輸出結(jié)果
首先是原圖:

添加高斯噪聲后:

通過(guò)非局部均值降噪算法降噪效果:

可以看出這個(gè)效果還是非常感人的

3. 結(jié)論

  • 可以看到非局部均值降噪算法的效果視覺上是非常可以接受的,但是它的缺點(diǎn)是時(shí)間復(fù)雜度太高,可以清楚看到程序里面有六個(gè)for循環(huán),當(dāng)我把搜索尺寸設(shè)為21,模板尺寸設(shè)為7是:
    第一份代碼運(yùn)行時(shí)間:135.034秒
    第二份代碼運(yùn)行時(shí)間:29.6425秒
    OpenCV庫(kù)函數(shù)運(yùn)行時(shí)間:0.512942秒
    通過(guò)對(duì)比可以發(fā)現(xiàn),Mat通過(guò)at函數(shù)操作速度要慢于指針操作,而我寫的指針操作的代碼要遠(yuǎn)慢于OpenCV庫(kù)函數(shù),OpenCV中的庫(kù)函數(shù)應(yīng)該是采用多線程操作。
  • 2014年有一篇paper講的是通過(guò)積分圖的方式優(yōu)化NLM,我對(duì)其進(jìn)行的C++代碼實(shí)現(xiàn),單線程下速度能提高到7秒左右,同時(shí)我也簡(jiǎn)單讀了下OpenCV的原理,同樣是使用了空間換時(shí)間的思想,不過(guò)相對(duì)積分圖的方式會(huì)更加巧妙,值得進(jìn)一步學(xué)習(xí)。
  • 此外,這里我寫一個(gè)各種算法的總結(jié)目錄圖像降噪算法——圖像降噪算法總結(jié),對(duì)圖像降噪算法感興趣的同學(xué)歡迎參考

    總結(jié)

    以上是生活随笔為你收集整理的图像降噪算法——非局部均值降噪算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。