一、高斯平滑(模糊)
def gaussian_blur(image): # 設置ksize來確定模糊效果 img = cv.GaussianBlur(image, (5, 5), 0) cv.imshow('img', img) # 不通過ksize來設置高斯核大小,通過設置高斯分布公式中的sigma img2 = cv.GaussianBlur(image, (0, 0), 1) cv.imshow('img2', img2)
在高斯平滑中,高斯核中所有數字加起來應該為1,這樣才能保證圖片只發生平滑效果,而不影響亮度等其他效果。
例如3x3的高斯核如下所示:
二、邊緣保留濾波(EPF)
高斯雙邊模糊(美顏):
def bi_blur(image): img = cv.bilateralFilter(image, 0, 100, 5) cv.imshow('img', img)
從效果可以看出,邊緣保留的還不錯,而非邊緣進行了模糊。雙邊模糊的效率比較低,特別是sigmaSpace比較大的時候。
cv.bilateralFilter()函數的參數:
src:原圖像
d:過濾過程中每個像素領域的直徑范圍,若非正數,則從sigmaSpace計算
sigmaColor:值越大,表示像素領域內有多寬的顏色(顏色范圍)會被混在一起
sigmaSpace:如果值較大,表示顏色相近的較遠像素(空間范圍)將互相影響,從而使更大區域足夠相似的顏色獲取相同的顏色。
三、腐蝕和膨脹
腐蝕操作:
# 腐蝕操作,用於去除一些細小的白色顆粒或線條 def erode_img(image): kernel = np.ones((5,5),np.uint8) # 當核尺寸越大時,每次腐蝕的程度越大,iter是操作中疊加幾次腐蝕 img = cv.erode(image,kernel,iterations = 1) cv.imshow('img',img)
膨脹操作:
膨脹可以說是腐蝕的反操作:
# 膨脹操作,用於去除一些細小的黑色漏洞 def dilate_img(image): kernel = np.ones((5, 5), np.uint8) img = cv.dilate(image, kernel, iterations=1) cv.imshow('img', img)
結合腐蝕和膨脹:
結合腐蝕和膨脹,可以消除一些細小的不需要的部分,然后再復原。
def combo_proc(image): kernel = np.ones((5, 5), np.uint8) img = cv.dilate(image, kernel, iterations=1) img2 = cv.erode(img, kernel, iterations=1) cv.imshow('img2', img2)
四、開運算和閉運算
# 開操作:先腐蝕再膨脹 def open_proc(image): kernel = np.ones((5, 5), np.uint8) opening = cv.morphologyEx(image, cv.MORPH_OPEN, kernel) cv.imshow('opening', opening) # 閉操作:先膨脹再腐蝕 def close_proc(image): kernel = np.ones((5, 5), np.uint8) closing = cv.morphologyEx(image, cv.MORPH_CLOSE, kernel) cv.imshow('closing', closing)
結合開閉運算:
# 先做開操作,再做閉操作 def open_close_proc(image): kernel = np.ones((5, 5), np.uint8) opening = cv.morphologyEx(image, cv.MORPH_OPEN, kernel) closing = cv.morphologyEx(opening, cv.MORPH_CLOSE, kernel) cv.imshow('closing', closing)
梯度運算:
# 梯度操作:膨脹 - 腐蝕 def gradient_proc(image): kernel = np.ones((3, 3), np.uint8) gradient = cv.morphologyEx(image, cv.MORPH_GRADIENT, kernel) cv.imshow('gradient', gradient)
五、禮帽和黑帽
禮帽是通過原圖片減去開操作后的圖像,得到其中的多於細小部分(字邊上的白色細線)。
黑帽是通過閉操作后的圖像減去原圖像,得到其中的細小泄漏部分(字中間的黑色細線)。
禮帽:tophat
# tophat 禮帽 def tophat_img(image): kernel = np.ones((3, 3), np.uint8) img = cv.morphologyEx(image, cv.MORPH_TOPHAT, kernel) cv.imshow('img', img)
黑帽:blackhat
# blackhat 黑帽 def blackhat_img(image): kernel = np.ones((3, 3), np.uint8) img = cv.morphologyEx(image, cv.MORPH_BLACKHAT, kernel) cv.imshow('img', img)
六、Sobel算子
def sobel_proc(image): # 這里的cv.CV_64F用來保存所有的梯度(不管正負),1,0是dx,dy表示計算橫向梯度 sobelx = cv.Sobel(image, cv.CV_64F, 1, 0, ksize=3) # 將所有梯度取絕對值 sobelx = cv.convertScaleAbs(sobelx) cv.imshow('sobelx', sobelx) # 計算y方向的梯度 sobely = cv.Sobel(image, cv.CV_64F, 0, 1, ksize=3) # 將所有梯度取絕對值 sobely = cv.convertScaleAbs(sobely) cv.imshow('sobely', sobely)
當計算X,Y方向的梯度時,Sobel算子分別為:
X方向是右邊像素減去左邊像素,Y方向是上面像素減去下面的像素。
將XY方向的梯度合並起來:
def sobel_proc(image): # 這里的cv.CV_64F用來保存所有的梯度(不管正負),1,0是dx,dy表示計算橫向梯度 sobelx = cv.Sobel(image, cv.CV_64F, 1, 0, ksize=3) # 將所有梯度取絕對值 sobelx = cv.convertScaleAbs(sobelx) # cv.imshow('sobelx', sobelx) # 計算y方向的梯度 sobely = cv.Sobel(image, cv.CV_64F, 0, 1, ksize=3) # 將所有梯度取絕對值 sobely = cv.convertScaleAbs(sobely) # cv.imshow('sobely', sobely) # 將x和y方向的梯度合並起來,類似於sobelx+sobely sobelxy = cv.addWeighted(sobelx, 1, sobely, 1, 0) cv.imshow('sobelxy', sobelxy) # 不建議使用這種方式,有問題 sobelxy2 = cv.Sobel(image, -1, 1, 1, ksize=3) cv.imshow('sobelxy2', sobelxy2)
建議使用addWeight()的方式進行合並,而不建議在一個Sobel計算中同時計算xy方向的梯度。
應用到圖片上:
彩色圖:
灰度圖:
七、其他算子介紹
Scharr算子:(讀/ʃɑr/)
scharr = cv.Scharr(image,cv.CV_64F, 1, 0)
scharr = cv.convertScaleAbs(scharr)
Scharr算子和Sobel算子類似,只是數值比Sobel大很多,這就導致Scharr算子靈敏度更高,噪聲影響較大。如下圖:
Laplacian算子:
拉普拉斯算子是圖像的離散二階導數,用於發現邊緣突變,但對於噪聲來說比較靈敏,一般配合其他技術一起使用。
laplacian = cv.Laplacian(image,cv.CV_64F)
laplacian = cv.convertScaleAbs(laplacian)
Laplacian算是和前面的兩種算子不同,前面的兩種算子都屬於一階導數,而Laplacian算子是用於計算二階導數的。體現的是邊緣的突變度,即梯度的變化度。效果如圖: