形态学操作主要包含:腐蚀、膨胀、开运算、闭运算、形态学梯度运算、顶帽运算(礼帽运算)、黑帽运算等操作
其中腐蚀操作和膨胀操作是形态学的基础
腐蚀操作能够将图像的边界点消除,将图像沿着边界点向内收缩,也可以将小于指定结构的部分消除,即可以把图像细化,
除去噪声
该操作是逐个像素点来决定值,每次判定的点都是结构元中心点所对应的点
函数形式
dst = cv2.erode(src , kernel [ , anchor [ , interations [, borderType [ , borderValue]]]])
dst 为腐蚀后输出的目标图像,与原始图像的类型和大小一样
src 所需要腐蚀的图像,图像的通道数可以任意, 但要求图像深度必须是CV_8U , CV_16U , CV_16S , CV_32F , CV_64F中的一种
kernel代表腐蚀操作时所采用的结构类型, 可以自定义生成, 也可以通过函数,cv2.getStructuringEleMent()
anchor代表结构中锚点的位置,默认为( - 1 , - 1 ) 即核的中心位置
interations腐蚀操作迭代的次数, 默认为1
borderType代表边界样式,当结构元为3x3时处理边界时会出现有一行未处理,当为5x5时有两行 既有以下的边界处理方式
类型 | 说明 |
cv2.BORDER_CONSTANT | iiiiii|abcdefgh|iiiiii 特定值i |
cv2.BORDER_REPLICATE | aaaaaa|abcdefgh| hhhhhh |
cv2.BORDER_REFLECT | fedcba|abcdefgh|hgfedcb |
cv2.BORDER_WRAP | cdefgh|abcdefgh|abcdefg |
cv2.BORDER_REFLECT_101 | gfedcb|abcdefgh| gfedcba |
cv2.BORDER_TRANSPARENT | uvwxyz|abcdefgh| ijklmno |
cv2.BORDER_REFLECT101 | 与cv2.BORDER_REFLECT_101 相同 |
cv2.BORDER_DEFAULT | 与cv2.BORDER_REFLECT_101 相同 |
cv2.BORDER_ISOLATED | 不考虑ROI之外的区域 |
以上的说明中的竖线中间的字母即代表图像的像素点, 而两边的字母即代表边界样式和像素点之间的关系
例如cv2.BORDER_CONSTANT即是特定值处理, 而cv2.BORDER_REPLICATE 即是将边缘样式处理为图像边缘的像素点
borderValue一般为默认值
1 import cv2 2 import numpy as np 3 img = np.zeros((5,5) , np.uint8) 4 img[1:4,1:4] = 1 5 kernel = np.ones((3,1) , np.uint8) 6 erosion = cv2.erode(img , kernel) 7 print("img = " , img) 8 print("kernel = " , kernel) 9 print("erosion = " , erosion)
img = [[0 0 0 0 0] [0 1 1 1 0] [0 1 1 1 0] [0 1 1 1 0] [0 0 0 0 0]] kernel = [[1] [1] [1]] erosion = [[0 0 0 0 0] [0 0 0 0 0] [0 1 1 1 0] [0 0 0 0 0] [0 0 0 0 0]]
如上代码结果所显示只有当整个结构元都在图像内时 , 结构元中心点才会保留, 如果结构元部分在或者完全不在,
则结构元中心点就会被处理为背景色。
代码中只有结构元的中心点 kernel[1,0] 在img[2,1] , img[2,3] , img[2,4] 的时候, 整个结构元才在前景图像中,
这三个点被处理为1
1 import cv2 2 import numpy as np 3 o = cv2.imread("/home/miao/img/chap8/erode.bmp") 4 kernel = np.ones((5,5) , np.uint8) 5 erosion = cv2.erode(o,kernel) 6 cv2.imshow("original" , o) 7 cv2.imshow("erosion" , erosion) 8 cv2.waitKey() 9 cv2.destroyAllWindows()
原图
处理之后 该代码中生成的5x5的核
1 import cv2 2 import numpy as np 3 o = cv2.imread("/home/miao/img/chap8/erode.bmp" , cv2.IMREAD_UNCHANGED) 4 kernel = np.ones((9,9) , np.uint8) 5 erosion = cv2.erode(o,kernel , iterations = 5) 6 cv2.imshow("original" , o) 7 cv2.imshow("erosion" , erosion) 8 cv2.waitKey() 9 cv2.destroyAllWindows()
这是用的9x9的核,并且迭代的5次
膨胀
膨胀的作用和腐蚀的作用是相反的,膨胀操作对当前图像将图像的边界扩张,即将背景点处理为前景图
处理方式为如果结构元中任意一点在前景图像中即将锚点处理为前景色,
如果完全处于背景图像值哦哦嗯,则将结果图像中的锚点处理为背景色
函数形式
dst = cv2.dilate( src , kernel [. anchor [, interations [ , borderType [, borderValue]]]])
参数和cv2.erode()中相应参数含义一致
1 import cv2 2 import numpy as np 3 img = np.zeros((5,5) , np.uint8) 4 img[2:3 , 1:4] = 1 5 kernel = np.ones((3,1) , np.uint8) 6 dilation = cv2.dilate(img , kernel) 7 print("img = ", img) 8 print("kernel = " , kernel) 9 print("dilation = " , dilation)
img = [[0 0 0 0 0] [0 0 0 0 0] [0 1 1 1 0] [0 0 0 0 0] [0 0 0 0 0]] kernel = [[1] [1] [1]] dilation = [[0 0 0 0 0] [0 1 1 1 0] [0 1 1 1 0] [0 1 1 1 0] [0 0 0 0 0]]
结构元为9x9
1 import cv2 2 import numpy as np 3 o = cv2.imread("/home/miao/img/chap8/dilation.bmp", cv2.IMREAD_UNCHANGED) 4 kernel = np.ones((9,9) , np.uint8) 5 dilation = cv2.dilate(o,kernel) 6 cv2.imshow("original" , o) 7 cv2.imshow("dilation" , dilation) 8 cv2.waitKey() 9 cv2.destroyAllWindows()
原图
结构元为5x5 迭代了9次
import cv2 import numpy as np o = cv2.imread("/home/miao/img/chap8/dilation.bmp", cv2.IMREAD_UNCHANGED) kernel = np.ones((5,5) , np.uint8) dilation = cv2.dilate(o,kernel , iterations = 9) cv2.imshow("original" , o) cv2.imshow("dilation" , dilation) cv2.waitKey() cv2.destroyAllWindows()