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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

(MATLAB/C/Python)快速中值滤波

發(fā)布時間:2023/12/29 python 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (MATLAB/C/Python)快速中值滤波 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

(MATLAB/C/Python)快速中值濾波

  • 一、中值濾波
  • 二、快速中值濾波
      • 介紹
      • 原理
      • 優(yōu)化
  • 三、代碼
      • MATLAB
      • C
      • Python
  • 四、測試
  • 其他

by HPC_ZY

最近一個項(xiàng)目中需要用到中值濾波(不能調(diào)庫),但是核半徑相當(dāng)大,用傳統(tǒng)的方法運(yùn)行速度極慢。因此查閱文獻(xiàn)找到快速中值濾波的方法。寫成三種語言并分享給大家。

一、中值濾波

簡單說就是,就是對某點(diǎn)鄰域內(nèi)所有像素進(jìn)行排序,取序數(shù)在中間的值替代原始值。
這樣做對脈沖噪聲有良好的濾除作用,特別是在濾除噪聲的同時,能夠保護(hù)信號的邊緣,使之不被模糊。

實(shí)現(xiàn)方法
step 1:通過從圖像中的某個采樣窗口取出奇數(shù)個像素進(jìn)行排序
step 2:用排序后的中值取代要處理的像素即可

代碼見后文。

注:本文主要講圖像處理,所有使用 “像素 ” 替代 “ 數(shù)據(jù)”。

二、快速中值濾波

介紹

中值濾波主要耗時就在于對窗口(鄰域)內(nèi)像素進(jìn)行排序,因此針對如何獲取中值進(jìn)行優(yōu)化。

最初——經(jīng)典的中值濾波對窗口內(nèi)所有像素進(jìn)行排序,所以排序算法的選擇就很重要。
接著——但后來有人意識到 “我們只需要中間值”,沒必要將整個序列進(jìn)行排序,因此出現(xiàn)了一些快速搜索數(shù)組中間值的方法。
然后——由于圖像的像素值為0~255的整數(shù),1979年有人就提出了用累積直方圖尋找中值的方法。
最后——人們又在這基礎(chǔ)上不斷改進(jìn)。

本文主要講基于直方圖的快速中值濾波方法


原理

  • 實(shí)現(xiàn)方法
    step 1:統(tǒng)計(jì)N?NN*NN?N窗口內(nèi)像素
    step 2:計(jì)算累積直方圖
    step 3:找到累積直方圖值剛好超過N?N2\frac{N*N}{2}2N?N?時對應(yīng)的灰度值。
    通過一個簡單的例子更直觀的說明。
    這里假設(shè)一個只有8個灰度級的圖像,某個5?55*55?5的窗口內(nèi)值如下,
    [0455534765677763211001100]\begin{bmatrix} 0 &4 &5&5&5 \\ 3 & 4&7&6&5\\6&7&7&7&6\\3&2&1&1&0\\0&1&1&0&0 \end{bmatrix} ???????03630?44721?57711?56710?55600????????
    其統(tǒng)計(jì)直方圖如下表。對于5*5的窗口,中值的序數(shù)為13,所以參照累積直方圖能快速中值為4。
    這里我們可以發(fā)現(xiàn),其實(shí)并不需要算出整個累積直方圖,只要某一次計(jì)算超過半數(shù),就可以停止了
  • 灰度01234567
    直方圖54122434
    累積直方圖59101214182125
  • 分析
    直方圖方法中,對于圖像灰度級為LLL、窗口尺寸為N?NN*NN?N,我們只需要進(jìn)行以下操作:
    1)進(jìn)行N?NN*NN?N次統(tǒng)計(jì)(獲得直方圖)
    2)最多進(jìn)行L?1L-1L?1次累加+判斷(計(jì)算累積直方圖的同時判斷是否超過半數(shù))
    通常圖像的LLL都為256,我們可以推斷對于3?33*33?3的窗口,傳統(tǒng)排序方法速度更快;但當(dāng)N越來越大,直方圖法的優(yōu)勢就越來越大。
  • 代碼見后文


    優(yōu)化

    進(jìn)一步思考可以發(fā)現(xiàn),我們在平移窗口時,新窗口里有N?(N?1)N*(N-1)N?(N?1)的像素都是上一窗口里有的(如下圖黃色),如果重新統(tǒng)計(jì)就浪費(fèi)時間。
    所以有人提出不必重新計(jì)算直方圖,只用更新直方圖——移除(如下圖紅色)+加入(如下圖綠色)。
    代碼見后文


    三、代碼

    本文首先用MATLAB講解演示:傳統(tǒng)排序中值法,快速直方圖中值法,改進(jìn)快速直方圖法
    然后直接分享C、Python的改進(jìn)快速直方圖法。

    MATLAB

  • 經(jīng)典方法
    為了方便轉(zhuǎn)為C語言,沒有使用MATLAB的函數(shù)
  • % 經(jīng)典中值濾波(不處理邊緣)(C格式) function out = medianfilterC(in,r)% 參數(shù)與初始化 [M,N] = size(in); out = zeros(M,N,'uint8'); L = 2*r+1; cidx = L*L/2+0.5; % 如果使用sort(),中值位置在這里 cache = zeros(L*L,1,'uint8'); % 遍歷圖片 for i = 1+r:M-rfor j = 1+r:N-r% 獲取鄰域for m = -r:rfor n = -r:rcache((m+r)*L+n+r+1) = in(i+m,j+n);endend% 選擇排序(找中值,所以沒必要全排序, 且沒必要保存過程的值)for p = 1:cidxminval = cache(p);idx = p;for q = p+1:L*Lif cache(q)<minvalminval = cache(q);idx = q;endendcache(idx) = cache(p);end% 中值out(i,j) = minval;end endend
  • 直方圖方法
  • % 直方圖法(不處理邊緣)(C格式) function out = medianfilterCHist(in,r)% 參數(shù)與初始化 [M,N] = size(in); out = zeros(M,N,'uint8'); L = 2*r+1; cidx = L*L/2+0.5; % 如果使用sort(),中值位置在這里 % 遍歷圖片 for i = 1+r:M-rfor j = 1+r:N-r% 獲取鄰域直方圖hlist = zeros(256,1,'uint32');for m = -r:rfor n = -r:rtmp = in(i+m,j+n)+1;hlist(tmp) = hlist(tmp)+1;endend% 累積直方圖求中值hsum = 0;for k = 1:256hsum = hsum+hlist(k);if hsum>=cidxout(i,j) = k-1;breakendendend endend
  • 改進(jìn)(更新)直方圖方法
  • % 改進(jìn)直方圖法(不處理邊緣)(C格式) function out = medianfilterCHistUpdata(in,r)% 參數(shù)與初始化 [M,N] = size(in); out = zeros(M,N,'uint8'); L = 2*r+1; cidx = L*L/2+0.5; % 如果使用sort(),中值位置在這里 % 遍歷圖片 for i = 1+r:M-r%% 計(jì)算第一列的hlist = zeros(256,1,'uint32');% 獲取鄰域直方圖for m = -r:rfor n = -r:rtmp = in(i+m,1+r+n)+1;hlist(tmp) = hlist(tmp)+1;endend% 累積直方圖求中值hsum = 0;for k = 1:256hsum = hsum+hlist(k);if hsum>=cidxout(i,1+r) = k-1;breakendend%% 計(jì)算后續(xù)的for j = 2+r:N-r% 更新直方圖for m = -r:r% 剔除tmp = in(i+m,j-r-1)+1;hlist(tmp+1) = hlist(tmp+1)-1;% 加入tmp = in(i+m,j+r)+1;hlist(tmp+1) = hlist(tmp+1)+1;end% 累積直方圖求中值hsum = 0;for k = 1:256hsum = hsum+hlist(k);if hsum>=cidxout(i,j) = k-1;breakendendend endend
  • 自帶
    當(dāng)然了,MATLAB有他自帶的中值濾波,賊快
  • out = medfitler2(in, [N,N]);

    C

    改進(jìn)(更新)直方圖方法

    /*** 中值濾波 ***/ void medfilter2(BYTE* pImgOut, // (out)濾波后圖像(0~255)const BYTE* pImg, // (in)原始灰度圖像(0~255)int imgWidth, // (in)圖像寬(pixel)int imgHeight, // (in)圖像高(pixel)int nR // (in)窗口核半徑(pixel) ) {int nL = 2 * nR + 1;int num = nL*nL;int cidx = num / 2 + 1; // 中值所在的位置// 初始化統(tǒng)計(jì)直方圖int *hist = (int*)malloc(256 * sizeof(int));// 開始遍歷int tmp = 0;for (int i = nR; i < imgHeight - nR; i++){memset(hist, 0, 256 * sizeof(int));// 第一列for (int m = -nR; m <= nR; m++){for (int n = -nR; n <= nR; n++){tmp = pImg[(i + m)*imgWidth + (nR + n)];hist[tmp]++;}}int histsum = 0;for (int k = 0; k < 256; k++){histsum += hist[k];if (histsum >= cidx){pImgOut[i*imgWidth + nR] = k;break;}}// 計(jì)算后續(xù)for (int j = 1 + nR; j < imgWidth - nR; j++){for (int m = -nR; m <= nR; m++){tmp = pImg[(i + m)*imgWidth + (j - 1 - nR)];hist[tmp]--;tmp = pImg[(i + m)*imgWidth + (j + nR)];hist[tmp]++;}int histsum = 0;for (int k = 0; k < 256; k++){histsum += hist[k];if (histsum >= cidx){pImgOut[i*imgWidth + j] = k;break;}}}}}

    Python

    寫時候遇到一個小問題,由于本人剛?cè)腴T不久,不太懂底層的原理
    用python跑for循環(huán)的時候運(yùn)行速度特別慢,如果有大佬知道原因希望留言告訴我,謝謝了。
    代碼還是放在這里。

    def medfilter( img, r ):# 參數(shù)設(shè)置rows = img.shape[0]cols = img.shape[1] L = 2*r + 1num = L*Lcidx = num/2+0.5out = np.zeros([rows,cols]) # 循環(huán)求解for i in range(r, rows-r):# 計(jì)算第一列hist = [0]*256# 獲取直方圖tmp = img[i-r:i+r+1,0:L].flatten()for n in range(0,num):hist[tmp[n]] += 1hist[tmp[n]] += 1# 累積直方圖histsum = 0for k in range(0,256):histsum += hist[k]if histsum>=cidx:out[i,r] = kbreak# 后續(xù)計(jì)算for j in range(1+r,cols-r):for m in range(-r,r+1):tmp = img[i+m, j-1-r]hist[tmp] -= 1tmp = img[i+m, j+r]hist[tmp] += 1histsum = 0for k in range(0,256):histsum += hist[k]if histsum>=cidx:out[i,j] = kbreak return out;

    四、測試

    這里只展示matlab測試結(jié)果,

    clear; close all; clc% 制造含噪圖像 im = imread('test.jpg'); gray = rgb2gray(im); in = imnoise(gray,'salt & pepper',0.02); % 椒鹽噪聲r = 4;% MATLAB自帶函數(shù) tic out0 = medfilt2(in,[2*r+1,2*r+1]); toc% 經(jīng)典排序方法 tic out2 = medianfilterC(in,r); toc% 直方圖中值法 tic out3 = medianfilterCHist(in,r); toc% 改進(jìn)直方圖中值法 tic out4 = medianfilterCHistUpdata(in,r); toc

    結(jié)果如下圖,由于我寫的沒有處理邊緣的像素,所以結(jié)果有黑邊。這里使用半徑為4,如果更大效果就非常明顯了。

    其他

  • 參考文獻(xiàn)
    《A Fast Two-Dimensional Median Filtering Algorithm》
    《Median Filter in Constant Time》
    《Fast Median Filtering by Use of Fast Localization of Median Value》
  • 由于本人剛?cè)腴TPython不久,不太懂底層的原理。用python跑for循環(huán)的時候運(yùn)行速度特別慢,如果有大佬知道原因希望留言告訴我,謝謝了。
  • 總結(jié)

    以上是生活随笔為你收集整理的(MATLAB/C/Python)快速中值滤波的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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