常见的三个视觉识别应用:计算机视觉项目 2 文档扫描OCR识别
常见的三个视觉识别应用:计算机视觉项目 2 文档扫描OCR识别for c in cnts: # 计算轮廓近似 peri = cv2.arcLength(c 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() 12345678910111213141516这里cv2.arcLength表示计算轮廓的周长。cv2.approx
我们这里以一个英文的文件,一个自己用中文的一首诗来去做这个项目。因为怕其他东西干扰边缘,于是自己画了个框把边缘圈起来了。
首先我们还是要导入第三方库,然后获取参数。
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())
12345678
这里我们一定要会这种导入参数的形式,非常方便,后期设置参数也非常方便,指定路径就完全OK了。
这里我们只需要指定一个传入参数,原始图像就OK了。
然后我们使用DEBUG操作一步一步进行操作,首先我们对图像进行一个resize操作。
image = cv2.imread(args["image"])
ratio = image.shape[0] / 500.0
orig = image.copy()
image = resize(orig height = 500)
12345
首先我们读取image数据,然后对图像进行一个求比例的操作。后期会用得到,再对图像进行resize操作时候,我们会把图像的h和w设置成同一比例。这里我们对image进行了resize函数操作,那么resize函数是什么呢?我们继续看。
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
12345678910111213
上方我们传入resize函数的参数是orig height = 500,那么orig是原始图像的copy,因为取轮廓是不可逆的,所以我们用copy去做,这里我们提取到图像的h和w,因为我们设置了height所以直接跳到if width is None,比例r=height/float(h),为了把width设置成和height同比例,所以进行了dim = (int(w * r) height),完成之后呢,就把dim传入到cv2.resize(image dim interpolation=inter),这里就把图像进行了同比例的resize操作。完成之后呢我们继续DEBUG继续看。
gray = cv2.cvtColor(image cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray (5 5) 0)
edged = cv2.Canny(gray 75 200)
123
对图像进行了形态学处理,分别是颜色空间转换,也就是彩色BGR转灰度,然后,进行了一次高斯滤波操作,可以让原图像模糊,目的就是为了去除噪音,最后计算出边缘信息,阈值设置为75到200。
cv2.imshow("Image" image)
cv2.imshow("Edged" edged)
cv2.waitKey(0)
cv2.destroyAllWindows()
1234
展示一下处理之后的结果。
这就是边缘检测之后的结果了,但是边缘检测之后的结果是一个点一个点的,所以我们要进行轮廓的提取。然后我们要进行一个轮廓的提取,我们要对图像中最外面的轮廓进行提取,因为我们要提取文档。
cnts = cv2.findContours(edged.copy() cv2.RETR_LIST cv2.CHAIN_APPROX_SIMPLE)[0]
cnts = sorted(cnts key = cv2.contourArea reverse = True)[:5]
12
这里我们首先进行了一个轮廓的提取,里面的参数cv2.RETR_LIST表示检测的轮廓不建立等级关系,cv2.CHAIN_APPROX_SIMPLE这里表示只简单的进行提取轮廓,用四个点来展示轮廓。因为这里返回了两个参数,老版本的CV返回的三个参数,但是我们只要轮廓参数就好了。所以设置索引为0,得到轮廓后呢,我们把轮廓按照面积大小进行了排序,由大到小,并且只取前五个。
for c in cnts:
# 计算轮廓近似
peri = cv2.arcLength(c 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()
12345678910111213141516
这里cv2.arcLength表示计算轮廓的周长。cv2.approxPolyDP主要功能是把一个连续光滑曲线折线化,其中0.02 * peri表示从原始轮廓到近似轮廓的最大距离,它是一个准确度参数。当轮廓是四个点的时候就拿出来,然后我们进行一个显示。得到的结果是: