【Opencv】基于python-opencv的CV2实现图片OCR前的扫描摆正OCR识别【代码实现】

实验目的

本实验的目的主要是实现诸如发票,pdf扫描成的图片,如何可以实现找到发票(这里都用发票指代了)外轮廓,把桌面等信息消除,直接将发票清晰摆正呈现,方便后续的OCR识别。
2.本次实验的重点在于预处理-找到外轮廓外接矩形-透视变换摆正图片,最终的OCR扫描可以参考我的博客【Python】图像文字识别:从图片中识别出文字(Pytesseract安装配置与使用),以前已经实现过,就不赘述。用百度API也可以,效果会更好,也已经实现。

主要想讲的是图1到图2过程:
图1
图2

代码实现

预处理(注意Resize图像)

import cv2
from imutils.perspective import four_point_transform
import pytesseract
import os
from PIL import Image
import argparse
import matplotlib as plt
import numpy as np
# 绘图展示
def cv2_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

image = cv2.imread("D:/check2.jpg")
cv2_show('origin',image)
#ratio = image.shape[0] / 800  # 比例,h除以500,w自行计算
#print(ratio)
orig = image.copy()  # copy()不对原图改变
#500是设置的h为500,(int(image.shape[1]/ratio))为变化后的w,(h,w)
# resize_image = cv2.resize(orig, (800,int(image.shape[1]/ratio)))
resize_image = cv2.resize(orig, None,fx=0.2,fy=0.2)
# 想用原图直接注释上一条用下一条即可
# resize_image=image.copy()
cv2_show('resize',resize_image)

# 预处理操作
gray = cv2.cvtColor(resize_image, cv2.COLOR_BGR2GRAY)
cv2_show('gray',gray)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
cv2_show('GaussianBlur',gray)
edged = cv2.Canny(gray, 75, 200)

原图太大,现需要resize:
在这里插入图片描述
灰度:
在这里插入图片描述
高斯:
在这里插入图片描述
!!!!这里需要注意Resize时候:!!!!
resize图片时候比例不要用设置好的一个值,比如定好h是500,则:

ratio = image.shape[0] / 500  # 比例,原图h除以想要的500则是比例
print(ratio)
orig = image.copy()  # copy()不对原图改变
#500是设置的h为500,(int(image.shape[1]/ratio))为变化后的w,(h,w)
#resize(原图,(设置的想要的h,设置的相应比例变化的高))
resize_image = cv2.resize(orig, (500,int(image.shape[1]/ratio)))

这样可以,但是在后面轮廓划定,透视变化摆正图像时(如下面代码),会出现倾斜情况:

wraped = four_point_transform(orig, screenCnt.reshape(4, 2)*ratio)

在这里插入图片描述
因此resize图片时候比例我们直接设置比例,不用ratio值:

resize_image = cv2.resize(orig, None,fx=0.2,fy=0.2)
#意为w,h缩小为原来5倍

后面透视变换摆正图像时候直接乘以1/fx即可(此处5倍):

wraped = four_point_transform(orig, screenCnt.reshape(4, 2)*5)

轮廓检测(找到矩形)

重点是近似计算找轮廓!!!
approx=cv2.approxPolyDP(c, 0.02* peri, True) # 检测出来的轮廓可能是离散的点,故因在此做近似计算,使其形成一个矩形。做精度控制,原始轮廓到近似轮廓的最大的距离,较小时可能为多边形;较大时可能为矩形。
这里的值如果太小,比如0.0002等,可能近似轮廓是多边形,不是矩形,因此选择0,02即可。
注意:对于findContours:
cnts可能有几百个轮廓,里面的各种字都会被圈出来,一般外围轮廓是最大,所以直接进行排序,再从里面找,会更简单。

cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]  # 将轮廓按照面积的大小进行排序,并且选出前5个中最大的轮廓

刚开始不知道,所有的在一起找,由于精度问题没太懂,就浪费了很多时间找外围轮廓。

上代码:

# 轮廓检测
cnts, hierancy = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# 找出图像中的轮廓
# cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]  # 将轮廓按照面积的大小进行排序,并且选出前5个中最大的轮廓,当多个小票时
print('cnts',len(cnts))

for c in cnts:
    peri = cv2.arcLength(c, True)  # 周长,闭合
    # print(peri)
    approx=cv2.approxPolyDP(c, 0.02* peri, True)  # 检测出来的轮廓可能是离散的点,故因在此做近似计算,使其形成一个矩形
    # 做精度控制,原始轮廓到近似轮廓的最大的距离,较小时可能为多边形;较大时可能为矩形
    # True表示闭合
    if len(approx)==4:  # 如果检测出来的是矩形,则break本段if
        screenCnt = approx
        print(len(approx))

image=resize_image.copy()
cv2.drawContours(image, [screenCnt], -1, (0, 0, 255), 2)  # 绘制轮廓,-1表示全部绘制
cv2_show('contour', image)

在这里插入图片描述

透视变换(摆正图像)

重点是:four_point_transform(resize_image, screenCnt.reshape(4, 2))
这个函数导入包即可

from imutils.perspective import four_point_transform

代码:

# 变换
# 透视变换:摆正图像内容
# wraped = four_point_transform(resize_image, screenCnt.reshape(4, 2))
# 在原图上改
wraped = four_point_transform(orig, screenCnt.reshape(4, 2)*5)
cv2_show('wrap',wraped)
wraped = cv2.cvtColor(wraped, cv2.COLOR_BGR2GRAY)
cv2_show('wrap2',wraped)
ref = cv2.threshold(wraped, 100, 255, cv2.THRESH_BINARY)[1]
cv2_show('ref',ref)
# ref=cv2.resize(ref,None,fx=0.3,fy=0.3)
cv2.imwrite("d:/test.jpg", ref)  
# 必须加后缀名,把完成摆正的图片保存下来用于后续识别

这里需要注意:如果是在resize后的图上操作可能最终会出现摆正后图像也不清楚的状态,如下所示。
在resize图上对检测后轮廓进行透视变换:
在这里插入图片描述

因此我们需要对原图进行处理,前面说过,我们已经对原图进行resize时fx=0.2,fy=0.2,缩小了5倍,这里只需要(在原图上,后面对选中轮廓区域点进行乘以1/fx倍)即可:
four_point_transform(original_image, screenCnt.reshape(4, 2)5)*
最终效果好,如下图。
在原图上对检测后轮廓进行透视变换:
在这里插入图片描述
原图完胜!!!ヽ(・ω・´メ)

灰度:
在这里插入图片描述
二值后即可用于识别:
在这里插入图片描述

OCR识别文字

十分简单,但pytesseract的安装可能会有各种问题,参照这篇博客即可。

import pytesseract
text = pytesseract.image_to_string(Image.open(filename))  # 转化成文本

实验结果

发票图片

resize后的原图:
在这里插入图片描述

结果:
在这里插入图片描述

自己随便拍的图片

效果也可,记得把原图右旋转一下再做。
原图:
在这里插入图片描述
resize后的图:
在这里插入图片描述
找到轮廓:
在这里插入图片描述
结果:
在原图上做的透视变换:
在这里插入图片描述
效果还可!
在这里插入图片描述在这里插入图片描述

----EchoZhang-----03/29-----发现实战解决问题才能真正有点懂某一点的意思!继续抓住3月小尾巴搞搞opencv!-------

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值