cv2.erode(src, element[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
src | 输入的原图片 |
element | 结构元 |
anchor | 结构元的锚点 |
iterations | 腐蚀操作的次数 |
borderType | 边界扩充类型 |
boderValue | 边界扩充值 |
与卷积操作类似,对于边界处的像素的领域有可能会超出图像边界,所以需要扩充图像边界,边界扩充类型中镜像扩充操作效果最好。
其中,参数element可由OpenCV提供的下列函数获取
cv2.getStructuringElement(shape, ksize[, anchor])
参数解释
shape | MORPH_RECT: 产生矩形的结构元 MORPH_ELLIPSEM: 产生椭圆形的结构元 MORPH_CROSS: 产生十字交叉形的结构元 |
ksize | 结构元的尺寸 |
anchor | 结构元的锚点 |
import cv2 as cv
import numpy as np
# 读入图片
src = cv.imread('test.jpg', flags=0)
# 添加说明文字
ori = src.copy()
cv.putText(ori, "Original Image", (580, 100), cv.FONT_HERSHEY_COMPLEX, 2.0, (150, 10, 0), 5)
# 生成卷积核
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# 进行腐蚀处理
erosion = cv.erode(src, kernel, iterations=3)
# 添加说明文字
cv.putText(erosion, "Eroded Image", (580, 100), cv.FONT_HERSHEY_COMPLEX, 2.0, (150, 10, 0), 5)
# 将原图片与腐蚀处理后的图片拼接起来
show = np.hstack([ori, erosion])
# 显示图片
cv.namedWindow('result', cv.WINDOW_NORMAL)
cv.imshow('result', show)
cv.waitKey()
cv.destroyAllWindows()
cv2.dilate(src, element[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
src | 输入的原图片 |
element | 结构元 |
anchor | 结构元的锚点 |
iterations | 腐蚀操作的次数 |
borderType | 边界扩充类型 |
boderValue | 边界扩充值 |
import cv2 as cv
import numpy as np
# 读入原图片
src = cv.imread('test.jpg', flags=0)
# 添加说明文字
ori = src.copy()
cv.putText(ori, "Original Image", (580, 100), cv.FONT_HERSHEY_COMPLEX, 2.0, (150, 10, 0), 5)
# 生成卷积核
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# 进行腐蚀处理
erosion = cv.dilate(src, kernel, iterations=3)
# 添加说明文字
cv.putText(erosion, "Dilated Image", (580, 100), cv.FONT_HERSHEY_COMPLEX, 2.0, (150, 10, 0), 5)
# 将原图片与腐蚀处理后的图片拼接起来
show = np.hstack([ori, erosion])
# 显示图片
cv.namedWindow('result', cv.WINDOW_NORMAL)
cv.imshow('result', show)
cv.imwrite('DilatedImage.jpg', show)
cv.waitKey()
cv.destroyAllWindows()
cv2.morphologyEx(src, op, element[, dst[, anchor[, iterations[, borderType[, borderValue ]]]]])
开运算和闭运算均是腐蚀和膨胀的组合,而顶帽变换和底帽变换是分别以开运算和闭运算为基础的。这四个操作都可直接使用OpenCV提供的上述API来完成
src | 输入矩阵 |
op | 形态学处理的各种运算,值的设置如下: MORPH_OPEN:开运算 MORPH_CLOSE:比运算 MORPH_GRADIENT:形态梯度 MORPH_TOPHAT:顶帽运算 MORPH_BLACKHAT:底帽运算 |
elememt | 结构元 |
anchor | 结构元的锚点 |
iterations | 迭代次数 |
先腐蚀,后膨胀
主要用于消除亮度较高的细小区域,在纤细点处分离物体,对于较大物体,可以在不明显改变其面积的情况下平滑其边界。
import cv2 as cv
src = cv.imread('test2.jpg', flags=0)
# 结构元初始半径,最大半径
r, MAX_R = 0, 20
# 初始迭代次数,最大迭代次数
i, MAX_I = 0, 20
# 创建窗口
cv.namedWindow('morphology')
# 设置回调函数
def nothing(*args):
pass
# 创建滑动条,分别为半径和迭代次数
cv.createTrackbar('r', 'morphology', r, MAX_R, nothing)
cv.createTrackbar('i', 'morphology', i, MAX_I, nothing)
while True:
# 得到进度条上当前的r值
r = cv.getTrackbarPos('r', 'morphology')
# 得到进度条上当前的i值
i = cv.getTrackbarPos('i', 'morphology')
# 创建结构元
kernel = cv.getStructuringElement(cv.MORPH_RECT, (2 * r + 1, 2 * r + 1))
# 形态学处理:开运算
result = cv.morphologyEx(src, cv.MORPH_OPEN, kernel, iterations=i)
# 显示效果
cv.imshow('morphology', result)
# 按Esc退出
ch = cv.waitKey(5)
if ch == 27:
break
cv.destroyAllWindows()
先膨胀,后腐蚀
主要用于填充白色物体内细小黑色空洞的区域,连接临近物体,同一个结构元,多次迭代处理,也可以在不明显改变其面积的情况下平滑其边界。
import cv2 as cv
src = cv.imread('test2.jpg', flags=0)
# 结构元初始半径,最大半径
r, MAX_R = 0, 20
# 初始迭代次数,最大迭代次数
i, MAX_I = 0, 20
# 创建窗口
cv.namedWindow('morphology')
# 设置回调函数
def nothing(*args):
pass
# 创建滑动条,分别为半径和迭代次数
cv.createTrackbar('r', 'morphology', r, MAX_R, nothing)
cv.createTrackbar('i', 'morphology', i, MAX_I, nothing)
while True:
# 得到进度条上当前的r值
r = cv.getTrackbarPos('r', 'morphology')
# 得到进度条上当前的i值
i = cv.getTrackbarPos('i', 'morphology')
# 创建结构元
kernel = cv.getStructuringElement(cv.MORPH_RECT, (2 * r + 1, 2 * r + 1))
# 形态学处理:闭运算
result = cv.morphologyEx(src, cv.MORPH_CLOSE, kernel, iterations=i)
# 显示效果
cv.imshow('morphology', result)
# 按Esc退出
ch = cv.waitKey(5)
if ch == 27:
break
cv.destroyAllWindows()
原图像减去开运算结果
开运算可以消除暗背景下的较亮区域,所以顶帽变换可以得到原图中灰度较亮的区域。顶帽变换的一个很重要的作用就是校正不均匀光照
import cv2 as cv
src = cv.imread('test2.jpg', flags=0)
# 结构元初始半径,最大半径
r, MAX_R = 0, 20
# 初始迭代次数,最大迭代次数
i, MAX_I = 0, 20
# 创建窗口
cv.namedWindow('morphology')
# 设置回调函数
def nothing(*args):
pass
# 创建滑动条,分别为半径和迭代次数
cv.createTrackbar('r', 'morphology', r, MAX_R, nothing)
cv.createTrackbar('i', 'morphology', i, MAX_I, nothing)
while True:
# 得到进度条上当前的r值
r = cv.getTrackbarPos('r', 'morphology')
# 得到进度条上当前的i值
i = cv.getTrackbarPos('i', 'morphology')
# 创建结构元
kernel = cv.getStructuringElement(cv.MORPH_RECT, (2 * r + 1, 2 * r + 1))
# 形态学处理:顶帽处理
result = cv.morphologyEx(src, cv.MORPH_TOPHAT, kernel, iterations=i)
# 显示效果
cv.imshow('morphology', result)
# 按Esc退出
ch = cv.waitKey(5)
if ch == 27:
break
cv.destroyAllWindows()
原图片减去闭运算结果
闭运算可以删除亮度较高背景下的较暗区域,所以底帽变换可以得到原图片中灰度较暗的区域,故而又称黑帽变换。
import cv2 as cv
src = cv.imread('test2.jpg', flags=0)
# 结构元初始半径,最大半径
r, MAX_R = 0, 20
# 初始迭代次数,最大迭代次数
i, MAX_I = 0, 20
# 创建窗口
cv.namedWindow('morphology')
# 设置回调函数
def nothing(*args):
pass
# 创建滑动条,分别为半径和迭代次数
cv.createTrackbar('r', 'morphology', r, MAX_R, nothing)
cv.createTrackbar('i', 'morphology', i, MAX_I, nothing)
while True:
# 得到进度条上当前的r值
r = cv.getTrackbarPos('r', 'morphology')
# 得到进度条上当前的i值
i = cv.getTrackbarPos('i', 'morphology')
# 创建结构元
kernel = cv.getStructuringElement(cv.MORPH_RECT, (2 * r + 1, 2 * r + 1))
# 形态学处理:底帽处理
result = cv.morphologyEx(src, cv.MORPH_BLACKHAT, kernel, iterations=i)
# 显示效果
cv.imshow('morphology', result)
# 按Esc退出
ch = cv.waitKey(5)
if ch == 27:
break
cv.destroyAllWindows()
膨胀结果减去腐蚀结果
膨胀是取领域内的最大值从而增大高亮度区域的面积;腐蚀是取领域内的最小值,从而减小高亮度区域的面积。所以形态学梯度的处理结果是图像中物体的边界。
import cv2 as cv
src = cv.imread('test2.jpg', flags=0)
# 结构元初始半径,最大半径
r, MAX_R = 0, 20
# 初始迭代次数,最大迭代次数
i, MAX_I = 0, 20
# 创建窗口
cv.namedWindow('morphology')
# 设置回调函数
def nothing(*args):
pass
# 创建滑动条,分别为半径和迭代次数
cv.createTrackbar('r', 'morphology', r, MAX_R, nothing)
cv.createTrackbar('i', 'morphology', i, MAX_I, nothing)
while True:
# 得到进度条上当前的r值
r = cv.getTrackbarPos('r', 'morphology')
# 得到进度条上当前的i值
i = cv.getTrackbarPos('i', 'morphology')
# 创建结构元
kernel = cv.getStructuringElement(cv.MORPH_RECT, (2 * r + 1, 2 * r + 1))
# 形态学处理:形态梯度
result = cv.morphologyEx(src, cv.MORPH_GRADIENT, kernel, iterations=i)
# 显示效果
cv.imshow('morphology', result)
# 按Esc退出
ch = cv.waitKey(5)
if ch == 27:
break
cv.destroyAllWindows()