形态学操作主要包含:腐蚀,膨胀,开运算,闭运算,形态学梯度运算,顶帽(礼帽)运算,黑帽运算等,其中腐蚀与膨胀是其它形态学操作的基础。
形态学处理主要用于视觉检测、文字识别、医学图像处理、图像压缩编码等领域
####下面大标题一、二、三均只针对二值图像,灰度图像与彩色图像与之不同,在大标题四中有单独阐述###
在介绍形态学操作之前先看下面一段代码:
import cv2
import numpy as np
#生成一个单通道灰度图像
img=np.random.randint(0,255,(10,10),np.uint8)
#根据阈值生成二值图
thresh,dst=cv2.threshold(img,100,255,cv2.THRESH_BINARY)
#使用cv2.getStructuringElement产生操作核,下面有相关介绍
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
#腐蚀,下面有介绍
dst_1=cv2.erode(dst,kernel)
print(img)
print("-------二值图像矩阵------")
print(dst)
print("-------kernel---------")
print(kernel)
print("---------腐蚀结果矩阵---------")
print(dst_1)
从二值矩阵和腐蚀结果矩阵来看,只有当操作核(kernel)中为1的像素点才参与了运算,而为0时不会计算在内,我们下面大标题一、二、三所说的二值图像操作核基本都是全1,但我们要明白次理。
一:腐蚀
(1):能够将图像的边界点消除,使图像沿着边界向内收敛,也可以将小于指定结构体元素的部分去掉。
(2):在腐蚀过程中,通常使用一个结构元来逐个像素的扫描要被腐蚀的图像,并根据结构元与被腐蚀图像的关系来确定腐蚀结果(每次判定的点都是结构元中心所对应的点)。
结果的判定:
a:如果结构元完全处在前景图像中,则将结构元中心点对应的腐蚀结果图像中的像素点处理为前景
b:如果结构元未完全处在前景图像中(部分在,或完全不在),则被处理为背景色
(3):dst=cv2.erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
(a)dst是腐蚀后的目标图像,该图像和原始图像具有同样的类型及大小
(b)src是需要进行腐蚀的原图,它可以具有任意数量的通道。但是要求图像的深度必须是
CV_8U,CV_16U,CV_16S,CV_32F,CV_64F中的一种。
(c)kernel 代表腐蚀操作时所采用的结果类型,可以自定义生成,也可以用函数cv2.getStructuringElement()生成。
(d) iterations表示腐蚀操作迭代的次数。默认为1
(e)anchor表示锚点,默认在kernel的中心,borderType边界样式,borderValue边界值。此三值一般默认即可
import cv2
import numpy as np
#13.png为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/13.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((3,1),np.uint8)
kernel_1=np.ones((10,1),np.uint8)
dst=cv2.erode(img, kernel)
dst_1=cv2.erode(img,kernel_1)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.imshow("dst_1",dst_1)
cv2.waitKey()
cv2.destroyAllWindows()
图img,dst,dst_1均为二值图,从dst与dst1中可以看出,随着kernel增大,腐蚀效果越明显
二:膨胀
(1):膨胀操作与腐蚀操作的作用是相反的,膨胀操作能对图像的边界进行扩充,膨胀操作将当前对象(前景)接触到的背景点合并在前景中,从而实现边界扩张。膨胀操作对填补图像分割后图像内所存在的空白有帮助。
(2):膨胀操作与腐蚀操作一样,都是使用一个结构元来逐个像素的扫描原图,并根据结构元与原图的关系来确定最终结果。
结果判断:
a:结构元中如果有像素点处于前景图像中,则结果处理为前景色
b:结构元完全处于背景图像中,结果处理为背景色。
(3)dst=cv2.dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
参数意义同腐蚀一致(只需将腐蚀替换为膨胀)
import cv2
import numpy as np
#13.png为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/13.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((10,10),np.uint8)
kernel_1=np.ones((10,1),np.uint8)
dst=cv2.dilate(img, kernel)
dst_1=cv2.dilate(img,kernel_1,iterations=5)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.imshow("dst_1",dst_1)
cv2.waitKey()
cv2.destroyAllWindows()
三:通用形态学函数
(1):腐蚀操作和膨胀操作是形态学运算的基础,腐蚀和膨胀操作的不同组合形式可以实现开运算,闭(闭)运算,形态学梯度,礼帽(顶帽)运算,黑帽运算等。
(2):opencv中,函数cv2.morphologyEx()可以实现上述形态学操作
dst=cv2.morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
dst,src与腐蚀膨胀中一致
op代表上述的不同操作类型,具体见下表
kernel、anchor、iterations、borderType、borderValue与腐蚀膨胀中的一致
(3)开运算:先腐蚀,再膨胀
import cv2
import numpy as np
#25.png与24.png均为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/25.png",cv2.IMREAD_UNCHANGED),(300,300))
img1=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/24.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((5,5),np.uint8)
#去噪
dst=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
#计数,将连接在一起的不同区域划分开
dst1=cv2.morphologyEx(img1,cv2.MORPH_OPEN,kernel,iterations=5)
cv2.imshow("img",img)
cv2.imshow("img1",img1)
cv2.imshow("dst",dst)
cv2.imshow("dst1",dst1)
cv2.waitKey()
cv2.destroyAllWindows()
对比图img与图dst可以看出,图dst在img的基础上去除了前景图边缘的噪声。而图dst1在图img1的基础上将原来连接不是特别紧密的部分彻底分开了,可用于计数。
(4)闭运算:先膨胀,再腐蚀
import cv2
import numpy as np
#26.png为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/26.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((5,5),np.uint8)
#去除原图中的前景图像中的小孔
dst=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel,iterations=2)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()
img为原图,dst为经过闭运算的图,显然可以看出图dst的前景图中没有了小孔。
(5)形态学梯度运算:膨胀图减去腐蚀图
import cv2
import numpy as np
#25.png为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/25.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((5,5),np.uint8)
#去除原图中的前景图像中的小孔
dst=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()
对比图img与dst可知,形态学梯度操作可以获取前景图像的边缘信息。
(6)顶(礼)帽运算:原始图像减去开运算
import cv2
import numpy as np
#25.png为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/25.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((5,5),np.uint8)
dst=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()
(6)黑帽运算:闭运算减去原始图像
import cv2
import numpy as np
#26.png为二值图像
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/26.png",cv2.IMREAD_UNCHANGED),(300,300))
kernel=np.ones((5,5),np.uint8)
dst=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()
(7)核函数:
在进行形态学操作时,必须使用一个特定的核(结构元),该核可以自定义生成,也可以通过函数cv2.getStructuringElement()构造,该函数返回一个用于形态学处理的指定大小和形状的结构元素。
kernel=cv2.getStructuringElement(shape, ksize, anchor=None)
A:shape代表形状类型,其可能取的值如下:
(a) cv2.MORPH_RECT:矩形结构元素,所有元素都是1
(b) cv2.MORPH_CROSS: 十字形结构元素,对角线元素值为1
(c) cv2.MORPH_ELLIPSE: 椭圆形结构元素
B:ksize代表结构元素的大小
C:anchor代表结构元素中锚点的位置,默认为(-1,-1),是形状的中心。只有十字星型的形状与锚点位置紧密相关,其它情况下,锚点位置仅用于形态学运算结果的调整。
用户也可以自己构建一个任意二进制掩码作为形态学操作中的结构元素。
import cv2
import numpy as np
img=cv2.resize(cv2.imread("D:/my project/opencv3/chapter_1/img/24.png"),(300,300))
#矩形结构元素
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(30,30))
#十字形结构元素
kernel_1=cv2.getStructuringElement(cv2.MORPH_CROSS,(30,30))
#椭圆形结构元素
kernel_2=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(30,30))
dst=cv2.dilate(img,kernel)
dst_1=cv2.dilate(img,kernel_1)
dst_2=cv2.dilate(img,kernel_2)
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.imshow("dst_1",dst_1)
cv2.imshow("dst_2",dst_2)
cv2.waitKey()
四:灰度图像与彩色图像的形态学操作
1、灰度图像的膨胀和腐蚀如下图所示(彩色图像(rgb)可以将每个通道单独的看成一幅灰度图像,将每个通道处理后,再将三个通道合并在一起,即该彩色图像的膨胀或腐蚀等操作结果):
(1)膨胀
由上图可知,在膨胀时,操作核中所有为1的位置所对应的灰度图像像素最大值即为该像素点的膨胀结果。
(2)腐蚀
由上图可知,在腐蚀时,操作核中所有为1的位置所对应的灰度图像像素最小值即为该像素点的腐蚀结果。
2、彩色图像的腐蚀效果展示
import cv2
import numpy as np
img = cv2.resize(cv2.imread(“img/1.jpg”), (300, 300))
kernel = np.ones((3, 1), np.uint8)
dst = cv2.erode(img, kernel)
cv2.imshow(“img”, img)
cv2.imshow(“dst”, dst)
b,g,r=cv2.split(img)
kernel = np.ones((3, 1), np.uint8)
b_dst=cv2.erode(b, kernel)
g_dst=cv2.erode(g, kernel)
r_dst=cv2.erode(r, kernel)
dst_1=cv2.merge([b_dst,g_dst,r_dst])
##单通道灰度图
cv2.imshow(“b_dst”,b_dst)
cv2.imshow(“dst_1”,dst_1)
cv2.waitKey()
cv2.destroyAllWindows()
对比图dst与dst_1可知,对彩色图像进行腐蚀操作时,相当于分别对三个通道进行腐蚀操作,然后叠加。b_dst为b通道(灰度图)进行腐蚀操作的结果,由于操作核较小,并且迭代次数(iterations)只要1次,所以效果不明显。
3、其它的彩色图像形态学操作与此类似,在此不做过多展示。