1. 程式人生 > >OpenCV中對模糊操作的總結 影象處理:基礎(模板、卷積運算) 影象處理-模板、卷積的整理 推文:影象濾波函式imfilter函式的應用及其擴充套件

OpenCV中對模糊操作的總結 影象處理:基礎(模板、卷積運算) 影象處理-模板、卷積的整理 推文:影象濾波函式imfilter函式的應用及其擴充套件

原帖地址

三種模糊操作

均值模糊

中值模糊

自定義模糊(可以實現上面兩種模糊方式)

 

這個演算法類似有:均值,中值,就是取周圍所有畫素的均值、中值來設定這個畫素的大小。

 

(關於邊界問題:有幾種填充方法:補零、邊界複製、塊複製、映象複製等方法)

原理

影象處理:基礎(模板、卷積運算)

 

影象處理-模板、卷積的整理

基於離散卷積

定義好每個卷積核

不同卷積核得到不同的卷積效果

模糊是卷積的一種表象

 一、均值模糊blur

opencv有一個專門的平均濾波模板供使用–歸一化卷積模板,所有的濾波模板都是使卷積框覆蓋區域所有畫素點與模板相乘後得到的值作為中心畫素的值。
Opencv中均值模板可以用cv2.blur和cv2.boxFilter,比如一個3*3的模板其實就可以如下表示:

模板大小是m*n是可以設定的。如果你不想要前面的1/9,可以使用非歸一化的模板cv2.boxFilter。

 img = cv.imread('11.jpg')
 img1 = cv.blur(img,(10,10))
 cv.imshow('img',img)
 cv.imshow('img1',img1)
 cv.waitKey(0)
 cv.destroyAllWindows()

均值模糊函式blur():

定義:blur(src,ksize,dst=None, anchor=None, borderType=None)

定義是有5個引數,但最後三個均為none,所以也就2個引數

src:要處理的原影象

ksize: 必須是奇數卷積核,周圍關聯的畫素的範圍:程式碼中(5,5)就是5*5的大小,就是計算這些範圍內的均值來確定中心位置的大小

二、中值模糊mediablur

中值濾波模板就是用卷積框中畫素的中值代替中心值,達到去噪聲的目的。 這個模板一般用於去除椒鹽噪聲。 前面的濾波器都是用計算得到的一個新值來取代中心畫素的值,而中值濾波是用中心畫素周圍(也可以使他本身)的值來取代他,卷積核的大小也是個奇數

  img = cv.imread('11.jpg')
  gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
  cv.imshow('gray',gray)
  for i in range(2000):
      x = np.random.randint(0,gray.shape[0])
      y = np.random.randint(0,gray.shape[1])
      gray[x,y] = 255
  cv.imshow('new_gray',gray)
  dst = cv.medianBlur(gray,9) #注意,中值模糊的ksize一個數字就可以了,這裡是9*9
  cv.imshow('dst',dst)
  cv.waitKey(0)
  cv.destroyAllWindows()

中值模糊函式medianBlur(): 

定義:medianBlur(src, ksize, dst=None)

ksize與blur()函式不同,不是矩陣,而是一個數字,例如為5,就表示了5*5的方陣

可以看到中值濾波對於這些白點噪聲的去除是非常的好的。

 三、高斯模糊GaussianBlur

1、原理

2、原理程式碼

def clamp(pv):  #使我們的隨機值在0-255之間
    if pv > 255:
        return 255
    elif pv < 0:
        return 0
    else:
        return pv

import cv2 as cv
import numpy as np

def gaussian_noise(image):  #對影象加上高斯噪聲
    h,w,c = image.shape
    for row in range(h):  #十分耗時
        for col in range(w):
            s = np.random.normal(0,20,3)  #產生3個隨機值,符合正態分佈,第一個引數是概率分佈的均值,對應分佈中心,,第二個是概率分佈的標準差,越小越瘦高,第三個是輸出的值個數
            b = image[row,col,0] #blue
            g = image[row,col,1] #green
            r = image[row,col,2] #red
            image[row,col,0] = clamp(b+s[0])  #為什麼畫素值是整數的怎麼會和float相加呢?
            image[row,col,1] = clamp(g+s[1])
            image[row,col,2] = clamp(r+s[2])

    cv.imshow("noise image",image)


src = cv.imread("./1.png")  #讀取圖片
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)    #建立GUI視窗,形式為自適應
cv.imshow("input image",src)    #通過名字將影象
gaussian_noise(src)

cv.waitKey(0)   #等待使用者操作,裡面等待引數是毫秒,我們填寫0,代表是永遠,等待使用者操作
cv.destroyAllWindows()  #銷燬所有視窗

 推文:從np.random.normal()到正態分佈的擬合

3、使用opencv高斯模糊

高斯平滑函式GaussianBlur()

定義:GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)

src,輸入影象,即源影象,填Mat類的物件即可。它可以是單獨的任意通道數的圖片,但需要注意,圖片深度應該為CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
dst,即目標影象,需要和源圖片有一樣的尺寸和型別。比如可以用Mat::Clone,以源圖片為模板,來初始化得到如假包換的目標圖。
ksize,高斯核心的大小。其中ksize.width和ksize.height可以不同,但他們都必須為正數和奇數(並不能理解)。或者,它們可以是零的,它們都是由sigma計算而來。
sigmaX,表示高斯核函式在X方向的的標準偏差。  根據這個可以獲取sigmaY,若是sigmaX和sigmaY都沒有則根據ksize獲取
sigmaY,表示高斯核函式在Y方向的的標準偏差。若sigmaY為零,就將它設為sigmaX,如果sigmaX和sigmaY都是0,那麼就由ksize.width和ksize.height計算出來。
為了結果的正確性著想,最好是把第三個引數Size,第四個引數sigmaX和第五個引數sigmaY全部指定到。
borderType,用於推斷影象外部畫素的某種邊界模式。注意它有預設值BORDER_DEFAULT。

img = cv.imread('11.jpg')
gaosi = cv.GaussianBlur(img,(0,0),15)  #(0,0),然後根據sigmaX=15自動計算ksize
cv.imshow('img',img)
cv.imshow('gaosi',gaosi)
cv.waitKey(0)
cv.destroyAllWindows()

 

4、對高斯噪聲圖進行高斯模糊(發現高斯噪聲的影響不大,高斯模糊對其有抑制作用)

img = cv.imread('11.jpg')
cv.imshow('image',img)
gaosi_noise(img)
gaosi = cv.GaussianBlur(img,(0,0),10)
cv.imshow('gaosi',gaosi)
cv.waitKey(0)
cv.destroyAllWindows()

四、邊緣保留濾波EPF

OpenCV經典的兩種實現EPF方法:高斯雙邊和均值遷移

1、雙邊模糊

只模糊上半部分,下半部分差異太大,沒有模糊

 差異越大,越會完整保留

雙邊濾波函式bilateralFilter():

定義:bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)

值域和空域的兩個方差sigma可以簡單的設定為相等,小於10,無太大效果,大於150效果太強,像卡通片似的。
濾波器尺寸d:大於5將較慢(5 forreal-time),d=9,for off-lineapplications,d 是畫素鄰域“直徑”。計算的半徑,半徑之內的像數都會被納入計算,如果提供-1或者0,會從後面的引數sigmaSpace中自動計算。
Sigma_color(顏色標準差):顏色空間過濾器的sigma值,這個引數的值越大,表明該畫素鄰域內有越寬廣的顏色會被混合到一起,產生較大的半相等顏色區域。
Sigma_space(空間標準差):座標空間中濾波器的sigma值,如果該值較大,則意味著顏色相近的較遠的畫素將相互影響,從而使更大的區域中足夠相似的顏色獲取相同的顏色。當d>0時,d指定了鄰域大小且與sigmaSpace五官,否則d正比於sigmaSpace.

雙邊濾波的內在想法是:在影象的值域(range)上做傳統濾波器在空域(domain)上做的工作。空域濾波對空間上鄰近的點進行加權平均,加權係數隨著距離的增加而減少;值域濾波則是對畫素值相近的點進行加權平均,加權係數隨著值差的增大而減少。

 

 想要得到比較好的結果,3/4/5引數最好都指定。d>5那麼計算會很慢,所以一般都設定為d=5,如果少數情況需要去除比較大的噪聲,那麼d=9,要去的較好的平滑效果,最好在9附近。

d或者sigma_space設定的越大,包含的範圍越大,耗時越長

def bi_demo(image):
    dst = cv.bilateralFilter(image,0,100,15)  #第二個引數d是distinct,我們若是輸入了d,會根據其去算第3或4個引數,我們最好是使用第3或4個引數反算d,先設為0
    cv.imshow("dst",dst)

src = cv.imread("1.jpg")  #讀取圖片
cv.namedWindow("img",cv.WINDOW_AUTOSIZE)    #建立GUI視窗,形式為自適應
cv.imshow("img",src)    #通過名字將影象和視窗聯絡
bi_demo(src)
cv.waitKey(0)   #等待使用者操作,裡面等待引數是毫秒,我們填寫0,代表是永遠,等待使用者操作
cv.destroyAllWindows()  #銷燬所有視窗

若是高斯模糊,則整體都會模糊掉,實現濾鏡效果。

2、均值遷移

推文:Opencv均值漂移pyrMeanShiftFiltering彩色影象分割流程剖析

meanShfit均值漂移演算法是一種通用的聚類演算法,它的基本原理是:對於給定的一定數量樣本,任選其中一個樣本,以該樣本為中心點劃定一個圓形區域,求取該圓形區域內樣本的質心,即密度最大處的點,再以該點為中心繼續執行上述迭代過程,直至最終收斂。

可以利用均值偏移演算法的這個特性,實現彩色影象分割,Opencv中對應的函式是pyrMeanShiftFiltering。這個函式嚴格來說並不是影象的分割,而是影象在色彩層面的平滑濾波,它可以中和色彩分佈相近的顏色,平滑色彩細節,侵蝕掉面積較小的顏色區域,所以在Opencv中它的字尾是濾波“Filter”,而不是分割“segment”。先列一下這個函式,再說一下它“分割”彩色影象的實現過程。

pyrMeanShiftFiltering(src, sp, sr, dst=None, maxLevel=None, termcrit=None): 

第一個引數src,輸入影象,8位,三通道的彩色影象,並不要求必須是RGB格式,HSV、YUV等Opencv中的彩色影象格式均可;

第二個引數sp,定義的漂移物理空間半徑大小;  #越大,細節丟失越多

第三個引數sr,定義的漂移色彩空間半徑大小;

第四個引數dst,輸出影象,跟輸入src有同樣的大小和資料格式;

第五個引數maxLevel,定義金字塔的最大層數;

第六個引數termcrit,定義的漂移迭代終止條件,可以設定為迭代次數滿足終止,迭代目標與中心點偏差滿足終止,或者兩者的結合;

dst = cv.pyrMeanShiftFiltering(image,10,50)   #一般這三個引數就可以了

五、自定義模糊fileter 2D

推文:影象濾波函式imfilter函式的應用及其擴充套件

Opencv提供的一個通用的2D濾波函式為cv2.filter2D(),
濾波函式的使用需要一個核模板,對影象的濾波操作過程為:將和模板放在影象的一個畫素A上,求與之對應的影象上的每個畫素點的和,
核不同,得到的結果不同,而濾波的使用核心也是對於這個核模板的使用,需要注意的是,該濾波函式是單通道運算的,
也就是說對於彩色影象的濾波,需要將彩色影象的各個通道提取出來,對各個通道分別濾波才行。

filter2D(src,ddepth,kernel):

ddepth:深度,輸入值為-1時,目標影象和原影象深度保持一致

kernel: 卷積核(或者是相關核),一個單通道浮點型矩陣

 1、實現中值模糊

img = cv.imread('1.jpg')
cv.imshow('img',img)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('gray',gray)
kernel = np.ones([5,5],np.float32)/25  
dst = cv.filter2D(gray,-1,kernel) 7 cv.imshow('dst',dst) 8 cv.waitKey(0) 9 cv.destroyAllWindows()

宣告二維陣列5*5,初始化1,保證值不溢位,除以陣列大小,實現中值模糊,自定義卷積核的運算元

上述生成的5*5核模板其實就是一個均值濾波。,當我們是/25就是中值濾波,歸一化處理

 

2、實現銳化處理

使用的kernel是:,實現銳化處理,提高影象的對比度,提高立體感,輪廓更加清晰。

img = cv.imread('1.jpg')
cv.imshow('img',img)
kernel = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]],np.float32)
dst = cv.filter2D(img,-1,kernel)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()