在人工智能计算机视觉方面,有图像分类、目标检测、语义分割、实例分割四大主要任务。目前在各个领域都有比较成熟的应用。
在一些特定的环境或特殊需求中,我们可能需要通过图像来对水表进行智能读数。
水表数据图像
对于水表读数,首先考虑使用语义分割,目的就是把水表盘的数据区域分割出来。关于语义分割可以参看:5.人工智能-语义分割。本文主要想讲一下语义分割后的图像数据处理和识别。
语义分割后,返回的是多边形坐标值。这里因为可以看到水表的数据区域并不是水平的,所以我们需要根据返回的多边形坐标值,对水表的数据区域图像进行旋转后得到,再进行文字识别。
这里每个水表图像对应一个文本文件,文件内容就是语义分割后返回的4个顶点的坐标值。如:97 475 280 424 293 466 105 520
演示数据
实现代码:
import cv2
import os
import numpy as np
import paddleocr
basedir="meter"
ptslst=[]
#读取文本文件
for f in os.listdir(basedir):
#分离文件名和后缀
fname,fext=os.path.splitext(f)
if fext==".txt":
#读取文件
with open(os.path.join(basedir,f)) as f:
for line in f:
#按照空格分割,并转换为int
x1,y1,x2,y2,x3,y3,x4,y4,v=list(map(lambda x:int(x),line.split()))
#print(x1,y1,x2,y2,x3,y3,x4,y4,v)
dxy={fname:[[x1,y1],[x2,y2],[x3,y3],[x4,y4]]}
ptslst.append(dxy)
#print(ptslst)
#多边形旋转为矩形,并计算旋转角度,返回旋转后的矩形,中心坐标
def rotate_rect(pts):
#计算多边形的中心点
x=sum(map(lambda x:x[0],pts))/4
y=sum(map(lambda x:x[1],pts))/4
#计算多边形的长宽
w=max(map(lambda x:x[0],pts))-min(map(lambda x:x[0],pts))
h=max(map(lambda x:x[1],pts))-min(map(lambda x:x[1],pts))
#计算多边形的旋转角度
angle=np.arctan2(pts[1][1]-pts[0][1],pts[1][0]-pts[0][0])*180/np.pi
#旋转后的矩形
pts_rotate=np.array([[x-w/2,y-h/4],[x w/2,y-h/4],[x w/2,y h/4],[x-w/2,y h/4]])
pts_rotate=pts_rotate.astype(np.int32)
return pts_rotate,angle,x,y
#以(x,y)为中心旋转图像
def rotate_img(img,angle,x,y):
#获取图像的高和宽
h,w=img.shape[:2]
#计算旋转后的高和宽
h_new=int(np.sqrt(h**2 w**2-2*h*w*np.cos(angle)))
w_new=int(np.sqrt(h**2 w**2 2*h*w*np.cos(angle)))
#计算旋转后的中心点
# x_new=w_new/2
# y_new=h_new/2
#计算旋转矩阵
# M=cv2.getRotationMatrix2D((x_new,y_new),angle,1)
M=cv2.getRotationMatrix2D((x,y),angle,1)
#旋转图像
img_rotate=cv2.warpAffine(img,M,(w_new,h_new))
return img_rotate
#读取图片,并画多边形
for f in os.listdir(basedir):
#分离文件名和后缀
fname,fext=os.path.splitext(f)
if fext==".jpg":
#读取图片
img=cv2.imread(os.path.join(basedir,f))
#画多边形
for dxy in ptslst:
if fname in dxy:
#转换为np.array
pts=np.array(dxy[fname])
#cv2.polylines(img,[pts],True,(0,255,0),2)
#返回旋转后坐标,旋转角度,中心点
pts_m,theta,x,y=rotate_rect(pts)
#print(pts_m)
#旋转图像
img=rotate_img(img,theta,x,y)
#cv2.polylines(img,[pts_m],True,(0,0,255),2)
#获取旋转后矩形的图像
roi_img=img[pts_m[0][1]:pts_m[2][1],pts_m[0][0]:pts_m[2][0]]
#ocr识别
ocr=paddleocr.PaddleOCR(use_angle_cls=True,lang="ch")
result=ocr.ocr(roi_img,cls=True)
line=result[0]
boxes=line[0]
txts=line[1][0]
scores=line[1][1]
#print(boxes,txts,scores)
#写文字
cv2.putText(roi_img,txts,(10,25),cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),2)
cv2.imshow("meter",roi_img)
#显示图片
#cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
旋转后识别结果
,