1.腐蚀(Erosing)
腐蚀是一种常见的形态学操作,它通过将图像中的物体边界向内部腐蚀来减小物体的大小。腐蚀操作通常用于去除图像中的小白噪声、分离物体等。在腐蚀操作中,我们需要定义一个结构元素(通常是一个小的矩形或圆形),然后将这个结构元素在图像上滑动,当结构元素完全覆盖物体时,该像素点保持原值,否则置为0。这里原图如下图所示。
现在选取一个核,我这里想要将白色竖线腐蚀掉,所以选取宽大于高的这种核运算,尽量保留白色横线。步骤如下:
当腐蚀核(绿色框)运算时,紫色?处的值为核内最小的值,随意?处的值为0(黑色)。
腐蚀核继续遍历像素值:
继续遍历所有像素点,最后得到整个图经过核(宽=3,高=1)腐蚀后的图如下图所示:
2.膨胀(dilation)
形态学操作膨胀其基本原理是将图像与结构元素进行卷积,计算结构元素覆盖下图像的最大像素值,并用这个最大值替换结构元素锚点位置的像素值。这样可以使图像中的高亮区域逐渐增长,实现“领域扩张”的效果。可以用于消除噪声、分割独立的图像元素、连接相邻的图像元素,以及寻找图像中明显的极大值区域等。在实际应用中,可以根据需要选择不同大小和形状的结构元素,以达到最佳的膨胀效果。
膨胀是针对图像中的高亮部分(即白色部分)进行的,而不是黑色部分。因此,膨胀操作可以使图像中的高亮区域逐渐增长,但不会影响黑色区域的大小和形状。
膨胀与腐蚀相反,如图(一个方格就是一个像素):对于该二值图(0代表黑色,255代表白色),只有黑色背景与白色前景。假设 有一个膨胀的核(图中绿色框),紫色为使用核膨胀后的元素,由于绿色框中最大值为0(黑色),所以该值膨胀后仍然为黑色(右图),以此遍历所有像素值就可以得到整个图被核(绿色框)膨胀后的图。
最后整个图膨胀为下图所示。
2.开运算(Opening)
开运算是形态学操作中的一种组合操作,它是先进行腐蚀操作,再进行膨胀操作。开运算的主要作用是去除图像中的噪声,平滑物体的边界,并且可以分离物体。开运算可以消除小的亮点(白噪声),并且可以将不同物体分开。在开运算中,首先对图像进行腐蚀操作,然后再对腐蚀后的图像进行膨胀操作。与其相反的是闭运算(先膨胀,再腐蚀),这里不讲解。
3.实现表格线的删除
利用开运算就可以达到删除水平线或者垂直线,这里用电脑绘图自己绘制了一个简易的表格图
删除水平线
import cv2 image = cv2.imread('opencv.png') result = image.copy() gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]#自适应 cv2.imshow('binary_INV',thresh)#显示反转后二值图 # Remove horizontal lines horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (20,1)) remove_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) cnts = cv2.findContours(remove_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(result, [c], -1, (255,255,255), 5) cv2.imwrite('img_remove_horizontal_lines.png',result)#保存结果图片 cv2.imshow('result',result) cv2.waitKey(0) cv2.destroyWindow() ''' cv2.THRESH_BINARY_INV:表示进行反转的二值化操作,即像素值高于阈值的区域将被设置为0(黑色),而像素值低于阈值的区域将被设置为指定的最大值(这里是255,即白色)。 cv2.THRESH_OTSU:表示使用Otsu方法自动计算阈值。Otsu方法是一种通过计算类间方差来确定图像二值化最佳阈值的方法。 cv2.threshold函数返回一个包含两个元素的元组,第一个元素是计算得到的阈值,第二个元素是二值化后的图像。 这里使用[1]来索引元组中的第二个元素,即二值化后的图像,并将其存储在thresh变量中。
cnts = cnts[0] if len(cnts) == 2 else cnts[1]是为了兼容OpenCV的不同版本。在OpenCV 3中,cv2.findContours
返回三个值:图像、轮廓和层次结构。而在OpenCV 4中,它只返回两个值:轮廓和层次结构。这行代码检查cv2.findContours
的返回值数量,并据此提取轮廓列表。
'''
运行后,得到的二值图像与保存的删除水平线的图像如下:
删除垂直线
import cv2 image = cv2.imread('opencv.png') result = image.copy() gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]#自适应 cv2.imshow('binary_INV',thresh)#显示反转后二值图 # Remove vertical lines vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,20)) remove_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2) cnts = cv2.findContours(remove_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(result, [c], -1, (255,255,255), 5) cv2.imwrite('img_remove_vertical_lines.png',result)#保存结果图片 cv2.imshow('result',result) cv2.waitKey(0) cv2.destroyWindow()
小结:注意核的选取不一定是常见的3x3,可以根据自己的需要选取核的形状与大小。图像形态学操作除了本文介绍的膨胀、腐蚀、还有其他包括形态学梯度、礼帽运算等。本文可以还可以继续调节不同的核大小与形状继续观察效果,至于为什么上图中得到的线条是断断续续的,就留给读者自己思考与解决了。
若存在不足或错误之处,欢迎指出与评论!
标签:清除,垂直线,cv2,opencv,腐蚀,cnts,result,图像,255 From: https://www.cnblogs.com/wancy/p/17953260