OpenCV-Python项目实战:OCR识别

OpenCV-Python项目实战:识别小票

OpenCV-Python项目实战:OCR识别_第1张图片
OpenCV-Python项目实战:OCR识别_第2张图片
OpenCV-Python项目实战:OCR识别_第3张图片

如图就是要识别和处理的对象。

得到情报:

1.背景是一种颜色,小票是另外的一种颜色

2.小票及小票内容是倾斜的(考虑使用透视)

3识别内容需要我另外下载OCR附加包

任务开始!

一:准备工作

为了保证下面的图像显示问题 我先引入cv_show 函数,再把库加进去

import cv2
import numpy as np
def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)  # 等待时间,毫秒级
    cv2.destroyAllWindow()

二:让主角进场,提醒他换个衣服,不打领带不准进!

image = cv2.imread('2019090715562446.jpg')
ratio = image.shape[0] / 500.0  
#为什么是500.0 是因为我想他换H=500的衣服,看看比率
#让我们写个函数 教他怎么换衣服 
def resize(image, width=None, height=None):
    dim = None
    (h, w) = 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)
    else:
        r = width / float(h)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, cv2.INTER_AREA)
    return resized
#换上了品如的衣服:
orig=image.copy()  #后面还要copy 
image = resize(orig, width=None, height=500)

三:衣服换完了,该化妆了

# 预处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 cv_show('gray',gray)

四:让别人好好康康你的轮廓

gray = cv2.GaussianBlur(gray, (5, 5), 0)
#高斯滤波去掉噪声点 
edged = cv2.Canny(gray, 75, 200)
cv_show('edged',edged)
#经典Canny检测  原形毕露!何方妖孽!!!

# 轮廓检测
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]

cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]
#我这里key定义的是面积 我就取4个 因为轮廓检测是很多的,必然包括图上的小票轮廓,排个序,取前五个,之后我再设置一定的规则去筛选这几个轮廓   

五:制定规则

for i in cnts:

    # 计算轮廓近似  peri是周长  老盆友
    peri = cv2.arcLength(i, True)
    #   c表示输入的点集合
    #   epsilon 表示从原始轮廓到近似轮廓的最大距离,它是一个准确度参数
    #   True表示封闭的
    approx = cv2.approxPolyDP(i, 0.02 * peri, True)
    screenCnt = []
    # 4个点时候就拿出来  得到矩形
    if len(approx) == 4:
        screenCnt = approx
        break
print(screenCnt)
'''
得到的结果:
[[[453 108]]

 [[100 135]]

 [[134 374]]

 [[462 322]]]
'''
#[screenCnt]   外 [] 别忘了 
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
cv_show('image', image)

六:透视变换

def order_points(pts):
  
    rect = np.zeros((4, 2), dtype="float32")
    # 0 0
    # 0 0
    # 0 0
    # 0 0
    
    s = pts.sum(axis=1)  # 计算矩阵的每一行元素相加之和
    rect[0] = pts[np.argmin(s)]  # tl
    rect[2] = pts[np.argmax(s)]  # bl

    diff = np.diff(pts, axis=1)
    rect[1] = pts[np.argmin(diff)]  # tr
    rect[3] = pts[np.argmax(diff)]  # br
    # return the ordered coordinates
    return rect

'''
定义一个 order_points 函数,需要传入参数 pts,是一个包含矩形四个点的(x, y)坐标的列表。

对矩形中的四个点进行 一致的排序 是非常重要的,实际的排序可以是任意的,只要它在整个实现过程中是一致的。

对于我来说,我习惯将点按照 “左上,右上,右下,左下” 进行排序。

代码里使用 np.zeros 为四个点分配内存。
根据 x 与 y 之和最小找到左上角的点,x 与 y 之和最大找到右下角的点。
然后使用 np.diff 函数,
根据 x 与 y 之差(y-x)最小找到右上角的点,x 与 y 之差最大找到左下角的点。
'''

七:计算W和H

def four_point_tramsform(image, pts):
    # 获取输入的坐标
    rect = order_points(pts)
    (tl, tr, bl, br) = rect

    # 计算出输入的w和h的值  勾股定理  走起
    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))
    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))

    # 变换之后的坐标位置
	# 计算变换矩阵M  rect是轮廓四个点  dst是我们规定的四个点(利用W和H人为创造的)
	M = cv2.getPerspectiveTransform(rect, dst)
    
	warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    # 返回变换后的结果  杰哥:让我康康!!
    return warped

warped = four_point_tramsform(orig, screenCnt.reshape(4, 2) * ratio)
#screenCnt是 Canny检测得到的  因为缩放 每个点的位置都要改
#别忘了*比率 因为我们现在这个图orig是初始image的复制体
cv_show('warped', warped)

八:把透视过的图处理一下

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

# 展示结果
cv2.imshow('Original', resize(orig, height=650))
cv2.imshow('Scanned', resize(ref, height=650))
cv2.waitKey(0)

九:开始OCR操作

下载Tesseract-OCR 开始读 !!!

from PIL import Image
import pytesseract
import os

mage = cv2.imread('scan.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
preprocess ='blur'
if preprocess =='thresh':
    gray = cv2.threshold(gray,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
if preprocess =='blur':
    gray = cv2.medianBlur(gray,3)

filename='{}.png'.format(os.getpid())
cv2.imwrite(filename,gray)

text = pytesseract.image_to_string(Image.open(filename))
print(text)
os.remove(filename)

cv2.imshow('image',image)
cv2.imshow('gray',gray)
cv2.waitKey(0)

你可能感兴趣的:(OpenCV图像处理,opencv,计算机视觉,python)