效果图如下:
对于任意图标都不需要自定义模板,直接程序生成,不过需要注意,图中的表格必须是水平的,无法适配倾斜的表格。
直接上代码:
import cv2
import numpy as np
import math
import xlwt
src='图片路径'
raw = cv2.imread(src, 1)
# 灰度图片
gray = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)
binary = cv2.adaptiveThreshold(~gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 35, -5)
# 展示图片
rows, cols = binary.shape
scale2=15
scale = 20
# 自适应获取核值
# 识别横线:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (cols // scale, 1))
kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (cols // scale2, 1))
eroded = cv2.erode(binary, kernel, iterations=1)
dilated_col = cv2.dilate(eroded, kernel1, iterations=1)
# cv2.imwrite("横线图.jpg", dilated_col)
# 识别竖线:
# scale = 40#scale越大,越能检测出不存在的线
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (1, rows // scale2))
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, rows // scale))
eroded = cv2.erode(binary, kernel, iterations=1)
dilated_row = cv2.dilate(eroded, kernel2, iterations=1)
# cv2.imwrite("竖线图.jpg", dilated_row)
# cv2.imwrite("3.png", dilated_row)
# 将识别出来的横竖线合起来
bitwise_and = cv2.bitwise_and(dilated_col, dilated_row)#对二值图进行与操作
# cv2.imwrite("交点二值图.jpg", bitwise_and)
# 标识表格轮廓
merge = cv2.add(dilated_col, dilated_row)
ret,binary = cv2.threshold(merge, 127, 255, cv2.THRESH_BINARY)
_,contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
area=[]
for k in range(len(contours)):
area.append(cv2.contourArea(contours[k]))
max_idx = np.argmax(np.array(area))
m_d_r=[]
m_u_l=[]
max_p=0
min_p=1e6
for l1 in contours[max_idx]:
for l2 in l1:
if sum(l2)>max_p:
max_p=sum(l2)
d_r=l2
if sum(l2)<min_p:
min_p=sum(l2)
u_l=l2
m_d_r=d_r
m_u_l=u_l
padding=5
x0=max(m_u_l[0]-padding,0)
x1=min(m_d_r[0]+padding,raw.shape[1])
y0=max(m_u_l[1]-padding,0)
y1=min(m_d_r[1]+padding,raw.shape[0])
bitwise_and_crop=bitwise_and[y0:y1,x0:x1]
merge=merge[y0:y1,x0:x1]
raw=raw[y0:y1,x0:x1]
# # 两张图片进行减法运算,去掉表格框线
# merge2 = cv2.subtract(binary, merge)
# cv2.imwrite("去表格图.jpg", merge2)
# new_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
# erode_image = cv2.morphologyEx(merge2, cv2.MORPH_OPEN, new_kernel)#先腐蚀,再膨胀
# cv2.imwrite('腐蚀膨胀后的图.jpg', erode_image)
# merge3 = cv2.add(erode_image, bitwise_and)
# cv2.imwrite('角点带字.jpg', merge3)
# 将焦点标识取出来
ys, xs = np.where(bitwise_and_crop > 0)
# print(xs)
# # print('---------------------------------')
# print(ys)
# 横纵坐标数组
y_point_arr = []
x_point_arr = []
# 通过排序,排除掉相近的像素点,只取相近值的最后一点
# 这个10就是两个像素点的距离,不是固定的,根据不同的图片会有调整,基本上为单元格表格的高度(y坐标跳变)和长度(x坐标跳变)
i = 0
sort_x_point = np.sort(xs)
# print(sort_x_point)
for i in range(len(sort_x_point) - 1):
if sort_x_point[i + 1] - sort_x_point[i] > 3:
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)
for i in range(len(sort_y_point) - 1):
if sort_y_point[i + 1] - sort_y_point[i] > 3:
y_point_arr.append(sort_y_point[i])
i = i + 1
y_point_arr.append(sort_y_point[i])
h_list=[y_point_arr[i+1]-y_point_arr[i] for i in range(len(y_point_arr)-1)]
w_list=[x_point_arr[i+1]-x_point_arr[i] for i in range(len(x_point_arr)-1)]
col_alpha=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
print(h_list)
print(w_list)
import xlsxwriter
workbook = xlsxwriter.Workbook('chineseQA.xlsx') #创建工作簿
worksheet = workbook.add_worksheet()
for i in range(len(w_list)):
worksheet.set_column('{}:{}'.format(col_alpha[i],col_alpha[i]),w_list[i]/6)
for j in range(len(h_list)):
worksheet.set_row(j,h_list[j])
def islianjie(p1,p2,img):#p的格式是先y后x
if p1[0]==p2[0]:
for i in range(min(p1[1],p2[1]),max(p1[1],p2[1])+1):
if sum([img[j,i] for j in range(max(p1[0]-5,0),min(p1[0]+5,img.shape[0]))])==0:
return False
return True
elif p1[1]==p2[1]:
for i in range(min(p1[0],p2[0]),max(p1[0],p2[0])+1):
if sum([img[i,j] for j in range(max(p1[1]-5,0),min(p1[1]+5,img.shape[1]))])==0:
return False
return True
else:
return False
class cell:
def __init__(self,lt,rd,belong):
self.lt=lt
self.rd=rd
self.belong=belong
lt_list_x=x_point_arr[:-1]
lt_list_y=y_point_arr[:-1]
rd_list_x=x_point_arr[1:]
rd_list_y=y_point_arr[1:]
d={
}
for i in range(len(lt_list_x)):
for j in range(len(lt_list_y)):
d['cell_{}_{}'.format(i,j)]=cell([lt_list_x[i],lt_list_y[j]],[rd_list_x[i],rd_list_y[j]],[lt_list_x[i],lt_list_y[j]])
for i in range(len(lt_list_x)):
for j in range(len(lt_list_y)):
p1=[d['cell_{}_{}'.format(i,j)].rd[1],d['cell_{}_{}'.format(i,j)].lt[0]]#左下点
p2=[d['cell_{}_{}'.format(i,j)].rd[1],d['cell_{}_{}'.format(i,j)].rd[0]]#右下点
p3=[d['cell_{}_{}'.format(i,j)].lt[1],d['cell_{}_{}'.format(i,j)].rd[0]]#右上点
if not islianjie(p1,p2,merge):
d['cell_{}_{}'.format(i,j+1)].belong=d['cell_{}_{}'.format(i,j)].belong
if not islianjie(p2,p3,merge):
d['cell_{}_{}'.format(i+1,j)].belong=d['cell_{}_{}'.format(i,j)].belong
crop_list={
}
for i in range(len(lt_list_x)):
for j in range(len(lt_list_y)):
crop_list['{},{}'.format(d['cell_{}_{}'.format(i,j)].belong[0],d['cell_{}_{}'.format(i,j)].belong[1])]=d['cell_{}_{}'.format(i,j)].rd
w_h_list=[]
zmax=0
zmin=1e6
zlt=[]
zrd=[]
for key in crop_list.keys():
lt=[int(i) for i in key.split(',')]
rd=crop_list[key]
# print(lt,rd)
if sum(rd)>zmax:
zrd=rd
zmax=sum(rd)
if sum(lt)<zmin:
zlt=lt
zmin=sum(lt)
cv2.imwrite('crop/{}.jpg'.format(key),raw[lt[1]:rd[1],lt[0]:rd[0]])
merge_format = workbook.add_format({
'bold': True,
'border': 6,
'align': 'center',#水平居中
'valign': 'vcenter',#垂直居中
'fg_color': '#D7E4BC',#颜色填充
})
for key in crop_list.keys():
lt=[int(i) for i in key.split(',')]
rd=crop_list[key]
lt_=[lt[0]-zlt[0],lt[1]-zlt[1]]
rd_=[rd[0]-zlt[0],rd[1]-zlt[1]]
print(lt_)
print(rd_)
for i in range(len(w_list)+1):
if lt_[0]==sum(w_list[:i]):
lt_col=chr(ord('A')+i)
if rd_[0]==sum(w_list[:i]):
rd_col=chr(ord('A')+i-1)
for i in range(len(h_list)+1):
if lt_[1]==sum(h_list[:i]):
lt_row=i+1
if rd_[1]==sum(h_list[:i]):
rd_row=i
if lt_col==rd_col and lt_row==rd_row:
worksheet.write('{}{}'.format(lt_col,lt_row),'',merge_format)
else:
worksheet.merge_range('{}{}:{}{}'.format(lt_col,lt_row,rd_col,rd_row),'',merge_format)
workbook.close()
文章浏览阅读1.1w次。一.JAVAVM 组件 说明 有关Oracle 所有组件的概述,参考:Oracle 8i/9i/10g/11g 组件(Components) 说明http://blog.csdn.net/tianlesoftware/article/details/5937382 现在我们查看组件的信息:SQL> col comp_id for a15SQL> col version for a15SQL> co_java vm组件更新
文章浏览阅读1.9k次,点赞2次,收藏4次。Spring Boot Actuator 未授权的测试与利用思路0x0 前言 最近遇到的一个漏洞,但是因为目标关掉了一些端点导致没利用起来达到RCE的效果,不过在提升漏洞危害的时候,参考了不少文章,也做了一些尝试,所以分享出来自己的经历,希望大家如果遇到跟我一样的情况,可以省下自己调试时间,来做更有意义的事情。0x1 Actuator 简介官方简介: Spring Boot Actuator: Production-ready FeaturesSpring Bo..._sb-actuator
文章浏览阅读1.3k次。在python3.7+vs2019环境下使用f2py将fortran和c++程序编译为python库前言步骤1安装Fortran和Visual Studio编译环境2配置vs在python中的路径3测试c++编译环境4测试Fortran编译环境参考链接前言今天务必开贴记录下将Fortran或c++程序编译为python库的方法。起因是老师给了一个Fortran函数,无奈本人看不懂,因而想办法..._python调用fortran代码
文章浏览阅读1.3k次。uboot中如果支持spi/qspi flash, 那么可以使用sf的erase, read, write命令操作spi flashsf read用来读取flash数据到内存sf write写内存数据到flashsf erase 擦除指定位置,指定长度的flash内容, 擦除后内容全1以备份uboot文件举例:1 、设置环境变量setenv serverip 192.168.230.111setenv ipaddr 192.168.230.124saping 192.168.230.111_uboot备份固件命令
文章浏览阅读965次。看了此文,Oracle SQL优化文章不必再看! 第一章 看了此文,Oracle SQL优化文章不必再看! DBAplus社群 | 2015-11-17 23:44 目录SQL优化的本质 SQL优化Road Map 2.1 制定SQL优化目标 2.2 检查执行计划 2.3 检查统计信息 2.4 检查高效访问结构 2.5 检查影...__optimizer_cost_based_transformation
文章浏览阅读9.3k次。vue 判断页面所有input的值不等于空,提交的时候并给出提示,1.html<input placeholder="必填" alt="开户支行" v-model="bank_branch" :value='bank_branch' />2.js//获取页面所有的inputvar els = document.getElementsByTagName("input"..._vue form判断input不为空
文章浏览阅读1.6k次。题目来源今天做了个题:将一个链表里的数据组装树形结构,链表里的数据已经满足树形结构要求这道题描述的很简单,但是有很多种情况。他只说了链表数据满足树形结构要求,并没有说明数据到底是什么样的,也就是题目参数具有多样性,这样其实我们给出一种解决方案就可以。而且也只要求将链表转换为树,并没有说是什么树。所以这道题说难也难,说简单也简单。解题思路最近也将平衡二叉树的原理看了一下,正好借着这..._链表node转树形接口
文章浏览阅读151次。单一职责原则(Single Responsibility Principle)定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。解决方案:遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责..._b10原则
文章浏览阅读1.2k次。关于mongodb的好处,优点之类的这里就不说了,唯一要讲的一点就是mongodb中有三元素:数据库,集合,文档,其中“集合”就是对应关系数据库中的“表”,“文档”对应“行”。 一: 下载 上MongoDB官网 ,我们发现有32bit和64bit,这个就要看你系统了,不过这里有两点注意: ①:根据业界规则,偶数为“稳定版”(如:1.6.X,1.8.X_传智mongodb
文章浏览阅读6.3k次,点赞2次,收藏16次。常用Python第三方库简介 如果说强大的标准库奠定了Python发展的基石,丰富的第三方库则是python不断发展的保证,随着python的发展一些稳定的第三库被加入到了标准库里面,这里有6000多个第三方库的介绍:点这里或者访问:http://pypi.python.org/pypi?%3Aaction=index。下表中加粗并且标红的都是我平时使用较多的一些第三方库。(P.S.C_python有用第三方库
文章浏览阅读374次。4. Kubernetes集群安装4.1 master节点部署4.1.1 提前下载所需镜像看一下kubernetes v1.15.1需要哪些镜像:$ kubeadm config images list --kubernetes-version=v1.15.1k8s.gcr.io/kube-apiserver:v1.15.1k8s.gcr.io/kube-controller-manager:v1..._kubelet如何指定cni插件目录
文章浏览阅读1.4w次。###图中仅对部分设备ip进行标注,描述如下场景50.237仅能访问171.7但由于安全策略等原因,无法直接访问171.8,因此利用xshell做隧道进行237与171.8之间的通信。###通讯方向说明192.168.50.237-->192.168.171.7-->192.168.171.81.xshell上在打开192.168.171.7的终端后,文件->属性->连接-..._xshell 隧道窗格说明