python-opencv表格识别

简介: python-opencv表格识别

最近学习了一下opencv,做了个简单的小东西,就是识别图片中的表格,识别完成后再把数据写入到csv中保存起来。

环境准备:

下面先说下我们应该要准备下啥环境:
1.python安装完成(笔者python3.7)
2.tesseract(google的开源cr框架)
3.pytesseract(python对tesseract的封装,调用时是通过pytesseract去调用tesseract)
4.python的一些类库,numpy,matplotlib
5.特别提一下要导入opencv的包,安装的时候名称是opencv-python,使用的时候名称是cv2,
cv2不是说是opencv的版本二哦,意思是在cv的基础上做了提升和优化的意思,跟版本没关系。
这里还有一点要注意的,__使用cv2报错的话,可能还要安装一下opencv-python-headless。__

识别步骤:

我们先来简单说一下原理,是怎么识别表格的呢?是这样的,如果直接咱们把一张图片用tesseract去识别成中文,它会把表格的横竖线都算进去,
很多汉字都识别不出来,效果也很难看。所以我们要做的前置步骤就是识别出excel图片的一个个单元格,把每个单元格中的信息给识别出来,然后拼接
成一个csv,在最后转为excel只需要通过excel导入csv的数据就可以了。

注意事项:本人水平有限,目前还只能处理比较简单的方方正正的表格,下面的程序是可直接跑的。但是如果有一些图片的表格是拍出来斜着的,或有干扰物
比如有支笔在图片中,或有很复杂的水印,这种目前还处理不了,还在继续研究当中。有兴趣的小伙伴可以一起玩啊,加个微信一起讨论交流。

不过咱们也对这些情况有一些方案,还在处理当中:
1.如果表格是倾斜的咱们可以使用透射变换先将表格处理成正常的矩形;
2.简单的水印,可以通过灰度之后,选个合理的阈值,将图片二值化后,白黑图可以去掉水印。

这里咱们安利一个很好的python-opencv的入门教程:github地址

好了废话说完了,开始教程:
原图:

1.读入图片灰度化:

可以理解为把彩色图片变为灰色图片

raw = cv2.imread(src, 1)
# 灰度图片
gray = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)

2.图片二值化:

可以理解为把图片变成只有黑白两种颜色,这样更方便处理,再说咱们处理表格也不需要颜色

binary = cv2.adaptiveThreshold(~gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 35, -5)
# 展示图片
cv2.imshow("binary_picture", binary)

二值化的图片:

3.识别出横线,竖线:

在此之后,如果图像不够清晰或者有小像素点,可以使用腐蚀,膨胀等操作让图片更清晰一点

rows, cols = binary.shape
scale = 40
# 自适应获取核值
# 识别横线:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (cols // scale, 1))
eroded = cv2.erode(binary, kernel, iterations=1)
dilated_col = cv2.dilate(eroded, kernel, iterations=1)
cv2.imshow("excel_horizontal_line", dilated_col)

# 识别竖线:
scale = 20
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, rows // scale))
eroded = cv2.erode(binary, kernel, iterations=1)
dilated_row = cv2.dilate(eroded, kernel, iterations=1)
cv2.imshow("excel_vertical_line:", dilated_row)

横线竖线的图:

4.计算出横竖线的焦点,就得到了每个单元格的坐标

# 将识别出来的横竖线合起来
bitwise_and = cv2.bitwise_and(dilated_col, dilated_row)
cv2.imshow("excel_bitwise_and", bitwise_and)

# 标识表格轮廓
merge = cv2.add(dilated_col, dilated_row)
cv2.imshow("entire_excel_contour:", merge)

# 两张图片进行减法运算,去掉表格框线
merge2 = cv2.subtract(binary, merge)
cv2.imshow("binary_sub_excel_rect", merge2)

new_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
erode_image = cv2.morphologyEx(merge2, cv2.MORPH_OPEN, new_kernel)
cv2.imshow('erode_image2', erode_image)
merge3 = cv2.add(erode_image, bitwise_and)
cv2.imshow('merge3', merge3)

# 将焦点标识取出来
ys, xs = np.where(bitwise_and > 0)

焦点图:

5.将坐标筛选下,临近的几个算一个:

这里说一下图片的数组中是(y,x)这样的,y在前面

# 横纵坐标数组
y_point_arr = []
x_point_arr = []
# 通过排序,排除掉相近的像素点,只取相近值的最后一点
# 这个10就是两个像素点的距离,不是固定的,根据不同的图片会有调整,基本上为单元格表格的高度(y坐标跳变)和长度(x坐标跳变)
i = 0
sort_x_point = np.sort(xs)
for i in range(len(sort_x_point) - 1):
    if sort_x_point[i + 1] - sort_x_point[i] > 10:
        x_point_arr.append(sort_x_point[i])
    i = i + 1
# 要将最后一个点加入
x_point_arr.append(sort_x_point[i])

i = 0
sort_y_point = np.sort(ys)
# print(np.sort(ys))
for i in range(len(sort_y_point) - 1):
    if (sort_y_point[i + 1] - sort_y_point[i] > 10):
        y_point_arr.append(sort_y_point[i])
    i = i + 1
y_point_arr.append(sort_y_point[i])

6.通过坐标把每个单元格图像取出来,然后使用pytesseract识别文字 :去除特殊符号后,data就是处理好的值

# 循环y坐标,x坐标分割表格
data = [[] for i in range(len(y_point_arr))]
for i in range(len(y_point_arr) - 1):
    for j in range(len(x_point_arr) - 1):
        # 在分割时,第一个参数为y坐标,第二个参数为x坐标
        cell = src[y_point_arr[i]:y_point_arr[i + 1], x_point_arr[j]:x_point_arr[j + 1]]
        cv2.imshow("sub_pic" + str(i) + str(j), cell)

        # 读取文字,此为默认英文
        # pytesseract.pytesseract.tesseract_cmd = 'E:/Tesseract-OCR/tesseract.exe'
        text1 = pytesseract.image_to_string(cell, lang="chi_sim+eng")

        # 去除特殊字符
        text1 = re.findall(r'[^\*"/:?\\|<>″′‖ 〈\n]', text1, re.S)
        text1 = "".join(text1)
        print('单元格图片信息:' + text1)
        data[i].append(text1)
        j = j + 1
    i = i + 1

6.最后把所有的信息写入csv

path是要写入的文件路径,data是数据

with open(path, "w", newline='') as csv_file:
      writer = csv.writer(file, dialect='excel')
      for index, item in enumerate(data):
          if index != 0 and index != len(data) - 1:
              writer.writerows([[item[0], item[1], item[2], item[3], item[4], item[5]]])

写入表格数据:

总结:

1.完成之后就大致知道了表格识别的原理,并且对opencv的api有了一定的了解和熟悉,这里放上github的地址:项目地址,觉得还可以点点star,fork啥的哈。
2.不过这个介绍是说完了大致流程,其实过程中还有遇到很多坑,直接运行github的项目有可能跑出的结果和我不一样,
那是因为一个是要下载tesseract的中文数据集,第二是这个里面数学和几个文字竟然识别不出来,需要手动给tesseract增加
一些训练集。这个增加训练数据集应该后面会再出一篇文章。
3.弄完这个表格识别,准备在看下图片矫正和去除水印,复杂的表格识别也会使用到的。

参考资料:

1.https://github.com/tesseract-ocr/tesseract
2.https://pypi.org/project/pytesseract/
3.https://blog.csdn.net/muxiong0308/article/details/80969355
4.https://www.cnblogs.com/HL-space/p/10547259.html

相关文章
|
4月前
|
数据挖掘 Python
【Python】已解决:Python pandas读取Excel表格某些数值字段结果为NaN问题
【Python】已解决:Python pandas读取Excel表格某些数值字段结果为NaN问题
352 0
|
6月前
|
存储 NoSQL MongoDB
MongoDB数据库转换为表格文件的Python实现
MongoDB数据库转换为表格文件的Python实现
212 0
|
4月前
|
关系型数据库 MySQL 数据库
使用Python读取xlsx表格数据并导入到MySQL数据库中时遇到的问题24
【7月更文挑战第24天】使用Python读取xlsx表格数据并导入到MySQL数据库中
61 7
|
5月前
|
数据采集 Web App开发 数据挖掘
使用Python和BeautifulSoup轻松抓取表格数据
使用Python和BeautifulSoup,结合代理IP,可以从网页抓取表格数据,如中国气象局的天气信息。通过requests库发送HTTP请求,BeautifulSoup解析HTML提取表格。安装必要库后,设置代理IP,发送请求,解析HTML找到表格,提取数据并存储。通过Pandas进行数据分析,如计算平均气温。这种方法让数据抓取和分析变得更加便捷。
117 3
使用Python和BeautifulSoup轻松抓取表格数据
|
4月前
|
数据格式 Python
Python代码示例,读取excel表格,将行数据转为列数据。(10)
【7月更文挑战第10天】Python代码示例,读取excel表格,将行数据转为列数据。
139 2
|
6月前
|
数据挖掘 数据处理 Python
【Python DataFrame 专栏】Python DataFrame 入门指南:从零开始构建数据表格
【5月更文挑战第19天】本文介绍了Python数据分析中的核心概念——DataFrame,通过导入`pandas`库创建并操作DataFrame。示例展示了如何构建数据字典并转换为DataFrame,以及进行数据选择、添加修改列、计算统计量、筛选和排序等操作。DataFrame适用于处理各种规模的表格数据,是数据分析的得力工具。掌握其基础和应用是数据分析之旅的重要起点。
75 2
【Python DataFrame 专栏】Python DataFrame 入门指南:从零开始构建数据表格
|
4月前
|
Python
【Python】已解决:(Python写入Excel表格报错)‘NoneType’ object has no attribute ‘write’
【Python】已解决:(Python写入Excel表格报错)‘NoneType’ object has no attribute ‘write’
206 0
|
6月前
|
数据采集 存储 数据挖掘
Python DataFrame初学者指南:轻松上手构建数据表格
【5月更文挑战第19天】本文是针对初学者的Pandas DataFrame指南,介绍如何安装Pandas、创建DataFrame(从字典或CSV文件)、查看数据(`head()`, `info()`, `describe()`)、选择与操作数据(列、行、缺失值处理、数据类型转换、排序、分组聚合)以及保存DataFrame到CSV文件。通过学习这些基础,你将能轻松开始数据科学之旅。
|
6月前
|
存储 数据采集 数据可视化
Python列表到Excel表格第一列的转换技术详解
Python列表到Excel表格第一列的转换技术详解
95 0
|
6月前
|
数据挖掘 数据处理 Python
【亮剑】介绍了Python中以表格格式打印列表的三种方法
【4月更文挑战第30天】本文介绍了Python中以表格格式打印列表的三种方法:1) 使用字符串格式化,适用于简单场景;2) 使用prettytable库,适合需要更多格式化选项的情况;3) 使用pandas库,适用于处理大量数据和复杂分析。根据需求选择合适的方法来展示数据。
317 0