再来是办公室表单的处理,
假设有些表单只有图像或是只有纸本,
想要汇入成Excel档案时,
我们就可以使用前面所使用的OCR程序来帮助进行转换。
首先,可能有人会问为甚麽不使用OPEN-CV来解析表格的框线,
然後使用每一格送入进行辨识?
表格不一定都有框线,使用pytessert会有辨识率不佳的情况,
如果有50格的表格,使用google client vision成本就大幅提升了50倍(每月前1000张免费,之後每1000张大约30元台币)。
这是我预想中的表格样式,每一条线代表一个字串。
from google.cloud import vision
import io
import os
credential_path = "cred.json"
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credential_path
client = vision.ImageAnnotatorClient()
with io.open('table.png', 'rb') as image_file:
content = image_file.read()
image = vision.Image(content=content)
response = client.text_detection(image=image)
texts = response.text_annotations
print('Texts:')
Xarray=[]
Yarray=[]
TextArray=[]
for text in texts[1:]:
xy0=(text.bounding_poly.vertices[0].x, text.bounding_poly.vertices[0].y)
xy1=(text.bounding_poly.vertices[1].x, text.bounding_poly.vertices[1].y)
xy2=(text.bounding_poly.vertices[2].x, text.bounding_poly.vertices[2].y)
xy3=(text.bounding_poly.vertices[3].x, text.bounding_poly.vertices[3].y)
print(f"{xy0}{xy1}{xy2}{xy3} {text.description}")
Yarray.append([text.bounding_poly.vertices[0].y,text.bounding_poly.vertices[2].y])
Xarray.append([text.bounding_poly.vertices[0].x ,text.bounding_poly.vertices[1].x])
TextArray.append(text.description)
处理表格,我就没有使用第0个的集合元素,
而是後面的元素文字及座标。
每个文字取两个X及两个Y座标为特徵:
采用Kmeans演算法来将字串以Y座标分群,并以silhouette_score找出最将分群数
(假设资料表格列数不超过60,超过的话,可以自行调整60的数值 )
import numpy as np
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
from scipy.signal import find_peaks
Yarray_X=np.array(Yarray)
silhouette_avg = []
for i in range(2,60):
try:
kmeans_fit = KMeans(n_clusters = i,max_iter=500).fit(Yarray_X)
silhouette_avg.append(silhouette_score(Yarray_X, kmeans_fit.labels_))
except:
pass
best_cluster_number,peak_heightsDict=find_peaks(silhouette_avg,height=0.7)
RowNumCategories=best_cluster_number[0]+2
#使用最佳分群数来重新分群
herekmeans = KMeans(n_clusters=RowNumCategories,max_iter=500).fit(Yarray_X)
RowSerialCount=1
row_dict={}
RowactualArray=[]
#这里是将Y座标得到的分群转换成未来写入excel时的第几个row。
for ele in herekmeans.labels_:
if ele not in row_dict:
row_dict[ele]=RowSerialCount
RowSerialCount+=1
RowactualArray.append(row_dict[ele])
X座标,栏位上的转换:
(可自行调整栏位20的数值,但是如果超过26,後续转换到excel字母时,需要再自行调整)
X=np.array(Xarray)
TableColumn=20
silhouette_avg = []
for i in range(2,TableColumn):
kmeans_fit = KMeans(n_clusters = i,max_iter=500).fit(X)
silhouette_avg.append(silhouette_score(X, kmeans_fit.labels_))
category_count = silhouette_avg.index(max(silhouette_avg))+2
print("最佳column分群数::")
print(category_count)
kmeans = KMeans(n_clusters=category_count,max_iter=500).fit(X)
文字X座标,一样使用最佳分群数来分群
cStarRay=[]
for center in kmeans.cluster_centers_:
cStar=(center[0]+center[1])/2
# print(center)
# print(int(cStar))
cStarRay.append(int(cStar))
ReSortStarRay=sorted(cStarRay)
Stardict={}
for star in cStarRay:
StarIndex = cStarRay.index(star)
ReStarIndex = ReSortStarRay.index(star)
Stardict[StarIndex]=ReStarIndex
actualXArray=[]
for ele in kmeans.labels_:
actualXArray.append(Stardict[ele])
Column_actualArray = np.array(actualXArray)
使用kmeans群心来重新排序X座标栏位
我们将文字内容、栏位分群结果、列数分群结果用zip打包
ToExcelZip=zip(TextArray,Column_actualArray,RowactualArray)
将文字写入EXcel,使用openpyxl套件:
安装
pip install openpyxl
使用
import openpyxl
wb=openpyxl.load_workbook("./template.xlsx")
ws=wb["工作表1"]
counts={}
for i in range(category_count):
counts[chr(65+i)]=1
for i in enumerate(ToExcelZip):
# print(i)
column=chr(65+i[1][1])
# print(column)
ws_column=column+str(i[1][2])
if ws[ws_column].value == None:
ws[ws_column]=i[1][0]
else:
ws[ws_column]=ws[ws_column].value+" "+i[1][0]
wb.save("test_output.xlsx")
依照分群结果来写入特定Excel栏位。
这是从农委会找到的 主力农家平均每户所得按所得来源分 表格:
进行截图及执行程序看结果:
<<: Varying - fragment shader 之资料
tags: 2021铁人赛 React 先从mobile版型的页面来看,可以分为几个部份,如下图: ...
我很清楚逆向是我的硬伤,所以拖到最後才写了 Q"Q 虽然逆向工程与恶意软件分析息息相关,但...
第四天的小试身手解答:将Unity介面改为2By3,Project从Two Column Layou...
美国国防部在 2020 年1月底公布新规范 「网路安全成熟度模型认证Cybersecurity Ma...
接下来是如何储存题目、抓出题目、呈现题目 对一个老师来说,很常把资料都放在excel 中 所以可以选...