只提供思路,具体场景核图像有关,需做前期调整
一、处理流程:
1、图像灰度化处理
2、图像二值化处理
3、图像腐蚀处理(若得到的横纵交线不清楚,添加膨胀处理)
4、获取表格交点坐标
5、根据交点集获取单元格轮廓并进行过滤
二、使用案例
三、代码示例及效果
1、灰度化处理
def gray_img(img:'numpy.ndarray'):
"""
对读取的图像进行灰度化处理
:param img: 通过cv2.imread(imgPath)读取的图像数组对象
:return: 灰度化的图像
"""
grayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
return grayImage
2、二值化处理
def bin_img(img:'numpy.ndarray'):
"""
对图像进行二值化处理
:param img: 传入的图像对象(numpy.ndarray类型)
:return: 二值化后的图像
"""
ret,binImage=cv2.threshold(img,180,255,cv2.THRESH_BINARY_INV)
return binImage
3、图像腐蚀
def erode_img(img,kernel_args=(2,2),iterations=1):
"""
对图像进行腐蚀
@param kernel_args 卷积核参数(2,2)
@param interations erode的迭代次数
"""
kernel = np.ones(kernel_args, np.uint8)
return cv2.erode(img, kernel,iterations=iterations)
(1)纵向腐蚀获取横向线条
img_transverse = erode_img(img,(1,2),40)
需要调节卷积核参数(kernel_args),迭代次数(iterations)
(2)横向腐蚀获取纵向线条
img_vertical = erode_img(img, (2,1), 40)
4、图像膨胀处理
膨胀处理相当于对线条进行加粗
img_transverse = dilate_img(img_transverse,(2,2),1)
img_vertical = dilate_img(img_vertical,(2,2),1)
5、获取交点
def get_points(img_transverse, img_vertical):
"""
获取横纵线的交点
:param img_transverse:
:param img_vertical:
:return:
"""
img = cv2.bitwise_and(img_transverse, img_vertical)
return img
6、获取单元格
def split_rec(arr):
"""
切分单元格
:param arr:
:return:
"""
# 数组进行排序
arr.sort(key=lambda x: x[0],reverse=True)
# 数组反转
arr.reverse()
for i in range(len(arr) - 1):
if arr[i+1][0] == arr[i][0]:
arr[i+1][3] = arr[i][1]
arr[i + 1][2] = arr[i][2]
if arr[i+1][0] > arr[i][0]:
arr[i + 1][2] = arr[i][0]
print(arr[i])
return arr
def get_rec(img):
"""
获取单元格
:param img:
:return:
"""
contours, hierarchy = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
contours_poly = [0] * len(contours)
boundRect = [0] * len(contours)
rois = []
for i in range(len(contours) - 1):
cnt = contours[i]
contours_poly[i] = cv2.approxPolyDP(cnt, 1, True)
boundRect[i] = cv2.boundingRect(contours_poly[i])
rois.append(np.array(boundRect[i]))
# img = cv2.rectangle(img_bak, (boundRect[i][0], boundRect[i][1]), (boundRect[i][2], boundRect[i][3]),
# (255, 255, 255), 1, 8, 0)
rois = split_rec(rois)
return rois
四、完整代码
from PIL import Image, ImageOps
import cv2
import numpy as np
def split_rec(arr):
"""
切分单元格
:param arr:
:return:
"""
# 数组进行排序
arr.sort(key=lambda x: x[0],reverse=True)
# 数组反转
arr.reverse()
for i in range(len(arr) - 1):
if arr[i+1][0] == arr[i][0]:
arr[i+1][3] = arr[i][1]
arr[i + 1][2] = arr[i][2]
if arr[i+1][0] > arr[i][0]:
arr[i + 1][2] = arr[i][0]
print(arr[i])
return arr
def get_points(img_transverse, img_vertical):
"""
获取横纵线的交点
:param img_transverse:
:param img_vertical:
:return:
"""
img = cv2.bitwise_and(img_transverse, img_vertical)
return img
def dilate_img(img, kernal_args:tuple, iterations:int):
"""
dilate image
@param kernel_args 卷积核参数(2,2)
@param interations dilate的迭代次数
"""
kernel = np.ones(kernal_args, np.uint8)
return cv2.dilate(img, kernel,iterations=iterations)
pass
def erode_img(img,kernel_args=(2,2),iterations=1):
"""
对图像进行腐蚀
@param kernel_args 卷积核参数(2,2)
@param interations erode的迭代次数
"""
kernel = np.ones(kernel_args, np.uint8)
return cv2.erode(img, kernel,iterations=iterations)
def bin_img(img:'numpy.ndarray'):
"""
对图像进行二值化处理
:param img: 传入的图像对象(numpy.ndarray类型)
:return: 二值化后的图像
"""
ret,binImage=cv2.threshold(img,180,255,cv2.THRESH_BINARY_INV)
return binImage
def gray_img(img:'numpy.ndarray'):
"""
对读取的图像进行灰度化处理
:param img: 通过cv2.imread(imgPath)读取的图像数组对象
:return: 灰度化的图像
"""
grayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
return grayImage
pass
def get_rec(img):
"""
获取单元格
:param img:
:return:
"""
contours, hierarchy = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
contours_poly = [0] * len(contours)
boundRect = [0] * len(contours)
rois = []
for i in range(len(contours) - 1):
cnt = contours[i]
contours_poly[i] = cv2.approxPolyDP(cnt, 1, True)
boundRect[i] = cv2.boundingRect(contours_poly[i])
rois.append(np.array(boundRect[i]))
# img = cv2.rectangle(img_bak, (boundRect[i][0], boundRect[i][1]), (boundRect[i][2], boundRect[i][3]),
# (255, 255, 255), 1, 8, 0)
rois = split_rec(rois)
return rois
if __name__ == "__main__":
image = "D:/cs/ocr/c.png"
img_bak = cv2.imread(image)
img = gray_img(img_bak)
img = bin_img(img)
img_transverse = erode_img(img,(1,2),40)
img_vertical = erode_img(img, (2,1), 40)
# img = img_transverse + img_vertical
img_transverse = dilate_img(img_transverse,(2,2),1)
img_vertical = dilate_img(img_vertical,(2,2),1)
img = get_points(img_transverse,img_vertical)
rois = get_rec(img)
for i, r in enumerate(rois):
cv2.imshow("src" + str(i), img_bak[r[3]:r[1], r[2]:r[0]])
cv2.waitKey(0)
cv2.destroyAllWindows()
pass
五、未解决
1、图像不清楚或倾斜,无法操作
2、若最右侧没有竖线会丢失最后一列
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)