计算机视觉-OpenCV(文档扫描OCR识别)

一、边缘检测

二、获取轮廓

三、变换

四、OCR识别

import cv2
import numpy as np
import argparse
import pytesseract
import os
from PIL import Image


#同比例变化方法
def resize(pic,height):
    (h,w,s)=pic.shape
    bili=h/height
    image = cv2.resize(pic, (int(w/bili),height,))
    return image
#图像显示
def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
#order_point方法定义
def order_point(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,axis=1)
    rect[1]=pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]

    return rect

#透视变换方法
def four_point_transform(image,pts):
    #获取坐标点
    rect=order_point(pts)
    (tl,tr,br,bl)=rect


    #计算输入的w和h值
    widthA=np.sqrt(((br[0]-bl[0])**2)+((br[1]-br[1])**2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tr[1]) ** 2))
    maxWidth=max(int(widthA),int(widthB))

    heightA=np.sqrt(((tr[0]-br[0])**2)+((tr[1]-br[1])**2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight=max(int(heightA),int(heightB))

    #变换后对应坐标位置
    dst=np.array([
        [0,0],
        [maxWidth-1,0],
        [maxWidth-1,maxHeight-1],
        [0,maxHeight-1]],dtype="float32")
    #计算变换矩阵
    #rect(输入的四个点),dst(输出的四个点),计算变换矩阵M
    M=cv2.getPerspectiveTransform(rect,dst)
    #将变换矩阵M带入函数warpPerspective,还有输入坐标计算出最大的宽和高
    warped=cv2.warpPerspective(image,M,(maxWidth,maxHeight))
    return warped
#读取图像
image=cv2.imread(r"D:\pythonProject\NewProject\PIc\ID.jpg")
#因为要resize图像,所以要计算resize后图像与原图像大小比例,方便计算坐标
#print(image.shape)#(1060, 881, 3) (h,w,通道数)
ratio=image.shape[0]/500.0
#创建副本
orig=image.copy()

#resize大小
image=resize(orig,500)
#print(image.shape)
#cv_show('image',image)

#图像预处理
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
gray=cv2.GaussianBlur(gray,(5,5),0)#高斯滤波,去噪音点
edged=cv2.Canny(gray,75,200)#Canny边缘检测,(抛弃弱边缘,留主边缘)

#显示预处理结果
print('STEP1:边缘检测')
cv_show('edged',edged)

#轮廓检测
cnts,hierarchy=cv2.findContours(edged.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#print(np.array(cnts).shape)
#对检测到轮廓排序,排序方式按面积排序,取前五个,
cnts=sorted(cnts,key=cv2.contourArea,reverse=True)[:5]

#遍历每一个轮廓
for c in cnts:
    #计算轮廓周长
    peri =cv2.arcLength(c,True)
    #轮廓近似,c:遍历的轮廓,0.02*peri:近似值(表示从原始轮廓到近似轮廓的最大距离,是一个准确的参数)
    # 周长的0.02倍,true:表示封闭
    approx=cv2.approxPolyDP(c,0.02*peri,True)

    #4个点的时候拿出来
    #approx是点值
    #近似成矩形时,有四个点值,为矩形时把点值拿出来
    if len(approx)==4:
        screenCnt=approx
        break
#显示结果
print('STEP2:获取轮廓')
cv2.drawContours(image,[screenCnt],-1,(0,255,0),2)
cv_show('image',image)

hh=screenCnt.reshape(4,2)*ratio


#透视变换 api:
#reshape(4,2): 4表示四个点,2表示每个点都是x,y两个值
#乘ratio表示把坐标还原成原始图像坐标
warped=four_point_transform(orig,screenCnt.reshape(4,2)*ratio)

#二值处理
warped=cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)
ref=cv2.threshold(warped,100,255,cv2.THRESH_BINARY)[1]
cv2.imwrite('scan.png',ref)

#展示结果
print("STEP3:变换")
cv_show('ref',ref)

filename="{}.png".format(os.getpid())
cv2.imwrite(filename,gray)
#文档扫描
text=pytesseract.image_to_string(filename)
print(text)

你可能感兴趣的:(Python机器学习,python)