图片表格识别错列+word读取表格无法读取合并单元格问题解决方案(代码绕行)
评论
收藏

图片表格识别错列+word读取表格无法读取合并单元格问题解决方案(代码绕行)

经验分享
土豆
2024-06-28 10:57·浏览量:1068
土豆
发布于 2024-06-26 10:49更新于 2024-06-28 10:571068浏览

1.图片表格识别错列

背景:使用ocr识别图片表格时,识别内容基本还是OK的,但是输出表格的时候会出现错列的问题,这个在实际使用中会影响对具体列的操作

解决方案:找了一些解决方案,一个是使用其他ocr识别,一个是把图片表格按每个单元格分割为图片再单独识别,然后生成一个列表再做写入

代码实现:

代码没封装,要自己调试一下,因为会产生临时文件,可以自己不删除文件然后去多尝试一些ocr,尝试过最后用微信ocr识别率最高,但是如果找到好的中文包,tesseract理论上才是最好的

# 使用提醒:
# 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能
# 2. package包提供访问当前应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能
# 3. 当此模块作为流程独立运行时执行main函数
# 4. 可视化流程中可以通过"调用模块"的指令使用此模块

import xbot
from xbot import print, sleep
from .import package
from .package import variables as glv



def main(args):
    pass


from xbot_extensions import we_chat
import cv2
import numpy as np
import math
import re
import os
from openpyxl import load_workbook


# 文件路径不要有中文
output_path = r"D:\opencv_test\test.xlsx" #文件保存路径
src=r"D:\opencv_test\test.png" #图片路径
temp_path = r"D:\opencv_test" #切割图片临时存放

# 创建一个新的 Excel 工作簿
wb = load_workbook(output_path)
 
# 选择默认的工作表
ws = wb.active


# 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)

# 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])
print(y_point_arr)

# 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 = binary[y_point_arr[i]:y_point_arr[i + 1], x_point_arr[j]:x_point_arr[j + 1]]


        # 微信离线ocr识别文本
        # 将二值化图像保存为本地的 JPG 文件
        # {'taskId': 1, 'ocrResult': [{'text': '序号', 'location': {'left': 8.326155, 'top': 11.921338, 'right': 68.00881, 'bottom': 45.424667}, 'pos': {'x': 9.287486, 'y': 11.921338}}]}
        file_path = f'{temp_path}\\{i}{j}.png'
        cv2.imwrite(file_path, cell)
        text1 = we_chat.wechat_ocr(file_path,0)
        print(text1)
        if len(text1['ocrResult']) == 0:
            text1 = ''
        else:
            text1 = text1['ocrResult'][0]['text']
        # 删除临时文件
        os.remove(file_path)



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

# 数据写入表格
for row in data:
    ws.append(row)

# 保存修改后的 Excel 文件
wb.save(output_path)

2.word读取表格无法读取合并单元格

背景:当前标准指令无法直接读取含有合并单元格的word表格

解决方案:直接用代码读取,docx库可以一次读取所有表格,但是无法读取doc文件,可以先把文件另存为docx文件再读取表格

代码实现:

安装一下python-docx,

import docx 

def ReadDocx(file):
    doc = docx.Document(file)
    data = []
    for table in doc.tables:
        data.append([])
        for row in table.rows:
            data[-1].append([])
            for cell in row.cells:
                data[-1][-1].append(cell.text)
    return data


收藏2
全部评论1
最新
发布评论
评论