圖片處理-opencv-5.圖像形態(tài)學(xué)(腐蝕,膨脹,開運(yùn)算,閉運(yùn)算,梯度運(yùn)算,頂帽運(yùn)算,黑帽運(yùn)算)

圖像腐蝕與圖像膨脹

圖像的膨脹(Dilation)和腐蝕(Erosion)是兩種基本的形態(tài)學(xué)運(yùn)算,主要用來(lái)尋找圖像中的極大區(qū)域和極小區(qū)域。

?

圖像腐蝕

image.png

該公式表示圖像A用卷積模板B來(lái)進(jìn)行腐蝕處理,通過(guò)模板B與圖像A進(jìn)行卷積計(jì)算,得出B覆蓋區(qū)域的像素點(diǎn)最小值,并用這個(gè)最小值來(lái)替代參考點(diǎn)的像素值。如圖所示,將左邊的原始圖像A腐蝕處理為右邊的效果圖A-B。


image.png

形態(tài)學(xué)轉(zhuǎn)換主要針對(duì)的是二值圖像(0或1)。圖像腐蝕類似于“領(lǐng)域被蠶食”,將圖像中的高亮區(qū)域或白色部分進(jìn)行縮減細(xì)化,其運(yùn)行結(jié)果圖比原圖的高亮區(qū)域更小。

dst = cv2.erode(src, kernel, iterations)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • kernel表示卷積核
  • iterations表示迭代次數(shù),迭代次數(shù)默認(rèn)是1,表示進(jìn)行一次腐蝕,也可以根據(jù)需要進(jìn)行多次迭代,進(jìn)行多次腐蝕
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))

#讀取圖片
src = cv2.imread('data/test4.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((5,5), np.uint8)

#圖像腐蝕處理
erosion = cv2.erode(src, kernel)

#顯示結(jié)果
titles = ['src', 'erosion']
images = [src, erosion]
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png

圖像膨脹

image.png

該公式表示用B來(lái)對(duì)圖像A進(jìn)行膨脹處理,其中B是一個(gè)卷積模板或卷積核,其形狀可以為正方形或圓形,通過(guò)模板B與圖像A進(jìn)行卷積計(jì)算,掃描圖像中的每一個(gè)像素點(diǎn),用模板元素與二值圖像元素做“與”運(yùn)算,如果都為0,那么目標(biāo)像素點(diǎn)為0,否則為1。從而計(jì)算B覆蓋區(qū)域的像素點(diǎn)最大值,并用該值替換參考點(diǎn)的像素值實(shí)現(xiàn)膨脹。下圖是將左邊的原始圖像A膨脹處理為右邊的效果圖A⊕B。
image.png

圖像膨脹是腐蝕操作的逆操作,類似于“領(lǐng)域擴(kuò)張”,將圖像中的高亮區(qū)域或白色部分進(jìn)行擴(kuò)張,其運(yùn)行結(jié)果圖比原圖的高亮區(qū)域更大,線條變粗了,主要用于去噪。
(1) 圖像被腐蝕后,去除了噪聲,但是會(huì)壓縮圖像。
(2) 對(duì)腐蝕過(guò)的圖像,進(jìn)行膨脹處理,可以去除噪聲,并且保持原有形狀。

dst = cv2.dilate(src, kernel, iterations)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • kernel表示卷積核
  • iterations表示迭代次數(shù)
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))

#讀取圖片
src = cv2.imread('data/test4.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((5,5), np.uint8)

#圖像膨脹處理
dilate = cv2.dilate(src, kernel)

#顯示結(jié)果
titles = ['src', 'dilate']
images = [src, dilate]
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png
# 依次進(jìn)行腐蝕、膨脹處理
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))


#讀取圖片
src = cv2.imread('data/test5.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel1 = np.ones((9,9), np.uint8)
#圖像腐蝕處理
result1 = cv2.erode(src, kernel1)

#設(shè)置卷積核
kernel2 = np.ones((9,9), np.uint8)
#圖像膨脹處理
result2 = cv2.dilate(result1, kernel2)

#顯示結(jié)果
titles = ['Image', 'erode', 'dilate']
images = [src, result1, result2]
for i in range(3):
    plt.subplot(1, 3, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png

圖像開運(yùn)算、閉運(yùn)算、梯度運(yùn)算、頂帽運(yùn)算、黑帽運(yùn)算

?

圖像開運(yùn)算

圖像開運(yùn)算是圖像依次經(jīng)過(guò)腐蝕、膨脹處理后的過(guò)程。圖像被腐蝕后,去除了噪聲,但是也壓縮了圖像;接著對(duì)腐蝕過(guò)的圖像進(jìn)行膨脹處理,可以去除噪聲,并保留原有圖像。

dst = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • cv2.MORPH_OPEN表示開運(yùn)算
  • kernel表示卷積核
import cv2  
import numpy as np  
import matplotlib.pyplot as plt


#讀取圖片
src = cv2.imread('data/test6.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((12,12), np.uint8)

#圖像開運(yùn)算
result = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)

#顯示結(jié)果
titles = ['src', 'result']
images = [src, result]
plt.figure(figsize=(10, 4))
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png

圖像閉運(yùn)算

圖像閉運(yùn)算是圖像依次經(jīng)過(guò)膨脹、腐蝕處理后的過(guò)程。圖像先膨脹,后腐蝕,它有助于關(guān)閉前景物體內(nèi)部的小孔,或物體上的小黑點(diǎn)。

dst = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • cv2.MORPH_CLOSE
  • kernel表示卷積核
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#讀取圖片
src = cv2.imread('data/test7.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((10,10), np.uint8)

#圖像閉運(yùn)算
result = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel)

#顯示結(jié)果
titles = ['src', 'result']
images = [src, result]
plt.figure(figsize=(10, 4))
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png

圖像梯度運(yùn)算

圖像梯度運(yùn)算是膨脹圖像減去腐蝕圖像的結(jié)果,得到圖像的輪廓,其中二值圖像1表示白色點(diǎn),0表示黑色點(diǎn)。

dst = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • cv2.MORPH_GRADIENT表示梯度運(yùn)算
  • kernel表示卷積核
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#讀取圖片
src = cv2.imread('data/test8.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((10,10), np.uint8)

#圖像閉運(yùn)算
result = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel)

#顯示結(jié)果
titles = ['src', 'result']
images = [src, result]
plt.figure(figsize=(10, 4))
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png

頂帽運(yùn)算

圖像頂帽(或圖像禮帽)運(yùn)算是原始圖像減去圖像開運(yùn)算的結(jié)果,得到圖像的噪聲。常用于解決由于光照不均勻圖像分割出錯(cuò)的問(wèn)題。

dst = cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • cv2.MORPH_TOPHAT表示頂帽運(yùn)算
  • kernel表示卷積核
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#讀取圖片
src = cv2.imread('data/test5.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((9,9), np.uint8)

#圖像頂帽運(yùn)算
result = cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel)

#顯示結(jié)果
titles = ['src', 'result']
images = [src, result]
plt.figure(figsize=(10, 4))
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png

黑帽運(yùn)算

圖像黑帽運(yùn)算是圖像閉運(yùn)算操作減去原始圖像的結(jié)果,得到圖像內(nèi)部的小孔,或者前景色中的小黑點(diǎn)。也常用于解決由于光照不均勻圖像分割出錯(cuò)的問(wèn)題。

dst = cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel)

  • dst表示處理的結(jié)果
  • src表示原圖像
  • cv2.MORPH_BLACKHAT表示頂帽運(yùn)算
  • kernel表示卷積核
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#讀取圖片
src = cv2.imread('data/test7.jpg', cv2.IMREAD_UNCHANGED)

#設(shè)置卷積核
kernel = np.ones((5,5), np.uint8)

#圖像黑帽運(yùn)算
result = cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel)

#顯示結(jié)果
titles = ['src', 'result']
images = [src, result]
plt.figure(figsize=(10, 4))
for i in range(2):
    plt.subplot(1, 2, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
image.png
# 基于灰度三維圖的頂帽黑帽運(yùn)算
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter

#讀取圖像
img = cv.imread("data/test5.jpg")
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
imgd = np.array(img)      #image類轉(zhuǎn)numpy

#準(zhǔn)備數(shù)據(jù)
sp = img.shape
h = int(sp[0])        #圖像高度(rows)
w = int(sp[1])       #圖像寬度(colums) of image

#繪圖初始處理
fig = plt.figure(figsize=(16,12))
ax = fig.gca(projection="3d")

x = np.arange(0, w, 1)
y = np.arange(0, h, 1)
x, y = np.meshgrid(x,y)
z = imgd
surf = ax.plot_surface(x, y, z, cmap=cm.coolwarm)  

#自定義z軸
ax.set_zlim(-10, 255)
ax.zaxis.set_major_locator(LinearLocator(10))   #設(shè)置z軸網(wǎng)格線的疏密
#將z的value字符串轉(zhuǎn)為float并保留2位小數(shù)
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) 

# 設(shè)置坐標(biāo)軸的label和標(biāo)題
ax.set_xlabel('x', size=15)
ax.set_ylabel('y', size=15)
ax.set_zlabel('z', size=15)
ax.set_title("surface plot", weight='bold', size=20)

#添加右側(cè)的色卡條
fig.colorbar(surf, shrink=0.6, aspect=8)  
plt.show()
image.png
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter

#讀取圖像
img = cv.imread("data/test5.jpg")
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

#圖像黑帽運(yùn)算
kernel = np.ones((10,10), np.uint8)
result = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

#image類轉(zhuǎn)numpy
imgd = np.array(result)     

#準(zhǔn)備數(shù)據(jù)
sp = result.shape
h = int(sp[0])        #圖像高度(rows)
w = int(sp[1])       #圖像寬度(colums) of image

#繪圖初始處理
fig = plt.figure(figsize=(16,12))
ax = fig.gca(projection="3d")

x = np.arange(0, w, 1)
y = np.arange(0, h, 1)
x, y = np.meshgrid(x,y)
z = imgd
surf = ax.plot_surface(x, y, z, cmap=cm.coolwarm)  

#自定義z軸
ax.set_zlim(-10, 255)
ax.zaxis.set_major_locator(LinearLocator(10))   #設(shè)置z軸網(wǎng)格線的疏密
#將z的value字符串轉(zhuǎn)為float并保留2位小數(shù)
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) 

# 設(shè)置坐標(biāo)軸的label和標(biāo)題
ax.set_xlabel('x', size=15)
ax.set_ylabel('y', size=15)
ax.set_zlabel('z', size=15)
ax.set_title("surface plot", weight='bold', size=20)

#添加右側(cè)的色卡條
fig.colorbar(surf, shrink=0.6, aspect=8)  
plt.show()
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容