Github地址
形态学处理主要对图像处理,提取高亮区域的暗部,提取暗部区域的高光。
基础构建结构元element:
7.1_腐蚀:领域最小灰度做输出灰度。图像亮度降低。亮度区域减小。
7.2_膨胀:领域最大灰度做输出灰度。图像亮度提高。亮度区域增加。
7.3/7.4_开运算&闭运算&白顶帽&黑底帽&形态学梯度
开运算: erode * dilate,消除暗部高亮区域,不改变面积情况下平滑边界
闭运算:dilate * erode,消除高光部分的暗部,多次迭代处理不改变面积情况平滑边界
白顶帽:src - open,得到暗部被消除的高光
黑底帽:src - close,得到高光消除的暗部
形态学梯度:dilate - erode,边缘检测作用
dst = cv2.morphologyEx(src,op,element)
7.3还介绍了OpenCV用调节条实时调节结构元半径&迭代次数
本章形态学用来优化分割区域的形状以达到更好的效果。
腐蚀:原理同中值平滑,但选取领域内最小值作为输出灰度。总体亮度平均值会降低。
仅需要调节element结构元,与iterations迭代次数即可,其他默认
element为结构元,有三种形状:cv2.MORPH_RECT(矩形),cv2.MORPH_ELLIPSEM(椭圆形),cv2.MORPH_CROSS(十字交叉形)
#-*- coding:utf-8 -*-
import cv2
import matplotlib.pyplot as plt
I = cv2.imread("img2.jpg",0)
#创建3*3,
s3 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
#腐蚀图像,迭代次数默认为1
r3 = cv2.erode(I,s3)
#边界提取
e3 = I - r3
#7*7尺寸结构元
s7 = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
r7 = cv2.erode(I,s7)
e7 = I - r7
#11*11尺寸结构元
s11 = cv2.getStructuringElement(cv2.MORPH_RECT,(11,11))
r11 = cv2.erode(I,s11)
e11 = I - r11
#显示图像和腐蚀后结果,边界提取效果
for i in range(7):
titles = ["src","dst3","dst7","dst11","edge3","edge7","edge11"]
images = [I,r3,r7,r11,e3,e7,e11]
plt.subplot(2,4,i+1)
plt.title(titles[i])
plt.imshow(images[i])
plt.show
效果很好,随着结构元尺寸增加,白色主体腐蚀越多,结构元形状也形如马赛克被凸显出来。
膨胀与腐蚀相反,选择领域最大灰度值作为输出。输出图像亮度平均值上升,亮部主体尺寸变大。
#-*- coding:utf-8 -*-
import cv2
import matplotlib.pyplot as plt
I = cv2.imread("img2.jpg",0)
cv2.imshow("I",I)
#结构元半径
r = 1
Max_R = 20
#显示膨胀效果窗口
cv2.namedWindow("dilate",1)
#创建回调函数
def nothing(*arg):
pass
#创建结构元半径调整条
cv2.createTrackbar("r","dilate",r,Max_R,nothing)
while True:
#得到当前的r值
r = cv2.getTrackbarPos('r','dilate')
#创建结构元
s = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(2*r+1,2*r+1))#若为(1,2*r+1),则只有垂直方向发生变化,水平方向不变
#膨胀图像
d = cv2.dilate(I,s)
#显示膨胀效果
cv2.imshow("dilate",d)
ch = cv2.waitKey(5)
#按下Esc退出
if ch==27:
break
cv2.destroyAllWindows()
#r=3不错 plt打印一下吧
r1 = 3
s1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(2*r1+1,2*r1+1))
d1 = cv2.dilate(I,s1)
plt.subplot(1,2,1)
plt.imshow(I)
plt.subplot(1,2,2)
plt.imshow(d1)
plt.show()
通过将腐蚀与膨胀进行先后组合,也就是开,闭运算。
开运算:先腐蚀后膨胀,消除高亮细节,消除暗处的较亮区域。对较大物体可不改变面积情况下平滑边界。
闭运算:先膨胀后腐蚀,填充亮处的黑色区域。同一个结构元,多次迭代处理可在不改变面积情况下平滑边界。
cv2.morphologyEx(src,op,element[, dst[, anchor[, iterations[, borderType[,borderValue]]]]])
op:
增加调节结构元半径进度条与迭代次数进度条
开运算
#-*- coding:utf-8 -*-
import sys
import cv2
import matplotlib.pyplot as plt
I_open = cv2.imread("open.jpg",0)
cv2.imshow("I_open",I_open)
#结构元半径与迭代次数调节条
r,i=1,1
MAX_R,MAX_I = 20,20
cv2.namedWindow("morphology",1)
def nothing(*arg):
pass
cv2.createTrackbar("r","morphology",r,MAX_R,nothing)
cv2.createTrackbar("i","morphology",i,MAX_I,nothing)
while True:
r = cv2.getTrackbarPos("r","morphology")
i = cv2.getTrackbarPos("i","morphology")
s = cv2.getStructuringElement(cv2.MORPH_RECT,(2*r+1,2*r+1))
#形态学处理
d_open = cv2.morphologyEx(I_open,cv2.MORPH_OPEN,s,iterations=i)
cv2.imshow("morphology",d_open)
ch = cv2.waitKey(5)
if ch ==27:
break
cv2.destroyAllWindows()
#r=3,iterations=5不错
plt.subplot(1,2,1)
plt.imshow(I_open)
plt.subplot(1,2,2)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(2*3+1,2*3+1))
d_open = cv2.morphologyEx(I_open,cv2.MORPH_OPEN,s,iterations=5)
plt.imshow(d_open)
plt.show()
#-*- coding:utf-8 -*-
import sys
import cv2
import matplotlib.pyplot as plt
I_close = cv2.imread("open.jpg",0)
cv2.imshow("I_close",I_close)
#结构元半径与迭代次数调节条
r,i=1,1
MAX_R,MAX_I = 20,20
cv2.namedWindow("morphology",1)
def nothing(*arg):
pass
cv2.createTrackbar("r","morphology",r,MAX_R,nothing)
cv2.createTrackbar("i","morphology",i,MAX_I,nothing)
while True:
r = cv2.getTrackbarPos("r","morphology")
i = cv2.getTrackbarPos("i","morphology")
s = cv2.getStructuringElement(cv2.MORPH_RECT,(2*r+1,2*r+1))
#形态学处理
d_close = cv2.morphologyEx(I_close,cv2.MORPH_CLOSE,s,iterations=i)
cv2.imshow("morphology",d_close)
ch = cv2.waitKey(5)
if ch ==27:
break
cv2.destroyAllWindows()
#r=5,i=3不错,打印一下
plt.subplot(1,2,1)
plt.imshow(I_close)
plt.subplot(1,2,2)
s = cv2.getStructuringElement(cv2.MORPH_RECT,(2*5+1,2*5+1))
d_close = cv2.morphologyEx(I_close,cv2.MORPH_CLOSE,s,iterations=3)
plt.imshow(d_close)
plt.show()
其他形态学操作:
白顶帽变换(cv2.MORPH_TOPHAT): 图像减去开运算,得到被消除高亮区域。
黑底帽变换(cv2.MORPH_BLACKHAT):图像减去闭运算,得到被消除的暗部区域。
形态学梯度变换(cv2.MORPH_GRADIENT):膨胀减去腐蚀,得到物体边界。(边缘检测)
import cv2
import matplotlib.pyplot as plt
I = cv2.imread("open.jpg",0)
cv2.imshow("I",I)
r,i = 1,1
MAX_R,MAX_I = 20,20
cv2.namedWindow("morphology",1)
def nothing(*arg):
pass
cv2.createTrackbar("r","morphology",r,MAX_R,nothing)
cv2.createTrackbar("i","morphology",i,MAX_I,nothing)
while True:
r = cv2.getTrackbarPos("r","morphology")
i = cv2.getTrackbarPos("i","morphology")
s = cv2.getStructuringElement(cv2.MORPH_RECT,(2*r+1,2*r+1))
d_TOPHAT = cv2.morphologyEx(I,cv2.MORPH_TOPHAT,s,iterations=i)
d_BLACKHAT = cv2.morphologyEx(I,cv2.MORPH_BLACKHAT,s,iterations=i)
d_GRADIENT = cv2.morphologyEx(I,cv2.MORPH_GRADIENT,s,iterations=i)
cv2.imshow("TOPHAT",d_TOPHAT)
cv2.imshow("BLACKHAT",d_BLACKHAT)
cv2.imshow("GRADIENT",d_GRADIENT)
ch = cv2.waitKey(5)
if ch == 27:
break
cv2.destroyAllWindows()
#r=5,i=3时,顶帽,底帽效果出的好
s = cv2.getStructuringElement(cv2.MORPH_RECT,(2*5+1,2*5+1))
d_TOPHAT = cv2.morphologyEx(I,cv2.MORPH_TOPHAT,s,iterations=3)
d_BLACKHAT = cv2.morphologyEx(I,cv2.MORPH_BLACKHAT,s,iterations=3)
#r=1,i=1时,形态学梯度使边缘出现明显
d_GRADIENT = cv2.morphologyEx(I,cv2.MORPH_GRADIENT,cv2.getStructuringElement(cv2.MORPH_RECT,(2*1+1,2*1+1)),iterations=1)
titles = ["I","TOPHAT","BLACKHAT","GRADIENT"]
images = [I,d_TOPHAT,d_BLACKHAT,d_GRADIENT]
for i in range(4):
plt.subplot(2,2,i+1)
plt.title(titles[i])
plt.imshow(images[i])
plt.show()