形态学变换erode(),膨胀dilate(),结构元getStructuringElement(), 开闭操作梯度顶帽黑帽击中击不中 morphologyEx(),金字塔pyrDown,pyrUp

形态学变换主要有腐蚀、膨胀、开操作、闭操作等等。
1.腐蚀erode()
腐蚀操作可以将边界的白色(前景)像素“腐蚀”掉,但仍能保持大部分白色。类似平滑处理的滑动窗口,用某种结构元在图像上滑动,当结构元覆盖原始图像中的所有像素都为“1”时,新图像中该像素点的值才为“1”(CV8U为255)。腐蚀可以用来去除噪声、去掉“粘连”。

cv2.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) ->dst

src:通道数任意;图像深度只能是CV_8U, CV_16U, CV_16S, CV_32F or CV_64F;
kernel:可以由getStructuringElement()构建;
dst:输出图像,通道数和数据类型同src;
anchor:锚点,默认使用(-1,-1)表示中心点;
iterations:腐蚀次数;
borderType:边界类型;
borderValue:边界值;

_,img = cv2.threshold(img,127,255,0)#阈值化处理 
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) #ksize=5,5
img_ret1 = cv2.erode(img,kernel,iterations=1)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7)) #ksize=7x7,
img_ret2 = cv2.erode(img,kernel,iterations=1)
img_ret3 = cv2.erode(img,kernel,iterations=2) #ksize=7x7,腐蚀2次

2.膨胀dilate()
膨胀是腐蚀的逆操作,可以将边界的白色(前景)像素“生长”扩大。滑动窗口经过白色像素时,只要结构元中有1个像素为“1”时,新图像中该像素点的值就为“1”(CV8U为255)。膨胀可以用来增强连接、填充凹痕。

cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) ->dst

src:通道数任意;图像深度只能是CV_8U, CV_16U, CV_16S, CV_32F or CV_64F;
kernel:可以由getStructuringElement()构建;
dst:输出图像,通道数和数据类型同src;
anchor:锚点,默认使用(-1,-1)表示中心点;
iterations:膨胀次数;
borderType:边界类型;
borderValue:边界值;

_,img = cv2.threshold(img,127,255,0)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
img_ret1 = cv2.dilate(img,kernel,iterations=1)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
img_ret2 = cv2.dilate(img,kernel,iterations=1)
img_ret3 = cv2.dilate(img,kernel,iterations=2) 

3.结构学生成getStructuringElement()

结构元生成函数用来生成形态学变换的kernel参数。

cv2.getStructuringElement(shape, ksize[, anchor]) ->retval

shape:结构元(kernel)的形状;
ksize:结构元(kernel)的大小;
anchor:锚点,默认使用(-1,-1)表示中心点;

shape属性有可选的3种形状:

cv2.MORPH_RECT 方形,所有的数值均为1
cv2.MORPH_CROSS 十字交叉形,在锚点坐标的水平和竖直方向的元素为1,其他为0
cv2.MORPH_ELLIPSE 椭圆形

_,img = cv2.threshold(img,127,255,0)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
print('MORPH_RECT kernel:\n',kernel)
img_ret1 = cv2.dilate(img,kernel,iterations=1)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7))
print('MORPH_ELLIPSE kernel:\n',kernel)
img_ret2 = cv2.dilate(img,kernel,iterations=1)
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(7,7))
print('MORPH_CROSS kernel:\n',kernel)
img_ret3 = cv2.dilate(img,kernel,iterations=1) 

#显示图像
fig,ax = plt.subplots(2,2)
ax[0,0].set_title('原图-mnist(juzicode.com)')
ax[0,0].imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) #matplotlib显示图像为rgb格式
ax[0,1].set_title('MORPH_RECT kernel')
ax[0,1].imshow(cv2.cvtColor(img_ret1,cv2.COLOR_BGR2RGB))
ax[1,0].set_title('MORPH_ELLIPSE kernel')
ax[1,0].imshow(cv2.cvtColor(img_ret2,cv2.COLOR_BGR2RGB))
ax[1,1].set_title('MORPH_CROSS kernel') 
ax[1,1].imshow(cv2.cvtColor(img_ret3,cv2.COLOR_BGR2RGB))
ax[0,0].axis('off');ax[0,1].axis('off');ax[1,0].axis('off');ax[1,1].axis('off')#关闭坐标轴显示
plt.show() 

4.morphologyEx()
开操作、闭操作、顶帽变换、黑帽变换等,这些变换都是以morphologyEx()的接口函数调用的,该函数的接口形式
cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) ->dst

src:源图像,通道数任意;图像深度只能是CV_8U, CV_16U, CV_16S, CV_32F or CV_64F;其中op为cv2.MORPH_HITMISS时仅支持CV_8UC1;
op:变换方式;
kernel:可以由getStructuringElement()构建,op为cv2.MORPH_HITMISS时则由子图构建;
dst:输出图像,通道数和数据类型同src;
anchor:锚点,默认使用(-1,-1)表示中心点;
iterations:迭代次数;
borderType:边界类型;
borderValue:边界值;

4.1腐蚀 cv2.MORPH_ERODE dst=erode(src,element)

4.2膨胀 cv2.MORPH_DILATE dst=dilate(src,element)

4.3开操作 cv2.MORPH_OPEN dst=dilate(erode(src,element))

开操作的实质是先进行腐蚀再膨胀,可以用来消除小于结构元大小的细小区域

img_open = cv2.morphologyEx(img_bin,cv2.MORPH_OPEN,kernel,iterations=1)

4.4闭操作 cv2.MORPH_CLOSE dst=erode(dilate(src,element))

闭操作实际上是先进行膨胀再腐蚀,因为膨胀可以用来填充孔洞、修复缺失的连接,但是同时也会导致白色轮廓增大,当用同样的结构元(kernel)再进行一次腐蚀操作后,就可以保持外形轮廓和原来的一致。

img_close = cv2.morphologyEx(img_bin,cv2.MORPH_CLOSE,kernel,iterations=1)

4.5梯度 cv2.MORPH_GRADIENT dst=dilate(src,element)−erode(src,element)
形态学梯度操作是用膨胀图像减去腐蚀图像的结果,因为膨胀可以增大边沿,腐蚀会缩小边沿,所以形态学梯度变换就能将轮廓提取出来

img_gradient = cv2.morphologyEx(img_bin,cv2.MORPH_GRADIENT,kernel,iterations=1)

4.6顶帽 cv2.MORPH_TOPHAT dst=src−open(src,element)

顶帽变换是用原图减去开操作图像,因为开操作会去除小于结构元的小区域,原图减去开操作图像后,会将开操作去除的小区域保留下来

img_tophat = cv2.morphologyEx(img_bin,cv2.MORPH_TOPHAT,kernel,iterations=1)

4.7黑帽 cv2.MORPH_BLACKHAT dst=close(src,element)−src

黑帽变换和顶帽变换则相反,是将闭操作后的图像减去原图,因为闭操作会填充孔洞(小的黑色区域),孔洞部分变成白色,而原图中仍然为黑色,这样就会将原图中的孔洞保留下来并变为白色区域.

img_blackhat = cv2.morphologyEx(img_bin,cv2.MORPH_BLACKHAT,kernel,iterations=1)

4.8击中击不中 cv2.MORPH_HITMISS dst=erode(src,element) & erode(src,element)
击中击不中变换可以用来在原图中查找子图,假设要查找的图像中包含了多种子图,可以利用某个子图构造出kernel,经过击中击不中变换就能在该子图中心保留一个非零的点

5图像金字塔

1.pyrDown
这里的down是指图像变小,所以原始图像在金字塔的底部。

首先将当前层的图像和下面这个高斯核卷积:
在这里插入图片描述
这个高斯核的尺寸为5×5大小,所有元素的值加起来正好为256,最后再除以256,得到的加权和正好为1。其距离最中心越近数值越大,这正好和高斯平滑选择的高斯核类似。这个过程也类似于高斯平滑,从后面的例子也可以看到经过pyrDown()处理的图像变得更加模糊(平滑)。然后移除偶数行和偶数列,然后就能得到和原图相比是原图1/4大小的新的图像,在图像金字塔中就位于当前层的上一层。

cv2.pyrDown(src[, dst[, dstsize[, borderType]]]) ->dst

src:源图像;
dst:目标图像;
dstsize:缩放后目标图像的尺寸,必须满足std::abs(dsize.width2 – ssize.width) <= 2 && std::abs(dsize.height2 – ssize.height) <= 2
borderType:边界填充类型;

img_down = cv2.pyrDown(img,dstsize=(img.shape[1]//2,img.shape[0]//2))
img_down2 = cv2.pyrDown(img_down,dstsize=(img_down.shape[1]//2,img_down.shape[0]//2))
img_down3 = cv2.pyrDown(img_down2,dstsize=(img_down2.shape[1]//2,img_down2.shape[0]//2))

2.pyrUp
这里的up是指将图像的尺寸变大,所以原始图像位于图像金字塔的顶层。

首先将当前层图像的宽高扩大2倍,插入的行和列位于偶数行或偶数列,这些位置填充数值0;然后用和pyrDown一样的kernel和当前层的图像卷积,填充到刚才插入的行列中。

cv2.pyrUp(src[, dst[, dstsize[, borderType]]]) ->dst
src:源图像;
dst:目标图像;
dstsize:缩放后目标图像的尺寸,必须满足std::abs(dsize.width – ssize.width2) == dsize.width % 2 && std::abs(dsize.height – ssize.height2) == dsize.height % 2
borderType:边界填充类型;

img_up = cv2.pyrUp(img,dstsize=(2*img.shape[1],2*img.shape[0]))
img_up2 = cv2.pyrUp(img_up,dstsize=(2*img_up.shape[1],2*img_up.shape[0]))
img_up3 = cv2.pyrUp(img_up2,dstsize=(2*img_up2.shape[1],2*img_up2.shape[0]))

猜你喜欢

转载自blog.csdn.net/aqiangdeba/article/details/129776214