整体思路:利用边缘检测+轮廓检测+透射变换+百度文字识别API实现。 总体分为3步: 1.运用边缘检测与轮廓检测检测到文本最外侧的边缘。 2.根据边缘的四点确定文档的区域,再利用透射变换等操作将文档视角转换。 3.调用百度文字识别API进行文本识别。 原始图像: 透射变换等操作之后的图像: 文本识别的结果(部分): 具体步骤: Step1:运用边缘检测与轮廓检测检测到文本最外侧的边缘 通过Canny边缘检测将测出轮廓,然后再进行轮廓检测。轮廓检测时会出现多个闭合图形,可以通过比较闭合图形的面积的大小确定,拥有面积最大值的闭合图形即为文档边缘。
img=cv.imread('receipt.jpg',cv.IMREAD_COLOR)
org=img.copy()
ratio=0.4
img=cv.resize(img, dsize=None,fx=ratio,fy=ratio)
gray=cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edged=cv.Canny(gray,75, 200)
cnts,hierarchy=cv.findContours(edged.copy(), cv.RETR_LIST,
cv.CHAIN_APPROX_SIMPLE)
cnt = sorted(cnts, key = cv.contourArea, reverse = True)[0]
peri = cv.arcLength(cnt, True)
approx=cv.approxPolyDP(cnt, 0.1*peri, True)
if(len(list(approx))==4):
screenCnt=approx
else:
print("未找到轮廓")
exit()
效果:
Step2:根据边缘的四点确定文档的区域,再利用透射变换等操作将文档视角转换。
1.确定文档边缘四点。 作者采用如下方法确定: 当x+y为最小/大值时,分别对应A/C点。(sum求和函数) 当y-x为最小/大值时,分别对应B/D点。(diff做差函数)
def order_points(pts):
rect = np.zeros((4, 2), dtype = "float32")
s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
diff = np.diff(pts, n=1,axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
2.透射变换 以四个边长的长/宽的最大值分别作为透射变换后长/宽,然后做透射变换。
def four_point_transform(image, pts):
rect=order_points(pts)
len=np.zeros((4,1))
for (i,p) in enumerate(pts) :
if i!=3:
x=pts[i:(i+2),0]
y=pts[i:(i+2),1]
elif i==3:
x=[pts[3,0],pts[0,0]]
y=[pts[3,0],pts[0,1]]
len[i]=np.sqrt(((x[0]-x[1])**2+(y[0]-y[1])**2))
maxWidth=int(max(len[0],len[2]))
maxHight=int(max(len[1],len[3]))
dst=np.array([
[0,0],
[maxWidth-1,0],
[maxWidth-1,maxHight-1],
[0,maxHight-1]
],dtype = "float32")
M=cv.getPerspectiveTransform(rect, dst)
warped=cv.warpPerspective(image, M, (maxWidth,maxHight))
return warped
实际调用:
warped=four_point_transform(org, screenCnt.reshape(4,2)/ratio)
再进行旋转变换与阈值处理即可获得纠正后的图像:
rows,cols = dst.shape[:2]
M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv.warpAffine(dst,M,(cols,rows))
gray=cv.cvtColor(warped, cv.COLOR_BGR2GRAY)
ret,dst=cv.threshold(gray, 127, 255, cv.THRESH_BINARY)
Step3:调用百度文字识别API进行文本识别。 如何获取OCR模块参考:https://blog.csdn.net/jyd0124/article/details/105868562 然后调用API即可,详细深入的OCR处理不在这里展开。
AppID = '*******'
API_Key = '********'
Secret_Key = '**************'
client = AipOcr(AppID, API_Key, Secret_Key)
image = get_file_content('图片的地址')
options = {}
options["language_type"] = "ENG"
options["detect_direction"] = "true"
options["detect_language"] = "true"
options["probability"] = "true"
res=client.basicGeneral(image,options)
print(res['words_result'])
for item in res['words_result']:
print(item['words'])
OCR结果:
|