使用Python+OpenCV构建文档扫描程序

版权声明:转载需说明出处! https://blog.csdn.net/m0_38106923/article/details/83151724

首先给各位展示原始图片:

使用自己搭建的文档扫描程序扫描效果如下图: 

图一:查找轮廓 

图二:边缘检测

图三:应用透视变换和阈值 

使用OpenCV构建文档扫描程序只需三个简单步骤即可完成:

扫描二维码关注公众号,回复: 4251153 查看本文章
  • 第1步:  检测边缘。
  • 第2步:  使用图像中的边缘找到表示正在扫描的纸张的轮廓(轮廓)。
  • 第3步:  应用透视变换获取文档的自上而下视图。

下面建立自己的移动扫描仪应用程序吧~

import cv2
import numpy as np
import rect

##这里添加图像。
##如果分辨率足够好,我们也可以使用笔记本电脑的摄像头。
image = cv2.imread('./1.jpg')

##调整图像大小以便处理
##选择最佳维度,以便不丢失重要内容
image = cv2.resize(image, (605, 807))

#创建原始图像拷贝
orig = image.copy()

#转换成灰度和模糊到平滑
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
#blurred = cv2.medianBlur(gray, 5)

#应用Canny边缘检测
edged = cv2.Canny(blurred, 0, 50)
orig_edged = edged.copy()

##找到边缘图像中的轮廓,只保留最大的轮廓,并初始化屏幕轮廓
(_,contours, _) = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)

#x,y,w,h = cv2.boundingRect(contours[0])
#cv2.rectangle(image,(x,y),(x+w,y+h),(0,0,255),0)

#得到近似轮廓
for c in contours:
    p = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * p, 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]])

M = cv2.getPerspectiveTransform(approx,pts2)
dst = cv2.warpPerspective(orig,M,(800,800))

cv2.drawContours(image, [target], -1, (0, 255, 0), 2)
dst = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)


#利用扭曲图像上的阈值进行扫描效果(如果需要)
ret,th1 = cv2.threshold(dst,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(dst,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(dst,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)
ret2,th4 = cv2.threshold(dst,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)


cv2.imshow("Original.jpg", orig)
cv2.imshow("Original Gray.jpg", gray)
cv2.imshow("Original Blurred.jpg", blurred)
cv2.imshow("Original Edged.jpg", orig_edged)
cv2.imshow("Outline.jpg", image)
cv2.imshow("Thresh Binary.jpg", th1)
cv2.imshow("Thresh mean.jpg", th2)
cv2.imshow("Thresh gauss.jpg", th3)
cv2.imshow("Otsu's.jpg", th4)
cv2.imshow("dst.jpg", dst)

#其他阈值法
##ret,thresh1 = cv2.threshold(dst,127,255,cv2.THRESH_BINARY)
##ret,thresh2 = cv2.threshold(dst,127,255,cv2.THRESH_BINARY_INV)
##ret,thresh3 = cv2.threshold(dst,127,255,cv2.THRESH_TRUNC)
##ret,thresh4 = cv2.threshold(dst,127,255,cv2.THRESH_TOZERO)
##ret,thresh5 = cv2.threshold(dst,127,255,cv2.THRESH_TOZERO_INV)
##
##cv2.imshow("Thresh Binary", thresh1)
##cv2.imshow("Thresh Binary_INV", thresh2)
##cv2.imshow("Thresh Trunch", thresh3)
##cv2.imshow("Thresh TOZERO", thresh4)
##cv2.imshow("Thresh TOZERO_INV", thresh5)


cv2.waitKey(0)
cv2.destroyAllWindows()

注意Demo中会有一个易错点!!!

关于解决cv2.findContours返回值too many values to unpack (expected 2)的问题。

根据网上的 教程,Python OpenCV的轮廓提取函数会返回两个值,第一个为轮廓的点集,第二个是各层轮廓的索引。但是实际调用时我的程序报错了,错误内容如下

too many values to unpack (expected 2)

其实是接受返回值不符,如果你仅仅使用一个变量a去接受返回值,调用len(a),你会发现长度为3,也就是说这个函数实际上返回了三个值。

第一个,也是最坑爹的一个,它返回了你所处理的图像;

第二个,正是我们要找的,轮廓的点集;

第三个,各层轮廓的索引。

猜你喜欢

转载自blog.csdn.net/m0_38106923/article/details/83151724
今日推荐