1、扫描文档的步骤html
一、scanner.pypython
import cv2 import numpy as np import rect #读入要检测的图片,此处读入单张图片。若是分辨率足够好的话,咱们也可使用笔记本电脑的摄像头。 image = cv2.imread('test.jpg') #从新设置图片的大小,以便对其进行处理:选择最佳维度,以便重要内容不会丢失 image = cv2.resize(image, (1500,880)) #建立原始图像的副本 orig = image.copy() #对图像进行灰度处理,并进而进行行高斯模糊处理 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) #使用canny算法进行边缘检测 edged = cv2.Canny(blurred,0,50) #建立canny算法处理后的副本 orig_edged = edged.copy() #找到边缘图像中的轮廓,只保留最大的,并初始化屏幕轮廓 #findContours()函数用于从二值图像中查找轮廓 img, contours, hierarchy = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) #使用python中的sorted函数返回contours从新排序的结果(降序),排序规则(key):根据计算的轮廓面积大小 contours = sorted(contours, key = cv2.contourArea, reverse = True) #获得近似轮廓 for c in contours: p = cv2.arcLength(c, True) #计算封闭轮廓的周长或者曲线的长度 approx = cv2.approxPolyDP(c, 0.02*p, True) #指定0.02*p精度逼近多边形曲线,这种近似曲线为闭合曲线,所以参数closed为True if len(approx) == 4: #若是逼近的是四边形 target = approx #则此轮廓为要找的轮廓 break #找到即跳出循环 #将目标映射到800*800四边形 approx = rect.rectify(target) pts2 = np.float32([[0,0],[800,0],[800,800],[0,800]]) #透视变换 # 使用gtePerspectiveTransform函数得到透视变换矩阵:approx是源图像中四边形的4个定点集合位置;pts2是目标图像的4个定点集合位置 M = cv2.getPerspectiveTransform(approx, pts2) # 使用warpPerspective函数对源图像进行透视变换,输出图像dst大小为800*800 dst = cv2.warpPerspective(orig, M, (800,800)) #画出轮廓,-1表示全部的轮廓,画笔颜色为(0,255,0),粗细为2 cv2.drawContours(image, [target], -1, (0, 255, 0), 2) #对透视变换后的图像进行灰度处理 dst = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY) #对透视变换后的图像使用阈值进行约束得到扫描结果 # 使用固定阈值操做:threshold()函数:有四个参数:第一个是原图像,第二个是进行分类的阈值,第三个是高于(低于)阈值时赋予的新值, # 第四个是一个方法选择参数:cv2.THRESH_BINARY(黑白二值) # 该函数返回值有两个参数,第一个是retVal(获得的阈值值(在OTSU会用到)),第二个是阈值化后的图像 ret, th1 = cv2.threshold(dst, 127, 255, cv2.THRESH_BINARY) #进行固定阈值处理,获得二值图像 # 使用Otsu's二值化,在最后一个参数加上cv2.THRESH_OTSU ret2, th2 = cv2.threshold(dst, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) # 使用自适应阈值操做:adaptiveThreshold()函数 # 第二个参数为领域内均值,第五个参数为规定正方形领域大小(11*11),第六个参数是常数C:阈值等于均值减去这个常数 th3 = cv2.adaptiveThreshold(dst, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) # 第二个参数为领域内像素点加权和,权重为一个高斯窗口,第五个参数为规定正方形领域大小(11*11),第六个参数是常数C:阈值等于加权值减去这个常数 th4 = cv2.adaptiveThreshold(dst,255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) #输出处理后的图像 cv2.imshow("原始图像", orig) cv2.imshow("原始图像经灰度变换", gray) cv2.imshow("原始图像经高斯模糊处理", blurred) cv2.imshow("原始图像经canny边缘检测后的结果", orig_edged) cv2.imshow("边界被标记的原图", image) cv2.imshow("固定阈值操做", th1) cv2.imshow("Otsu二值化", th2) cv2.imshow("自适应阈值(领域内均值)", th3) cv2.imshow("自适应阈值(领域内像素点加权和)", th4) cv2.imshow("透视变换后的图像", dst) cv2.waitKey(0) cv2.destroyAllWindows()
二、rect.py算法
import numpy as np def rectify(h): h = h.reshape((4,2)) #改变数组的形状,变成4*2形状的数组 hnew = np.zeros((4,2), dtype = np.float32) #建立一个4*2的零矩阵 #肯定检测文档的四个顶点 add = h.sum(1) hnew[0] = h[np.argmin(add)] #argmin()函数是返回最大数的索引 hnew[2] = h[np.argmax(add)] diff = np.diff(h, axis = 1) #沿着制定轴计算第N维的离散差值 hnew[1] = h[np.argmin(diff)] hnew[3] = h[np.argmax(diff)] return hnew
注意:在程序调试时出现如下错误---ValueError: too many values to unpack (expected 2)数组
此错误说明是函数输出的值没有足够的参数对其进行存储,即变量个数不够app
是由于在python2和python3中,cv2.findContours():
python2中会返回两个值:contours, hierarchy函数
python三中会返回三个值:img, contours, hierarchyspa
#findContours()函数用于从二值图像中查找轮廓 #python2 contours, hierarchy = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) #python3 img, contours, hierarchy = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
三、结果调试