OpenCV筆記(2)(高斯平滑、腐蝕和膨脹、開閉運算、禮帽和黑帽、Sobel及其他算子)


一、高斯平滑(模糊)

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算子是用於計算二階導數的。體現的是邊緣的突變度,即梯度的變化度。效果如圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM