Python 识别图片中表格

python 进行图片识别,首先需要安装相应的Python库文件和识别引擎tesseract-ocr。
库文件:
1、pytesseract 图片识别库
2、numpy 矩阵库
3、PIL 图像处理库(仅支持到Python2.7)
4、Pillow 图像处理库(支持Python3.0以上)
一、Python 库文件安装方法:
1、命令行安装
pip install pytesseract
   pip install Pillow
2、使用pycharm编辑器安装,具体步骤省略,大家可以百度一下。
二、图片识别引擎tesseract-ocr安装
软件名称:tesseract-ocr-setup-4.00.00dev.exe
下载地址:https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-4.00.00dev.exe
1、Tesseract是开源的OCR引擎。Tesseract最初设计用于英文识别,经过改进引擎和训练系统,它能够处理其它语言和UTF-8字符。Tesseract 3.0能够处理任何Unicode字符,但并非在所有语言上都工作得很好。Tesseract在庞大字符集语言(比如中文)上较慢,但是工作良好。
2、默认不支持中文,在软件安装时一定要选择chi_sim(简体中文),安装成后,可以在

定义字符集,引入相应的类库

    # --- coding:UTF-8 ---
    from skimage import io, data, morphology, segmentation
    import numpy as np
    from PIL import Image
    import pytesseract
    import os

    # pytesser3.tesseract_exe_name="C:/Program Files (x86)/Tesseract-OCR/tesseract.exe"
    #识别图片中的文字
    def img_to_txt(file):
        if os.path.exists(file):
            image = Image.open(file)
            # 英文
            # vcode = pytesseract.image_to_string(image,"eng")
            # txt = pytesser3.image_to_string(image, "chi_sim")
            txt = pytesseract.image_to_string(image, "chi_sim")
            print("{}识别内容:{}".format(file,txt))

 for i in range(16):
             img_file = r"img/pic_{}.jpg".format(i)
             img_to_txt(img_file)
  img_to_txt(r"img/abc.png")

    img = io.imread("test.jpg",True) # as_grey=true 灰度图片
 #二值化
    bi_th=0.81
    img[img<=bi_th]=0
    img[img>bi_th]=1

io.imsave("gray.jpg",img)

膨胀腐蚀操作

def dil2ero(img,selem):
    img=morphology.dilation(img,selem)   # 膨胀
    imgres=morphology.erosion(img,selem) # 腐蚀
    return imgres

求图像中的横线和竖线

rows,cols=img.shape
scale=10   #这个值越大,检测到的直线越多,图片中字体越大,值应设置越小。需要灵活调整该参数。

col_selem=morphology.rectangle(cols//scale,1)
img_cols=dil2ero(img,col_selem)

row_selem=morphology.rectangle(1,rows//scale)
img_rows=dil2ero(img,row_selem)

线图

img_line=img_cols*img_rows
io.imsave("table.jpg",img_line)

点图

img_dot=img_cols+img_rows
img_dot[img_dot>0]=1

io.imsave("table_dot.jpg",img_dot)

收缩点团为单像素点(3×3)

def isolate(imgdot):
    idx=np.argwhere(imgdot<1)  # img值小于1的索引数组
    rows,cols=imgdot.shape

    for i in range(idx.shape[0]):
        c_row=idx[i,0]
        c_col=idx[i,1]
        if c_col+1<cols and c_row+1<rows:
            imgdot[c_row,c_col+1]=1
            imgdot[c_row+1,c_col]=1
            imgdot[c_row+1,c_col+1]=1
        if c_col+2<cols and c_row+2<rows:
            imgdot[c_row+1,c_col+2]=1
            imgdot[c_row+2,c_col]=1
            imgdot[c_row,c_col+2]=1
            imgdot[c_row+2,c_col+1]=1
            imgdot[c_row+2,c_col+2]=1
    return imgdot

img_dot=isolate(img_dot)

io.imsave("table_dot_del.jpg",img_dot)
print(img_dot.shape)  #显示尺寸
print(img_dot.shape[0])  #图片高度
print(img_dot.shape[1])  #图片宽度
# 表格点图
    def get_dot(self):
        self.img_dot2 = self.isolate(self.img_dot)
        io.imsave("table_dot_del.jpg", self.img_dot2)
        return self.img_dot2
 # 分析表格
    def fenxi_dots(self):
        self.dot_idxs=np.argwhere(self.img_dot<1)  # img_dot值等于0的索引数组
        self.table_cols = [] #记录每行有几个单元格
        table_rows = 1
        table_row_index = self.dot_idxs[0][0] #第一行点图y值坐标
        colu_dot = 0   # 单元格数量

        for n,indx in enumerate(self.dot_idxs):
            if indx[0] == table_row_index : # 如果点图y值坐标相同则为同一行
                colu_dot = colu_dot + 1
                print(indx,end=" ")
            else :
                if n < len(self.dot_idxs):
                    self.table_cols.append(colu_dot-1) # 将行单元格数量加入table_cols列表
                    # table_row_index = self.dot_idxs[n+1][0] #记录下一行位置索引
                    table_row_index = indx[0] # 点图y值坐标
                    colu_dot = 1  # 清0后,换行记录单元格数量
                    print("",end="\n")
                    print(indx, end=" ")

        print("")
        for n,v in enumerate(self.table_cols):
            print("row{}:{}".format(n,v))
        self.row_num = len(self.table_cols)
        self.max_row = max(self.table_cols)
        self.min_row = min(self.table_cols)
        self.cell_nums = sum(self.table_cols)
        print("这个表格一共{}行".format(self.row_num))
        print("这个表格最多行单元格数:{}".format(self.max_row))
        print("这个表格最少行单元格数:{}".format(self.min_row))
        print("这个表格一共{}个单元格".format(self.cell_nums))

        # go = input("表格分析是否正确?")
        #
        # if go == "no" :
        # exit(0)

        return self.dot_idxs,self.table_cols
 # 开始识别单元格,分割表格图片
def split_table_pic(self):
   # a_dots =[] #记录已经处理过的A点坐标
   # cells = [] # 记录单元格的A点和D点坐标 [[a11,a12,d11,d12][a21,a22,d21,d22]]]
   # cell_num = 0
   #
   # cell_a = []
   # cell_b = []
   # cell_c = []
   # cell_d = []
   cell_a_x = 0
   cell_b_x = 0
   cell_c_y = 0
   if self.max_row == self.min_row : # 标准表格 n*m
       for n,v in enumerate(self.table_cols):
           print("row{}:".format(n),end= " ")
           for i in range(v):
               row_dot_num = v + 1
               cell_num = n * row_dot_num
               cell_a_index = cell_num + i
               cell_b_index = cell_a_index + 1
               cell_c_index = cell_a_index + row_dot_num
               cell_d_index = cell_c_index +1
               print("cell[{}]:a{} b{} c{} d{}".format(cell_num+i,self.dot_idxs[cell_a_index],
                   self.dot_idxs[cell_b_index],self.dot_idxs[cell_c_index],self.dot_idxs[cell_d_index]),end= " ")
               x1=self.dot_idxs[cell_a_index][1]+1 # 加1去除列边框线
               x2=self.dot_idxs[cell_b_index][1]
               y1=self.dot_idxs[cell_a_index][0]+1 # 加1去除行边框线
               y2=self.dot_idxs[cell_c_index][0]
               #print(x1,x2,y1,y2)
               roi=self.img2[y1:y2,x1:x2] # 50~100 行,50~100 列(不包括第 100 行和第 100 列)
               # 分割原图并保存至img文件夹里,建议将图片保存为png格式,因为JPG不支持透明度
               io.imsave("img/{}_{}.png".format(self.filename[:-4],cell_num+i),roi)
           print("", end="\n")
   else: # 非标准表格
       for n,v in enumerate(self.table_cols):
           print("row{}:".format(n),end= " ")
           for i in range(v):
               row_dot_num = v + 1
               cell_num = n * row_dot_num
               cell_a_index = cell_num + i
               cell_b_index = cell_a_index + 1
               cell_a_x = self.dot_idxs[cell_a_index][1]
               cell_b_x = self.dot_idxs[cell_a_index][1]

               cell_c_index = cell_a_index + row_dot_num
               cell_d_index = cell_c_index +1
               print("cell[{}]:a{} b{} c{} d{}".format(cell_num+i,self.dot_idxs[cell_a_index],
                   self.dot_idxs[cell_b_index],self.dot_idxs[cell_c_index],self.dot_idxs[cell_d_index]),end= " ")
               x1=self.dot_idxs[cell_a_index][1]+1 # 加1去除列边框线
               x2=self.dot_idxs[cell_b_index][1]
               y1=self.dot_idxs[cell_a_index][0]+1 # 加1去除行边框线
               y2=self.dot_idxs[cell_c_index][0]
               #print(x1,x2,y1,y2)
               roi=self.img2[y1:y2,x1:x2] # 50~100 行,50~100 列(不包括第 100 行和第 100 列)
               # 分割原图并保存至img文件夹里,建议将图片保存为png格式,因为JPG不支持透明度
               io.imsave("img/{}_{}.png".format(self.filename[:-4],cell_num+i),roi)
           print("", end="\n")

识别分割后图片内容并写入EXCEL中

 def write_excel(self,img_ocr_sel):
     wbk = xlwt.Workbook()
     sheet = wbk.add_sheet('sheet 1')

     if img_ocr_sel == "BaiDu OCR":
         for n, v in enumerate(self.table_cols):
             for i in range(v):
                 # 当前行单元格数量
                 cur_row_cells = v + 1
                 # 图片序号
                 img_num = n * cur_row_cells + i
                 img_file = r"img/{}_{}.png".format(self.filename[:-4],img_num)
                 txt = self.baidu_img_to_txt(img_file) # 百度文字识别
                 if txt =="" : txt = "0"
                 sheet.write(n, i, txt)  # 第n行第i列写入内容
     else:
         for n, v in enumerate(self.table_cols):
             for i in range(v):
                 # 当前行单元格数量
                 cur_row_cells = v + 1
                 # 图片序号
                 img_num = n * cur_row_cells + i
                 img_file = r"img/{}_{}.png".format(self.filename[:-4],img_num)
                 txt = self.img_to_txt(img_file) #OCR 文字识别
                 if txt =="" : txt = "0"
                 sheet.write(n, i, txt)  # 第n行第i列写入内容
     wbk.save('{}.xls'.format(self.filename[:-4]))
     print("success!")
     self.msg.insert(self.mark, "\n\nsuccess!")
     self.msg.see(self.see_end)
     self.msg.update()
    原文作者:天若有情(爱笑妍)
    原文地址: https://blog.csdn.net/weixin_44499757/article/details/86354033
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞