0


【opencv学习】基于透视变换和OCR识别的小票识别

本文基于之前学习的透视变换、和OCR识别,做了个简单的小票识别,如下:

import cv2
import numpy as np
from PIL import Image
import pytesseract as tess

dsize =(55,88)# 统一尺度# 展示图像,封装成函数defcv_show_image(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)# 等待时间,单位是毫秒,0代表任意键终止
    cv2.destroyAllWindows()# =========================================================# ================读取图像进行预处理=========================# =========================================================# 读取原始的彩色图像
ocr_img = cv2.imread('images/ocr_qr_code.PNG')
h_src, w_src, c_src = ocr_img.shape

# 进行灰度值和二值化转换
ocr_img_gray = cv2.cvtColor(ocr_img, cv2.COLOR_BGR2GRAY)# cv_show_image('template_gray', template_gray)# 高斯滤波
ocr_img_gray = cv2.GaussianBlur(ocr_img_gray,(3,3),1)# 二值化
ret, ocr_img_thresh = cv2.threshold(ocr_img_gray,200,255, cv2.THRESH_BINARY)
cv_show_image('template_thresh', ocr_img_thresh)# 找到所有的轮廓。只需要外轮廓
ocr_img_contours, hierarchy = cv2.findContours(ocr_img_thresh,
                                               cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)# =========================================================# ================找到最大面积的那个轮廓=========================# =========================================================# 找到最大面积的那个轮廓
draw_img = ocr_img.copy()# 阶段性测试查看使用# 最后的参数可以控制找到前几个最大的。比如哈,0表示最大的,2表示前三大的。
cont_max =sorted(ocr_img_contours, key=cv2.contourArea, reverse=True)[0]# 按照面积来排序,找到最大的,倒序。# 画出这个轮廓,红色线条
x, y, w, h = cv2.boundingRect(cont_max)
draw_img = cv2.drawContours(draw_img,[cont_max],-1, color=(0,0,255), thickness=2)# 画出这个轮廓,会在原图上画
arcLength = cv2.arcLength(cont_max,True)# 求最大的轮廓的周长# 这个原始轮廓可能是很多歌点哈,但是我们只需要四个点的四边形的轮廓就行了。这里需要进行轮廓近似运算。# 不断的尝试提升阈值,增大近似范围,减少边数目。
rate =0.01
approx_max =Nonewhilelen(cont_max)!=4:# epsilon是原始轮廓到近似轮廓的最大距离,也是近似的判断阈值。 closed 是表示是个封闭的轮廓
    approx_max = cv2.approxPolyDP(cont_max, epsilon=rate * arcLength, closed=True)iflen(approx_max)==4:print("rate={}, epsilon={}".format(rate, rate * arcLength))break
    rate +=0.01print("approx: ", approx_max)# 画出这个轮廓,绿色线条
draw_img = cv2.drawContours(draw_img,[approx_max],-1, color=(0,255,0), thickness=2)# 画出这个轮廓,会在原图上画

cv_show_image('rectangle_contours_img', draw_img)del draw_img

# =========================================================# ================得到了四个顶点,进行透视变换=========================# =========================================================# 先排序这个四个顶点,按照((左上),(右上),(右下),(坐下))的顺序来定义# 最终这四个点将转成((0,0), (w,0), (w,h), (h,w)) + 平移(左上)的形式。defsort_dotCnt(kps):
    rect = np.zeros((4,2), dtype='float32')
    s = kps.sum(axis=1)# 找出左上和右下
    rect[0]= kps[np.argmin(s)]
    rect[2]= kps[np.argmax(s)]# 找出右上和左下
    diff = np.diff(kps, axis=1)
    rect[1]= kps[np.argmin(diff)]
    rect[3]= kps[np.argmax(diff)]return rect

print(approx_max.shape)print(approx_max.reshape(4,2))
rect_ordered = sort_dotCnt(approx_max.reshape(4,2))(top_left, top_right, bottom_right, bottom_left)= rect_ordered

# 原始图像中物体的四个顶点的信息
pts_src = np.array([top_left, top_right, bottom_right, bottom_left], dtype="float32")# 目标物体中的物体的四个顶点信息
pts_dst = np.array([(0+ top_left[0],0+ top_left[1]),(w + top_left[0],0+ top_left[1]),(w + top_left[0], h + top_left[1]),(0+ top_left[0], h + top_left[1])], dtype="float32")# 是一个3x3的矩阵,根据对应的两个点,计算出变换矩阵,由此将原始图像进行转换。
M = cv2.getPerspectiveTransform(pts_src, pts_dst)# 基于单应性矩阵,将原始图像转换成目标图像
im_out = cv2.warpPerspective(ocr_img_thresh, M,(w_src, h_src))
cv_show_image('im_out', im_out)# =========================================================# ================识别其数字=========================# =========================================================

textInImage = Image.fromarray(im_out)
text = tess.image_to_string(textInImage)print("\nocr detect result:%s"% text)

原图经过预处理后:
请添加图片描述
经过轮廓检测后,得到一个四个顶点的轮廓用绿色线画出
请添加图片描述
经过透视变换得到:
请添加图片描述
最后用过OCR识别得到:
请添加图片描述
目前智能识别到数字,下一次,我将去看看学习下怎么识别简体汉字


本文转载自: https://blog.csdn.net/qq_29367075/article/details/123171016
版权归原作者 星海千寻 所有, 如有侵权,请联系我们删除。

“【opencv学习】基于透视变换和OCR识别的小票识别”的评论:

还没有评论