参考 https://www.cnblogs.com/ssyfj/p/9277688.html
开操作
开操作=腐蚀+膨胀,输入图像+结构元素
开操作先腐蚀,后膨胀
特点:消除噪点,去除小的干扰块,而不影响原来的图像
#开操作,去除干扰块
def open_demo(image):
print(image.shape)
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
cv.imshow("open_binary",binary)
kernel=cv.getStructuringElement(cv.MORPH_RECT,(9,9))
#kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 1))#去除垂直线
#kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 15))#去除水平线
open_binary=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
cv.imshow("open_demo",open_binary)
运行结果
可以看出,干扰点被去除了
还可以利用开操作去除水平线或垂直线,去除哪个线就改变哪个的值
kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 1))#去除垂直线
kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 15))#去除水平线
kernel=cv.getStructuringElement(cv.MORPH_RECT,(9,9))去除干扰线
闭操作
闭操作=膨胀+腐蚀,输入图像+结构元素
闭操作先膨胀,后腐蚀
特点:可以填充闭合区域
开闭操作还可以用于水平线或垂直线的提取,进而去除干扰线
#闭操作,填充闭合区域
def close_demo(image):
print(image.shape)
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
cv.imshow("close_binary",binary)
kernel=cv.getStructuringElement(cv.MORPH_RECT,(10,10))
close_binary=cv.morphologyEx(binary,cv.MORPH_CLOSE,kernel)
cv.imshow("close_demo",close_binary)
运行结果
可以看出,闭合区域被填充了
完整代码
import cv2 as cv
import numpy as np
#开操作,去除干扰块
def open_demo(image):
print(image.shape)
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
cv.imshow("open_binary",binary)
kernel=cv.getStructuringElement(cv.MORPH_RECT,(9,9))#去除干扰
#kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 1))#去除垂直线
#kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 15))#去除水平线
open_binary=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
cv.imshow("open_demo",open_binary)
#闭操作,填充闭合区域
def close_demo(image):
print(image.shape)
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
cv.imshow("close_binary",binary)
kernel=cv.getStructuringElement(cv.MORPH_RECT,(10,10))
close_binary=cv.morphologyEx(binary,cv.MORPH_CLOSE,kernel)
cv.imshow("close_demo",close_binary)
src = cv.imread("D:/OpenCV/opencv/sources/samples/data/A.png")
src1 = cv.imread("D:/OpenCV/opencv/sources/samples/data/ABCD.png")
open_src = cv.imread("D:/OpenCV/opencv/sources/samples/data/pic2.png")
close_src = cv.imread("D:/OpenCV/opencv/sources/samples/data/pic1.png")
cv.namedWindow("input image1", cv.WINDOW_AUTOSIZE)
cv.imshow("input image1", src1)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
cv.namedWindow("input open_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input open_image", open_src)
cv.namedWindow("input close_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input close_image", close_src)
#open_demo(src)
open_demo(src1)
#open_demo(open_src)
#close_demo(close_src)
cv.waitKey(0)
cv.destroyAllWindows()
print("Hi,python!")
函数补充说明
open_binary=cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
close_binary=cv.morphologyEx(binary,cv.MORPH_CLOSE,kernel)
void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), intiterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
函数参数:
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U,CV_16U,CV_16S, CV_32F 或CV_64F。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
MORPH_OPEN – 开运算(Opening operation)
MORPH_CLOSE – 闭运算(Closing operation)
MORPH_GRADIENT -形态学梯度(Morphological gradient)
MORPH_TOPHAT - “顶帽”(“Top hat”)
MORPH_BLACKHAT - “黑帽”(“Black hat“)
第四个参数,InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
第五个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。