python图片表格单元格切分算法

  • 切分思路
  • 生成表格文件
  • 寻找表格的范围和最小点
  • 查找单元格
  • 寻找坐标的行像素列像素
  • 寻找点周围的单元格

切分思路

首先通过寻找轮廓线的方法找到最大的轮廓线,然后根据轮廓线确定表格的区域,选择坐标最小的点作为种子点通过泛洪填充得到标记的表格图像,通过横向和纵向的腐蚀和膨胀得到横平竖直的表格,再通过蒙特卡洛算法根据表格的坐标范围生成随机点,通过随机点找行像素和列像素,然后找出最接近的标记颜色的坐标,从而定位出该点四周的表格。为了消除个别多余线段的干扰,采用一次验证,验证方法为,通过找到的表格定位中心点,根据中心点的坐标再寻找一次周围表格的坐标,如果两次坐标相同予以采信。不断寻找直到多次寻找不再增加或者超时为止。

生成表格文件

def gen_table_file(imgfile="test.png"):  #  路径不能有中文"""   生成图表框文件   """print("# 找到最大轮廓")pt0=getpt0(imgfile)  img_org = cv.imread(imgfile, cv.IMREAD_COLOR)print("# 获取种子点。。。")seed_point = pt0  # 坐标new_val = (0, 0, 255)  # 赋新值BGRlower_diff =(30, 30, 30)# (30, 30, 30)  # 下灰阶差up_diff = (200, 200, 200)#(50, 50, 50)# (30, 30, 30)  # 上灰阶差# mask图片h, w = img_org.shape[:2]img_mask = np.zeros([h + 2, w + 2], np.uint8)  # 需要大一点img_copy = img_org.copy()  # 会覆盖原图# 3.执行处理print("# 标记表格为红色。。。")cv.floodFill(img_copy, img_mask, seed_point, new_val, lower_diff, up_diff,flags=4 | (255 << 8) | cv.FLOODFILL_FIXED_RANGE)#             flags=4 | (255 << 8) | cv.FLOODFILL_FIXED_RANGE)  # 模式 4连通 + 255白色 + 区域计算# 4.显示结果#cv.imshow("img_mask", img_mask)#cv.imshow("img_org", img_org)#cv.imshow("img_copy", img_copy)x,y,z=img_copy.shaperes=img_copy.reshape(x*y*z)         # 变成一维了print("# 生成红色蒙板...")mask=np.zeros(x*y*z).astype("uint8").reshape(x*y,z)  # 变成2维mask=mask+np.array([0,0,255],dtype='uint8')      #   生成红色蒙板#print(mask[:20])mask=mask.reshape(x*y*z)print("# 蒙板运算获取红色区域")new=(res==mask).astype("uint8")new=new.reshape(x*y,z)new=np.apply_along_axis(lambda x:x[0]*x[1]*x[2],1,new)   #  全1为1res=res.reshape(x*y,z)new2=np.vstack((new,new))new=np.vstack((new,new2)).T   #  转置了#print(res.shape,new.shape)new=new.reshape(x*y*z)res=res.reshape(x*y*z)res=np.multiply(new,res)#res=np.array([np.array([0,0,255],dtype='uint8') if (x==new_val).all() else np.array([255,255,255],dtype='uint8') for x in res ])res=res.reshape(x,y,z)#cv.imshow("img_contour", res)print("# 保存表格框图片")#dst = cv.fastNlMeansDenoisingColored(res,None,10,10,7,21)#res=cv.GaussianBlur(res, (3, 3), 0)#cv.pyrMeanShiftFiltering(res, 20, 100) ##res=cv.pyrMeanShiftFiltering(res, 30, 100)res=ero_dialation(res)cv.imwrite("table.png",res)    #  到这里都是不错的

寻找表格的范围和最小点

def get_max_contour(imgfile):"""   找到最大的轮廓,注意白色被认为是背景色   """img = cv2.imread(imgfile)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)gray_temp = gray.copy()ret, dst = cv2.threshold(gray_temp, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)   #   二值化gray_temp=255-dst      #   反色处理了contours, hierarchy = cv2.findContours(gray_temp, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)area=[]for i in range(len(contours)):area.append(cv2.contourArea(contours[i]))max_idx = np.argmax(area)return contours[max_idx]def getpt0(imgfile):"""   得到最大轮廓的最左上的位置   """maxcontour=get_max_contour(imgfile)pt0=process_contour(maxcontour)return pt0
def get_region(imgfile):maxcontour=get_max_contour(imgfile)region=get_range(maxcontour)return region

查找单元格

def get_rects_in_table(tablepng,rang):res=[]x0,y0,x1,y1=rangtimeout=90t0=time.time()l=0cnt=0while time.time()-t0<timeout:#low、high、sizexs=np.random.randint(x0,x1,100)ys=np.random.randint(y0,y1,100)pts=np.vstack((xs,ys))pts=pts.Tfor pt in pts:ret=get_rect_around_pt(tablepng,pt)# 根据找到的点,计算矩形的中心的,根据中心点重新计算rect,如果两者是一致的那么予以保留,反之抛弃之if ret is not None:xx1,yy1,xx2,yy2=retpt_new=((xx1+xx2)//2,(yy1+yy2)//2)ret_2=get_rect_around_pt(tablepng,pt_new)if ret not in res and ret_2==ret:res.append(ret)if l==0:print(f"第一轮找到{len(res)}个单元格。")if l==len(res):cnt+=1print(f"第{cnt}次区域不再增加。")else:cnt=0l=len(res)print("找到新区域。")if cnt>10:breakreturn res

寻找坐标的行像素列像素

def get_row_col_at_xy(pt,narray):"""   得到图片某点处的行像素集和列像素集   """h,w,z=narray.shape  #  高宽通道数,高--行数,宽--xx,y=ptnarr=narray.reshape(h,w*z)row=narray[y].reshape(w,z)#行col=narray[:,x].reshape(h,z)# 列return row,col

寻找点周围的单元格

def get_rect_around_pt(imgarr,pt,color=[0,0,255]):"""   如果存在0,那么刚好在线上,数据抛弃如果存在一正一负,取正的最小,负的最大,加上减去的就是对应的坐标   """row,col=get_row_col_at_xy(pt,imgarr)  #  行像素,列像素rflag=(row==color).astype(int)  #  判断3个通道的值是否一致rnew=np.apply_along_axis(lambda x:x[0]*x[1]*x[2],axis=1,arr=rflag) #  全部为1才为1result1=np.where(rnew==1)[0]-pt[0]   #  找到等于1的那个标号,就是坐标的值,再和当前点的坐标进行比较,得出距离if 0 in result1: return None   # 刚好在线上抛弃#print(result1)try:x1,x2=(result1[np.where(result1<0)].max()+pt[0],result1[np.where(result1>0)].min()+pt[0]) #  x1,x2  取正的最小,负的最大,except:return None#下面操作同上面cflag=(col==color).astype(int)cnew=np.apply_along_axis(lambda x:x[0]*x[1]*x[2],axis=1,arr=cflag)result2=np.where(cnew==1)[0]-pt[1]if 0 in result2: return None#print(result2)try:  #  可能出现不规则区域,导致pt在图表外,因此找不到符合要求的两个点y1,y2=(result2[np.where(result2<0)].max()+pt[1],result2[np.where(result2>0)].min()+pt[1]) # y1,y2except:return None#print(x1,y1,x2,y2)return [x1,y1,x2,y2]

##主程序

if __name__ == '__main__':#pytesseract.image_to_string(image,lang="",config="")"""测试输入为带有表格的imgfile,只考虑了识别最大的那个表格,首先通过imgfile,生成table.png,然后根据table.png来找到横线竖线,得到相应的坐标,并进行切分   """imgfile="test.png" #  路径不能有中文gen_table_file(imgfile)  # 生成了只含table的文件。targetfile=r"table.png"target = cv2.imread(targetfile) # trainImageregion=get_region(imgfile)#get_rect_around_pt(target,[365,180])print(f"单元格寻找区域:{region}")ret=get_rects_in_table(target,region)print(len(ret))tmpdir="cropped"if os.path.exists(tmpdir) and os.path.isdir(tmpdir):passelse:os.mkdir(tmpdir)result=[]ret=sorted(ret,key=lambda x:x[0])ret=sorted(ret,key=lambda x:x[1])print(ret)  # 此处进行了排序!二次排序,先排x1,再排y1for i,reg in enumerate(ret):x0,y0,x1,y1=regcropped=PIL.Image.open(imgfile).crop([x0+1,y0+1,x1,y1])fnm=f"{tmpdir}\\cropped_{i:03d}.jpg"cropped.save(fnm)#img=cv.imread(fnm)img=np.array(cropped)dst = cv.fastNlMeansDenoisingColored(img,None,10,10,7,21)#txt=pytesseract.image_to_string(dst, lang='chi_sim')txt=get_string(dst)#print(str(sn)+":",txt.strip())result.append(str(i)+":"+txt.strip())print("\n".join(result))

具体代码可以见我上传的资源。

python图片表格单元格切分相关推荐

  1. python合并word表格单元格_Python-Excel转word表格并合并流程

    工作中正好接到个小项目需要将Excel数据导出组成word表格并合并所有表格成一个word文档,这个流程涉及到Excel的解析.Word文档的数据插入,多个Word文档的合并,对Word文档插入图片等 ...

  2. python颜色表_python docx设置表格单元格背景和文本颜色

    我正在使用python 2.7和docx,我想根据条件更改表格中单元格的背景和文本颜色.python docx设置表格单元格背景和文本颜色 我找不到任何关于单元格格式化的有用资源 有什么建议吗? 编辑 ...

  3. openxlpy 在excel中批量插入图片 根据单元格内容插入图片 图片随单元格大小变化而变化 AnchorMarker python

    需求: 根据单元格的文本内容,插入相同名称的图片: 图片大小与单元格大小相同 要用到OS库和openxlpy库 步骤: 遍历excel区域里面的单元格,看是否有文本内容 根据文本内容确定图片的名称,从 ...

  4. Excel根据表格内容批量导入指定图片到单元格

    如下图所示想根据姓名列导入对应的图像列内容,看小编如何操作呢,请看动图演示 (方方格子插件) 1.选择图片工具按钮 2.选择根据内容导入图片 ​ 3.选择图片名的拉选按钮 4.拉选图片名单元格 ​ 5 ...

  5. 总结Python设置Excel单元格样式的一切,比官方文档还详细。

    Python对Excel表格处理非常方便,本文专门对Excel单元格样式设置进行总结,日常用到的设置基本都可以用openpyxl库完成. 创建一个表格 openpyxl是第三方库,如果你还没有安装,输 ...

  6. ppwjs之bootstrap表格:String.到表头单元格元素 和 String.到表格单元格元素

    2019独角兽企业重金招聘Python工程师标准>>> <!DOCTYPT html> <html><head><meta http-equ ...

  7. html table设置行高_html 表格单元格的宽度和高度的设置方法

    做网页的时候,经常会碰到表格宽度对不齐的问题.详细地看了html中表格标签table的高度和宽度设置的细节,现总结如下: 1.table中的width和height设置及其作用:table中设置的he ...

  8. python实现excel单元格合并_python进行excel单元格合并逆操作

    python进行excel单元格合并逆操作.利用anaconda3中的 pandas对包含合并单元格的表进行预处理,完成取消合并单元格的操作. 目标 通过处理表格A,得到表格B. 图1(通过处理表格A ...

  9. html中如何定义斜框,html表格单元格添加斜下框线的方法

    一.分隔单元格的方法 1.用"transform: rotate(-55deg);"把一条水平线旋转一定角度就成斜线了 2.利用以下命令调整分割线位置等. :after :befo ...

最新文章

  1. Linux 内核环境搭建花絮
  2. IOS开发笔记4-C语言基础复习
  3. 8/人天,小记一次 JAVA(APP后台) 项目改造 .NET 过程(后台代码已完整开源于 Github)...
  4. Vue010_ 过滤器
  5. Django从理论到实战(part29)--Field的常用参数
  6. 重磅!!!微软发布.NET Core 2.2
  7. linux找不到动态链接库 .so文件的解决方法
  8. c语言比较大小 谁大选谁,C语言比较优先级
  9. Shell编程(逻辑判断、文件目录属性判断、if特殊用法、case判断)
  10. Integer你真的了解吗,快来瞅瞅吧
  11. 根据控件ID得到句柄
  12. Mongodb系列:初识Mongodb
  13. axios 同时多个请求_Axios是什么?用在什么场景?如何使用?
  14. Qt环境下利用opencv逐帧播放视频
  15. Windows 远程桌面(RDP)客户端相关工具
  16. 如何保证库存在高并发的场景下是安全的
  17. 21个深度学习开源数据集分类汇总
  18. Oracle Coherence中文教程三:配置
  19. 热敏电阻、RTD、热电偶的原理和特性
  20. js实现公历(阳历)和农历(阴历)的换算

热门文章

  1. linux卸载nginx
  2. SQL报错: > ORA-00918: column ambiguously defined
  3. 小米手机无法连接eclipse调试解决方案
  4. 数据探索分析-EDA
  5. java hincrby_使用Redis构建文章投票网站(Java)
  6. java毕业生设计电子商城系统计算机源码+系统+mysql+调试部署+lw
  7. 最新笑话_逗牙搞笑网_交通灯坏了伤不起
  8. 简述关系数据库的数据完整性规则_什么是数据库关系的完整性?
  9. Unity3D-黑魂复刻学习-(1)玩家输入模块
  10. 完全搞定iframe(框架)里的滚动条!(一)