怎样在5分钟内构筑一台功能强大的移动式文件扫描仪(翻译)
原文链接:How to Build a Kick-Ass Mobile Document Scanner in Just 5 Minutes - PyImageSearch
https://ww.pyimagesearch.com/2014/09/01/build-kick-ass-mobile-document-scanner-just-5-minutes/
怎样在5分钟内构筑一台功能强大的移动式文件扫描仪
by Adrian Rosebrock on September 1, 2014 in Image Processing, Tutorials
从我的关于skin detection博客,记起我的朋友 James没有?
嗯,昨天我在地区食品超市买了一杯咖啡和一些杂品,正是在讨论最新和最好CVPR论文的时间。
结帐后,我拿出我的iPhone,拍下一张收据照片--我喜欢这样做,这让我能够保持跟踪我每月钱的流向(例如,我在咸肉上花销$20)。
总之,James问我为什么不利用一台文件扫描APP,如 Genius Scan 或 TurboScan去扫描帐单到手机。
好问题。
我承认我没有想到这事。
但那时 James走得太远...
他打赌$100,说我不能自已制作一台移动式文件扫描APP.
嗯,你看自已笑话吧, James。
下次见面时我将拿到我的$100。
因为老实讲,文件扫描APP制作真的很容易。
GeniusScan. TurboScan. Scanner Pro.你给它命名--运行在幕后的计算机视频算法执行起来非常简单。
我打赌,读过此博客后,你能创建一个应用,也能完成一台大男孩式文件扫描仪。
你看,利用手机扫描文件分成三个简单步骤:
步1:边缘检查。
步2:利用图象的边缘去寻找被扫描纸张的轮廓。
步3:施加一个透视转换去获取文件的顶视图。真的,就这样。仅仅三步,你就能提交你自己的文件到APP库。
有趣吗?
读下去。解开秘密去构成一台你自己的移动扫描仪APP。
OpenCV和Python版本:
本例子在 Python 2.7/3+ 和 OpenCV 2.4/3+下运行。
样在5分钟内构筑一台功能强大的移动式文件扫描仪
上周我给了你一个特殊的款待—我个人的transform.py模块,那是我用在我的计算机视频和图象处理项目中。关于这个模块你可以更多阅读一下。
当你需要执行4点透视转换时,你应当利用这个模块。
你猜对了,我们要利用它去构筑自己的文件扫描仪。
让我们谈正事。
打开你喜欢的Python IDE,(我喜欢Sublime Text 2),创建一个新文件,命名为scan.py,让我们开始吧。
利用Python Python, OpenCV,以及计算机视频构筑一台文件扫描仪APP.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # import the necessary packages from pyimagesearch.transform import four_point_transform from skimage.filters import threshold_local import numpy as np import argparse import cv2 import imutils
# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i","--image", required = True, help ="Path to the image to be scanned") args = vars(ap.parse_args()) |
行2-7:运用必须的Python输入包,这是我们需要的。
开始时先输入我们的四点转换功能,上周我们讨论过此功能。
我们也使用 imutils模块,它包含放大缩小,旋转,裁剪图象这样的方便功能。关于 imutils你可以在我的博客中读到更多。安装imutils很简单:
|
接下来,让我们从scikit-image输入threshold_local功能。这个功能让我们对被扫描图象获得“黒与白”的感觉。
注(15/1/2018): threshold_adaptive 功能已经弃用。本博客更新应用 threshold_local。
最后,我们用NumPy做数字处理, argparse做解析命令行参数,用cv2做OpenCV绑定。
行10-13用来解析命令行参数。我们只需要一个单一开关图象,----image,它是到达包含要扫描文件图象的通路。
现在我们有了到达图象的通路,我们可以去看步1:边缘检测。
Step 1: Edge Detection边缘检测
利用OpenCV构筑我们的文件扫描仪APP的第一步是执行边缘检测。看看下面:
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # load the image and compute the ratio of the old height # to the new height, clone it, and resize it image=cv2.imread(args["image"]) ratio=image.shape[0]/500.0 orig=image.copy() image=imutils.resize(image,height=500)
# convert the image to grayscale, blur it, and find edges # in the image gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) gray=cv2.GaussianBlur(gray,(5,5),0) edged=cv2.Canny(gray,75,200)
# show the original image and the edge detected image print"STEP 1: Edge Detection" cv2.imshow("Image",image) cv2.imshow("Edged",edged) cv2.waitKey(0) cv2.destroyAllWindows() |
首先,在第17行中从磁盘装载图象。
为加速图象处理,并且使我们的边缘检测更精确,在行17-20我们调整所扫描的图象到高度为500象素。
我们也要特别注意跟踪图象的原始高度对新高度的比值(行18)--这就让你以原始图象高度执行扫描,而不是以缩放后的高度执行。
在第24行,我们对图象从RGB转换到灰度,在行26中执行精确检测。 Line 26.执行高斯模糊,移去频率噪声(在步2的轮廓检测中有帮助)
步1 的输出在行30和31中显示。
看看下面的示例文件:
图1:构筑文件扫描APP的第一步。左侧是原始;图象,右侧是图象中的边缘检测。
左侧你看到我的全食超市收据。注意图片是怎样一个角度拍摄的。它肯定不是90度,是页面的从上到下视图。进而,在图象中还有我的桌子。肯定这不是任何想要的扫描。我们完成了我们想要的“扫描”。
当然,右侧你看到了执行边缘检测后的图象。我们已经看到了收据的轮廓。
开头不错。
看第二步。
Step 2: Finding Contours找轮廓
轮廓检测不太难。
事实上,在构筑文件扫描仪时,你实质上具备优势。
.花点时考虑一下,你实际在构筑什么。
一台文件扫描仪,简单地扫描一张纸。
假设一张纸箱是矩形。
.矩形有四个边界。
因此,我们可以创建一个简单的启发去帮助我们构筑文件扫描仪。
启发式的方法是这样的:我们假设以精确四个点表达的图象的最大轮廓是我们的被扫描纸张。
这是合理可靠的假设--扫描仪APP假设你想要扫描的文件就是我们图象的主焦点。同样合理可靠假设是(至少是)此纸片有四个边缘。
这正是下面代码要做的:
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # find the contours in the edged image, keeping only the # largest ones, and initialize the screen contour cnts=cv2.findContours(edged.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) cnts=cnts[0]ifimutils.is_cv2()elsecnts[1] cnts=sorted(cnts,key=cv2.contourArea,reverse=True)[:5]
# loop over the contours forcincnts: # approximate the contour peri=cv2.arcLength(c,True) approx=cv2.approxPolyDP(c,0.02*peri,True)
# if our approximated contour has four points, then we # can assume that we have found our screen iflen(approx)==4: screenCnt=approx break
# show the contour (outline) of the piece of paper print("STEP 2: Find contours of paper") cv2.drawContours(image,[screenCnt],-1,(0,255,0),2) cv2.imshow("Outline",image) cv2.waitKey(0) cv2.destroyAllWindows() |
首先在行37中我们寻找已确定边缘的图象的轮廓。在行38中OpenCV 2.4 和
OpenCV 3分别返回轮廓。
我喜欢做的一个好的办法是按面积对轮廓排序,只保留最大者(行39)。这样我们仅只检测最大轮廓者,而抛弃其余。
在行42开始对轮廓循环,近似于行44和行45的点数。
如果近似的轮廓具有四个点(行49),则假设我们找到了图象中的文件。
再说一次,这是相当可行的假设。扫描仪APP 假设(1)被扫描文件就是图象的主焦点。(2)文件是矩形,从而具有四个边缘。
从这里,行55和行56显示要扫描文件的轮廓。
图2:构筑文件扫描仪App的第二步是利用图象的边缘去找到纸张的轮廓。
正如你能够看到的那样,我们成功地利用检测到的图象的边缘找到文件的轮廓,由围绕我的收据的绿色矩形表明。
最后,进入第3步,用我的四点转换功能作对齐。
步3:施加透视转换&临界值
构筑一台文件扫描仪的最后一步是取四点表达文件的轮廓,并施加透视转换从而获取图象的鸟瞰视图。
看看:
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | # apply the four point transform to obtain a top-down # view of the original image warped=four_point_transform(orig,screenCnt.reshape(4,2)*ratio)
# convert the warped image to grayscale, then threshold it # to give it that 'black and white' paper effect warped=cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY) T=threshold_local(warped,11,offset=10,method="gaussian") warped=(warped>T).astype("uint8")*255
# show the original and scanned images print("STEP 3: Apply perspective transform") cv2.imshow("Original",imutils.resize(orig,height=650)) cv2.imshow("Scanned",imutils.resize(warped,height=650)) cv2.waitKey(0) |
行62执行挠曲转换。事实上,所有重要工作都是由four_point_transform功能处理的。在下周博客中你可以读到更多东西。
我们通过两个参进入四点转换(four_point_transform):第一个参数是我们从磁盘上装入的原始图象(不是缩放的),第二参数是代表文件的轮廓,乘以缩放比。
那么,你可能想知道,为什么乘以缩放比?
乘以缩放比是因为我们执行边缘检测并按高=500象素的缩放后图象找到轮廓。
当然,我们要执行原图象的扫描,而不是对缩放图象的扫描,因此我们用缩放比乘轮廓点。
在行66-68中,为获得图象的黒白感,我们把变形的图象转换成灰度,并施加自适应阀值变换。
最后,在行72-74中显示输出。
说到输出,请看看我们的输出文件:
图3:完成我们的扫描仪第3步,透视转换。原图在左侧,扫描所得图在右侧。
左侧是从磁盘装入的原图。右侧是扫描所得图形。
注意被扫描图象的视角怎样被改变了-我们得到顶视,90度的图象视图。
幸亏有了我们的自适应算法,我们有了良好的,清晰的黒白的文件感。
我们已经成功构筑了一台文件扫描仪!
时间小于5分钟,少于75行代码(多数是注释)。
更多例子
收据例子很好。
但这种工作方法适用于普通纸张吗?
当然!
我打印出“Practical Python and OpenCV”书的第22页,这是一本用于学习计算机视频的可靠快速启动指南
图4:利用计算机视频对扫描文件施加边缘检测。
你能看到左侧是原图,右侧是检测所得图象的边缘。
现在,让我们寻找页面的轮廓:
图5:利用检测到的图象去寻找被扫描页面的外形与轮廓
最后,我们施加透视转换和阀值图象。
图6:左侧是原图象。右侧是我们看到的扫描所得文本。扫描是成功的。
这是另一个成功的扫描。
Where to Next?下面做什么?
现在你有了构筑一台移动式文件扫描仪的代码,或许你想要做成一个APP发布到你自已的APP商店!
事实上,我觉得应该。
那将是一个伟大实践...
另一个伟大的“下一步”是施加OCR到图象中的文件。一仅你能够扫描文件产生PDF文件,而且让你还能编辑文本!
Summary总结
在本博客中我告诉了你怎样用OpenCV在5分钟内仅用75行Python码,构筑了一台移动式文件扫描仪。。
文件扫描可以分成三个不同的简单步骤。
第一步是施加边缘检测。
第二步是寻找表达我们所需要扫描文件图象的轮廓。
最后一步是施加透视转换以获取图象的顶视,90度视图,如同我们扫描的文件。
这样你成功了。在5分钟内做成一台移动式文件扫描仪。
原谅我,我打电话给James,让他付款…
你喜欢这篇博客吗?
嘿,你是否欣赏这篇关于构筑一台移动式文件扫描仪呢?
要是欣赏,我想你会喜欢我的书“ Practical Python and OpenCV”。
当你学习案例研究包时,你将学习怎样检测图象中的面孔,认识手写字,利用关键点检测以及
有趣吗?
Just click here and pickup a copy.那就点击这里选择一本副本。
在一个简单的周末,你解开了计算机视频项目应用秘密,你成了一名项目专家!
(以下略)