项目实战-文档扫描OCR识别

一、完整项目代码

import numpy as np
import argparse
import cv2

#设置参数
ap =argparse.ArgumentParser()
ap.add_argument("-i","--image",required =True,help="Path to the image to be scanned")
args = vars(ap.parse_args())

def order_points(pts):
    #一共四个坐标点
    rect = np.zeros((4,2),dtype= "float32")

    #按顺序找到对应坐标0123分别是 左上,右上,右下,左下
    #计算左上,右下
    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_points(pts)
    (tl,tr,br,bl)=rect

    #计算输入的w和h值   根号下x平方+y平方
    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))

    #变换后对应坐标位置
    dst = np.array([[0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1],
                    [0, maxHeight - 1]], dtype="float32")  #3x3的矩阵

    #计算变换矩阵
    M =cv2.getPerspectiveTransform(rect,dst)
    warped =cv2.warpPerspective(image, M ,(maxWidth,maxHeight))

    #返回变换后的结果
    return warped

def  resize(image, width=None,height=None,inter=cv2.INTER_AREA):
    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(w)  #比例
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

#读取输入
image = cv2.imread('E:/anaconda3/picture/receipt.jpg')
#坐标相同变化
ratio = image.shape[0] / 500.0  
orig = image.copy()

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)    #进行边缘检测,以便后边的轮廓提取

#显示预处理结果
print("STEP 1: 边缘检测")
cv2.imshow("Image", image)
cv2.imshow("Edged", edged)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 轮廓检测
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1] 
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]  

# 遍历轮廓
for c in cnts:
    # 计算轮廓近似
    peri = cv2.arcLength(c, True)  #轮廓长度
    # C表示输入的点集
    # epsilon表示从原始轮廓到近似轮廓的最大距离,它是一个准确度参数
    # True表示封闭的
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)  

    # 4个点的时候就拿出来
    if len(approx) == 4:  #得到近似 4个点
        screenCnt = approx   #近似完的结果
        break  #拿出来

# 展示结果
print("STEP 2: 获取轮廓")
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)   #画出轮廓
cv2.imshow("Outline", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 透视变换 
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.jpg', ref)
# 展示结果
print("STEP 3: 变换")
cv2.imshow("Original", resize(orig, height=650))
cv2.imshow("Scanned", resize(ref, height=650))
cv2.waitKey(0)

二、具体操作

1、先导入工具包,设置参数(设置图片读取路径)

import numpy as np
import argparse
import cv2

#设置参数
ap =argparse.ArgumentParser()
ap.add_argument("-i","--image",required =True,help="Path to the image to be scanned")
args = vars(ap.parse_args())

2、读取输入,图片读取后,计算其四个坐标点,要做边缘检测就要是坐标有相同的变化。然后,再进行图片片预处理(转灰度图、高斯滤波-为了滤除一些噪音点、边缘检测)

#读取输入
image = cv2.imread('E:/anaconda3/picture/receipt.jpg')
#坐标相同变化
ratio = image.shape[0] / 500.0  
orig = image.copy()

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)    #进行边缘检测,以便后边的轮廓提取

#显示预处理结果
print("STEP 1: 边缘检测")
cv2.imshow("Image", image)
cv2.imshow("Edged", edged)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:

项目实战-文档扫描OCR识别_第1张图片项目实战-文档扫描OCR识别_第2张图片

边缘检测之后,要进行具体的轮廓检测

3、轮廓检测

cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]  #
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]   
会检测出这张图上所有的轮廓,但我们需要的是最外边,所以为了计算他外接的东西,所以进行排序前五个最大的轮廓,然后再遍历每一个轮廓:
for c in cnts:
    # 计算轮廓近似
    peri = cv2.arcLength(c, True)  #轮廓长度
    # C表示输入的点集
    # epsilon表示从原始轮廓到近似轮廓的最大距离,它是一个准确度参数
    # True表示封闭的
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)  #对轮廓点进行【近似】(c是每一个轮廓/0.02 * peri就是epsilon/)

    # 4个点的时候就拿出来
    if len(approx) == 4:  #得到近似 4个点
        screenCnt = approx   #近似完的结果
        break  #拿出来

输出结果:

项目实战-文档扫描OCR识别_第3张图片项目实战-文档扫描OCR识别_第4张图片

这样一来,图片中的文字凸显出来,要想得到图片中具体的文字内容就要安装tesseract_ocr

三、tesseract_OCR 的安装与配置

1、安装包网址:https://digi.bib.uni-mannheim.de/tesseract/

选择最新版本下载即可,设置好安装路径(我是E:\opencv)

2、配置环境变量:属性>高级设置>环境变量>上下两个框中path都加进去E:\opencv的路径 就OK

3、WIN+R输入cmd后输入tesseract -v进行测试,得到版本号就成功

4、tesseract XXX.png 得到结果  输入一个图片

5、tesseract XXX.png   result  得到图片识别到的文字结果   这就说明 tesseract安装成功

6、在命令栏tesseract的目录下输入pip install pytesseract, 安装pytesseract

7、在anaconda3> lib> site-packges> pytesseract.py >tesseract_cmd 修改为绝对路径即可

 绝对路径也就是tesseract安装的具体路径.

到这里tesseract就可以运行来识别图片文字内容了:

from PIL import Image
import pytesseract
import cv2
import os

preprocess = 'blur' #thresh

image = cv2.imread('scan.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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("Output", gray)
cv2.waitKey(0)   

 就会得到"超市小片上的文字:"

输出的: 

项目实战-文档扫描OCR识别_第5张图片项目实战-文档扫描OCR识别_第6张图片

 

你可能感兴趣的:(大数据)