中值濾波是空域中常用的一種濾波方式,是一種非線性的濾波。它的原理就是將視窗畫素排序,取中值,然後移動視窗,不斷重複取中值的過程。
但是,可以發現,每次移動視窗,都需要對畫素點進行排序,從而選取中間的那個畫素點。每次重新排序的效率特別低,為了優化這個排序,便有了快速中值濾波。
快速中值濾波是中值濾波的優化版,它利用了視窗每次平移時,沒有移出視窗的畫素點還是排好序的,因此,只需要把新加入的畫素點插入到其中即可完成排序。此外,由於我們並不需要乙個完整的排序數列, 只需要找到中值就可以了。
基於上面兩點,快速中值濾波採用的是直方圖的方式來統計畫素點,橫座標是畫素點的值,縱座標是視窗中畫素點的個數。設定乙個「游標」,在橫軸上左右移動,當兩邊畫素點相等時,對應的畫素點就是要找的中值。然後移動視窗,更新直方圖,再次移動「游標」,找到中值,不斷反覆。
需要注意的是,「游標」的每次移動,都只能移動在數目不為 0 的畫素點上,否則,取到的中值很可能不在這個視窗中。
r、g、b 三個通道分別計算(可以一起計算,但單通道計算更清晰)
視窗大小為 3*3 的**:
# -*- coding: utf-8 -*-
import numpy as np
import cv2
def quickmedianfiltering(img) :
b, g, r = cv2.split(img)
# 對 藍色通道 進行中值濾波
h = np.zeros(256, dtype=int) # 直方圖
for row in range(1, len(b) - 1) :
# 到達乙個新的行 初始化
h = np.zeros(256, dtype=int) # 直方圖
# 求中值
med = np.uint8(np.median(b[row - 1 : row + 2, 0:3]))
n = 0
for i in range(-1, 2) :
for j in range(0, 3) :
h[b[row+i][j]] = h[b[row+i][j]] + 1
if b[row+i][j] <= med :
n = n + 1
for col in range(1, len(b[row]) - 1) :
if col == 1 :
none
# 移到下一列
else :
# 更新直方圖 並計算 n 的值
for i in range(-1, 2) :
# 對左列元素 值減一
h[b[row+i][col-2]] = h[b[row+i][col-2]] - 1
if b[row+i][col-2] <= med :
n = n - 1
# 對右列元素 值加一
h[b[row+i][col+1]] = h[b[row+i][col+1]] + 1
if b[row+i][col+1] <= med :
n = n + 1
# 重新計算中值
if n > 5 :
while n > 5 :
if med == 0 :
break
n = n - h[med]
med = med - 1
elif n < 5 :
while n < 5 :
med = med + 1
n = n + h[med]
sum = 0
for k in range(med + 1) :
sum = sum + h[k]
# 更新中值後的直方圖
h[b[row][col]] = h[b[row][col]] - 1
if med < b[row][col] :
n = n + 1
b[row][col] = med
h[med] = h[med] + 1
# 對 綠色通道 進行中值濾波
h = np.zeros(256, dtype=int) # 直方圖
for row in range(1, len(g) - 1) :
# 到達乙個新的行 初始化
h = np.zeros(256, dtype=int) # 直方圖
# 求中值
med = np.uint8(np.median(g[row - 1 : row + 2, 0:3]))
if med == -128 :
print(g[row - 1 : row + 2, 0:3])
n = 0
for i in range(-1, 2) :
for j in range(0, 3) :
h[g[row+i][j]] = h[g[row+i][j]] + 1
if g[row+i][j] <= med :
n = n + 1
for col in range(1, len(g[row]) - 1) :
if col == 1 :
none
# 移到下一列
else :
# 更新直方圖 並計算 n 的值
for i in range(-1, 2) :
# 對左列元素 值減一
h[g[row+i][col-2]] = h[g[row+i][col-2]] - 1
if g[row+i][col-2] <= med :
n = n - 1
# 對右列元素 值加一
h[g[row+i][col+1]] = h[g[row+i][col+1]] + 1
if g[row+i][col+1] <= med :
n = n + 1
# 重新計算中值
if n > 5 :
while n > 5 :
if med == 0 :
break
n = n - h[med]
med = med - 1
elif n < 5 :
while n < 5 :
med = med + 1
n = n + h[med]
# 更新中值後的直方圖
h[g[row][col]] = h[g[row][col]] - 1
if med < g[row][col] :
n = n + 1
g[row][col] = med
h[med] = h[med] + 1
# 對 紅色通道 進行中值濾波
h = np.zeros(256, dtype=int) # 直方圖
for row in range(1, len(r) - 1) :
# 到達乙個新的行 初始化
h = np.zeros(256, dtype=int) # 直方圖
# 求中值
med = np.uint8(np.median(r[row - 1 : row + 2, 0:3]))
if med == -128 :
print(r[row - 1 : row + 2, 0:3])
n = 0
for i in range(-1, 2) :
for j in range(0, 3) :
h[r[row+i][j]] = h[r[row+i][j]] + 1
if r[row+i][j] <= med :
n = n + 1
for col in range(1, len(r[row]) - 1) :
if col == 1 :
none
# 移到下一列
else :
# 更新直方圖 並計算 n 的值
for i in range(-1, 2) :
# 對左列元素 值減一
h[r[row+i][col-2]] = h[r[row+i][col-2]] - 1
if r[row+i][col-2] <= med :
n = n - 1
# 對右列元素 值加一
h[r[row+i][col+1]] = h[r[row+i][col+1]] + 1
if r[row+i][col+1] <= med :
n = n + 1
# 重新計算中值
if n > 5 :
while n > 5 :
if med == 0 :
break
n = n - h[med]
med = med - 1
elif n < 5 :
while n < 5 :
med = med + 1
n = n + h[med]
sum = 0
# 更新中值後的直方圖
h[r[row][col]] = h[r[row][col]] - 1
if med < r[row][col] :
n = n + 1
r[row][col] = med
h[med] = h[med] + 1
return cv2.merge([b,g,r])
快速中值濾波主要是利用了直方圖的思想,雖然思路很簡單,但寫**的時候,也遇到不少bug,所幸最後寫完了。 中值濾波 python實現
中值濾波介紹 中值濾波法是一種非線性平滑技術,它將每一畫素點的灰度值設定為該點某鄰域視窗內的所有畫素點灰度值的中值。優點 中值濾波對脈衝雜訊有良好的濾除作用,特別是在濾除雜訊的同時,能夠保護訊號的邊緣,使之不被模糊。這些優良特性是線性濾波方法所不具有的,可以很好的過濾掉椒鹽雜訊。缺點是易造成影象的不...
中值濾波C 實現
中值濾波器是一種非線性濾波器,常用於消除影象中的椒鹽雜訊。與低通濾波不同的是,中值濾波有利於保留邊緣的尖銳度,但它會洗去均勻介質區域中的紋理。因為椒鹽雜訊是由灰度值為0或者255產生的點,所以去畫素周圍畫素值得中值得話很容易剔除校驗雜訊。include include include using n...
中值濾波 MATLAB實現
1 原理 中值濾波能有效抑制雜訊。主要採用灰度值排序,把數字影象中一點的值用該點的乙個鄰域中各點值的中值代替,依次取代畫素中心點的灰度值,讓原本與周圍畫素灰度值相差比較大的畫素更改為與周圍的畫素值比較接近的值,從而消除孤立的雜訊點。它可以保護影象邊緣的同時去除雜訊。實現 clear all clc ...