赞
踩
对于一些背景纯色,结构相对简单的图,可以利用传统的opencv图像处理进行分割。先来记录一下基于二值化图像素投影的图片切割方法的实现。比如下面这张图,可以利用这个算法进行切割。(源代码在最后面)
切割后的效果
思路:对于背景为白色的图片,可以分别统计每一行和每一列的黑像素点的个数,获得水平和垂直方向累计黑点个数的列表,如果列表中某个元素的值为0,代表这一行或这一列没有黑色像素,可以认为这一行或这一列是背景,切割时利用列表相邻两个元素是否为0和非零,确定切割边界。黑色背景的图也可以用这个思路,这次笔记以白色背景图为例。
首先要对图片进行二值化,我选用自适应二值化方法,选择其他二值化方法也可以,但自适应二值化方法有个好处是只要把常数设置成大于0,不管黑色背景还是白色背景的图都能变成白色背景。
- def adaptive_threshold(gray, blockSize=5, C=10, inv=False):
- if inv == False:
- thresholdType = cv2.THRESH_BINARY
- else:
- thresholdType = cv2.THRESH_BINARY_INV
- # 自适应阈值化能够根据图像不同区域亮度分布,改变阈值
- binary_img = cv2.adaptiveThreshold(
- gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, thresholdType, blockSize, C)
- return binary_img
-
- if __name__ == "__main__":
- img_path = 'xxx.jpg'
- img = cv2.imread(img_path)
- gray = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY)
-
- binary_img = adaptive_threshold(gray, blockSize=15)
得到二值化图像后,就需要计算水平或垂直方向的投影了,方法简单粗暴,遍历每个像素点
- def get_projection_list_demo(binary_img):
- h, w = binary_img.shape[:2]
- row_list = [0] * h
- col_list = [0] * w
- for row in range(h):
- for col in range(w):
- if binary_img[row, col] == 0:
- row_list[row] = row_list[row] + 1
- col_list[col] = col_list[col] + 1
-
- # 显示水平投影
- temp_img_1 = 255 - np.zeros((binary_img.shape[0], max(row_list)))
- for row in range(h):
- for i in range(row_list[row]):
- temp_img_1[row, i] = 0
- cv2.imshow('horizontal', temp_img_1)
-
- # 显示垂直投影
- temp_img_2 = 255 - np.zeros((max(col_list), binary_img.shape[1]))
- for col in range(w):
- for i in range(col_list[col]):
- temp_img_2[i, col] = 0
- cv2.imshow('vertical', temp_img_2)
根据水平投影图可以很明显地分割出每一行,而垂直投影图则没有明显的价值,但是如果把图片的每一行拿出来做垂直投影,就能分割出每一行的文字块。按照这个思路,需要把这张图先进行水平切分,切完后的每个水平图片再进行垂直切分,最后得到的每个区域差不多就是我们想要的目标区域集了。
因此需要先把上面这幅图的水平投影列表进行提取每个区域的起始和终止位置。
def split_projection_list(projecti
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。