opencv图像处理—项目实战:文档扫描OCR识别

目录

1.边缘检测 

 2.获取轮廓

3.变换 

 4.tesseract-OCR安装配置

5.使用pycharm运行检测

出现错误 1

 出现错误2

出现错误3 

 出现问题4



    完整代码

# 导入工具包
import imutils
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):
	# 一共4个坐标点
	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值
	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")

	# 计算变换矩阵,最少四组坐标,且不共线
	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(args["image"])
#坐标也会相同变化
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=cnts[1]if imutils.is_cv3()else cnts[0]
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:
		screenCnt = approx
		break

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

# 透视变换,2个参数,把歪歪扭扭的转换为规规矩矩的
#orig:原始图像的copy,第二个参数是四个点的坐标,每个点都是X,Y,
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.边缘检测 

# 读取输入
image = cv2.imread(args["image"])
#坐标也会相同变化
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()

 输入图片

 边缘检测结果

 2.获取轮廓

# 轮廓检测
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# [1]
cnts=cnts[1]if imutils.is_cv3()else cnts[0]
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:
		screenCnt = approx
		break

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

3.变换 

# 透视变换,2个参数,把歪歪扭扭的转换为规规矩矩的
#orig:原始图像的copy,第二个参数是四个点的坐标,每个点都是X,Y,
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)

 4.tesseract-OCR安装配置

 下载地址:Index of /tesseract

  • 下载后安装,复制安装路径,环境配置时要用 
  • 进行环境变量的配置,在path里面直接添加刚才复制的路径即可。 
  • tesseract -v进行测试,查看版本

  •  tesseract XXX.png result  可以得到结果

 先保存一张teacher.png图片

然后在cmd中输入 tesseract teacher.png result

可以在同文件目录下找到result文本

  • anaconda中安装此包

pip install pytesseract 

  •  修改路径

找到pytesseract .py文件;我的路径在E:\Anaconda\anzhuang\Lib\site-packages\pytesseract

 打开,找到tesseract_cmd,然后将后面的路径换为下载tesseract-ocr时的路径,保存即可。

完整代码

# https://digi.bib.uni-mannheim.de/tesseract/
# 配置环境变量如E:\Program Files (x86)\Tesseract-OCR
# tesseract -v进行测试
# tesseract XXX.png 得到结果 
# pip install pytesseract
# anaconda lib site-packges pytesseract pytesseract.py
# tesseract_cmd 修改为绝对路径即可
from PIL import Image
import pytesseract
import cv2
import os

preprocess = 'blur' #thresh

image = cv2.imread('images/page.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)                                   

5.使用pycharm运行检测

  • 出现错误 1

 原因:没有安装opencv包

解决办法:设置-解释器-+号-搜索opencv进行安装(安装太慢可以用管理仓库,删除原有镜像源,使用清华镜像源:Simple Index


  •  出现错误2

 运行以下代码进行调试的时候出现了错误

import cv2 as cv

src = cv.imread("E:\OpenCV\image\1.png") #括号里是照片地址
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
cv.waitKey(0)
cv.destroyAllWindows()
print("hi python")

错误如下:

 原因分析:主要是图片路径中“文件夹分隔符”使用的错误

解决办法:将路径中的“\”改为“/”即可 ,即

错误:src = cv.imread("E:\OpenCV\image\1.png")
正确:src = cv.imread("E:/OpenCV/image/1.png")

 处理后可正常显示图像


  • 出现错误3 

将代码复制进入pycharm中

出现如下错误 

usage: opencv.py [-h] -i IMAGE
opencv.py: error: the following arguments are required: -i/--image

原因分析:没有在程序运行前进行参数设置 

解决方法:

 形参中将要读取的图片的路径放进去

 显示正常


  •  出现问题4

cv2.error: OpenCV(4.6.0) :-1: error: (-5:Bad argument) in function 'contourArea'

 分析原因:少写一行代码

cnts=cnts[1]if imutils.is_cv3()else cnts[0]

 解决方法:

# 轮廓检测
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# [1]
cnts=cnts[1]if imutils.is_cv3()else cnts[0]
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]#排序操作,按矩形面积

猜你喜欢

转载自blog.csdn.net/weixin_58176527/article/details/125248406