- 图片预处理
- 透视变换,拉正视角
- tesseract进行识别
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 导包
import numpy as np
import cv2
# 读取图片
image = cv2.imread('./images/page.jpg')
print(image.shape)
# 计算比例,限定高度500
ratio = image.shape[0] / 500.0
orig = image.copy()
# 对图片进行统一的resize
# 封装resize功能
# cv_show('img', image)
def resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# cv2.resize()
dim = None
(h, w) = image.shape[:2]
# print(image.shape[:2])
if width is None and height is None:
return image
if width is None: # 只提供了高度
r = height /float(h)
dim = (int(w * r), height)
# print(dim)
else: # 如果只提供了宽度
r = width / float(w)
dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation = inter)
return resized
# 对图片进行热size
image = resize(orig, height = 500)
# 灰度化处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 高斯模糊去噪点
gray = cv2.GaussianBlur(gray, (5,5), 0)
# 边缘检测
edged = cv2.Canny(gray, 75, 200)
cv_show('img', edged)
# 用边缘检测的结果进行轮廓检测
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
# 按照面积排序
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)
print(len(cnts))
# 显示轮廓
image_contours = cv2.drawContours(image.copy(), cnts, -1, (0, 0, 255), 2)
cv_show('img', image_contours)
# 遍历轮廓,找出最大轮廓
for c in cnts:
# 计算轮廓周长
perimeter = cv2.arcLength(c, True)
# 多边形逼近
approx = cv2.approxPolyDP(c, 0.02 * perimeter, True)
if len(approx) == 4:
screen_cnt = approx
break
# 显示轮廓
image_contours = cv2.drawContours(image.copy(), [screen_cnt], -1, (0, 0, 255), 2)
cv_show('img', image_contours)
def order_points(pts):
# 创建全为0 的矩阵, 来接收找到的坐标
rect = np.zeros((4, 2), dtype = 'float32')
s = pts.sum(axis = 1)
# 左上角的坐标一定是X,Y相加最小的,右下为最大的
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
# 右上角的x,y 相减的差值一定是最小的
# 左下角的x,y 相减,差值一定是最大的
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_points(pts)
(tl, tr, br, bl) = rect
widthA = np.sqrt((br[0] - bl[0]) ** 2 + (br[1] - bl[1]) ** 2)
widthB = np.sqrt((tr[0] - tl[0]) ** 2 + (tr[1] - tl[1]) ** 2)
max_width = 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)
max_height = max(int(heightA), int(heightB))
dst = np.array([
[0, 0],
[max_width - 1, 0],
[max_width -1, max_height - 1],
[0, max_height -1]], dtype = 'float32')
M = cv2.getPerspectiveTransform(rect, dst)
warped = cv2.warpPerspective(image, M, (max_width, max_height))
return warped
# 视图透视变换
# 将视图转为正对透视
warped = four_point_transform(orig, screen_cnt.reshape(4, 2) * ratio)
# 二值化处理
warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
ref = cv2.threshold(warped, 120, 255, cv2.THRESH_BINARY)[1]
# print(ref.shape)
cv_show('ref', ref)
# 把处理好的图片写入文件
cv2.imwrite('./scan1.jpg', ref)
# cv_show('warp', warped)
# 调用电脑的识图转文字功能
import pytesseract
from PIL import Image
# pytesseract要求的image不是OpenCV读进来的image, 而是pillow这个包, 即PIL
text = pytesseract.image_to_string(Image.open('./scan1.jpg'))
print(text)