一、边缘检测
二、获取轮廓
三、变换
四、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)