使用Python和OpenCV在视频中实时监测条形码,pythonopencv,未经许可,禁止转载!英文
使用Python和OpenCV在视频中实时监测条形码,pythonopencv,未经许可,禁止转载!英文
本文由 编橙之家 - Den 翻译,Daetalus 校稿。未经许可,禁止转载!英文出处:www.pyimagesearch.com。欢迎加入翻译组。
https://www.youtube.com/watch?v=oooDn5SBUAg
今天的博客是上篇博客的继续,上篇博客是使用Python和OpenCV检测图像中的条形码。
今天我们将重构代码去检测视频中的条形码。
举个例子,下图是我实验的一个截图,我手持Modern Warfare 3,我们的程序能够顺利检测到其背面的条形码。
图1:使用Python和OpenCV检测视频流中的条形码
注意:非常感谢Jason的建议,他在上次的博客中留言道:要是能检测视频中的条形码将是很酷的事情。你说的很对,这确实很酷。
举个例子,假设我们12月26日这天正在电玩店工作。店外面排起了足有十个街区长的队伍,这些孩子正等着退货或是换货(显而易见,他们的父母或亲戚买错东西了)。
为了加快换货速度,我们就到队伍中间去一个一个去扫描他们的条形码。但是问题来了,激光扫描枪的线是连接到柜台上的电脑上的,队伍可有10个街区长,怎么都够不到。
既然这样,我有个计划:那我们可以用智能手机代替。
使用我们的iPhone(或者Android),带上摄像头,切换到录像模式,向着漫漫长队开工吧。
只要手机摄像头扫描到商品上的条形码,我们的APP就会检测到它的信息并及时传回到柜台。
听起来是不是太美好了,简直难以置信。
也许吧。毕竟,你也可以用激光扫描枪和无线连接来完成这项工作。况且稍后也会看到我们方法的局限性。
但是,我还是觉得这是一个关于使用OpenCV和Python检测条形码的好例子,该例展示了利用OpenCV函数来构建一个真实的应用。
不管怎样,继续往下看,看我们是怎么使用OpenCV和Python来检测视频中的条形码的。
使用Python和OpenCV在视频中实时监测条形码
这就是我们的方案,我们的视频条形码检测系统分成两个部分:
- 部件1:该模块检测图像中的条形码(本例中,既是视频中的帧图像)。上篇博客中我们已经实现了该功能,现在我们只需要简单修改一下代码即可
- 部件2:该模块的功能是读取视频源,然后调用条形码检测模块。
我们先讲解第一部分,单帧图像的条形码检测。
部件1:视频帧中的条形码检测
由于上篇博客中已经讲到图像中条形码的检测,这里我就不再熬述。
尽管这样,基于完整性考虑,我快速过一下这部分内容。打开一个新文件,取名simple_barcode_detection.py,开始编码:
Python# import the necessary packages import numpy as np import cv2 def detect(image): # convert the image to grayscale gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # compute the Scharr gradient magnitude representation of the images # in both the x and y direction gradX = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 1, dy = 0, ksize = -1) gradY = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 0, dy = 1, ksize = -1) # subtract the y-gradient from the x-gradient gradient = cv2.subtract(gradX, gradY) gradient = cv2.convertScaleAbs(gradient) # blur and threshold the image blurred = cv2.blur(gradient, (9, 9)) (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY) # construct a closing kernel and apply it to the thresholded image kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) # perform a series of erosions and dilations closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4) # find the contours in the thresholded image (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # if no contours were found, return None if len(cnts) == 0: return None # otherwise, sort the contours by area and compute the rotated # bounding box of the largest contour c = sorted(cnts, key = cv2.contourArea, reverse = True)[0] rect = cv2.minAreaRect(c) box = np.int0(cv2.cv.BoxPoints(rect)) # return the bounding box of the barcode return box
如果你看过之前的博客,那么这段关于在图像中检测条形码的代码将非常熟悉。
第一件事就是导入NumPy库来做数值计算,cv2来调用OpenCV。
第5行定义的函数带1个参数,就是需要检测条形码的图像。
第7行将图像转换为灰度图像,9-16行检测图像中具有水平梯度高和垂直梯度低的区域(想了解更多,请参看前面条形码检测的博客)。
19和20行分别模糊图像和二值化图像,方便后续23-28行的形态学处理。形态学操作用来检出条形码的矩形区域,忽略其他区域。
现在我们已经有了条形码的矩形区域,接下来在30-31行就是找出其轮廓。
如果没有找到轮廓,那么就认为没有条形码(35和36行)。
如果找到了轮廓,在40行我们就对轮廓进行排序(轮廓按面积大小降序排列)。这里,我们同样假设面积最大的轮廓就是条形码的位置。
最后,我们拿到这个轮廓,然后计算该轮廓的矩形包络(41和42行)。然后45行就返回该包络的x,y坐标,意即条形码的位置。
现在,我们这个简单的条形码检测就告完成,步入第二部分,图像获取,然后整合第一部分。
部件2:访问摄像头,检测视频中的条形码
我们开始构建一个驱动接口以便后面检测视频中的条形码。打开并新建一个文件,取名detect_barcode.py,开始构建第二个部件:
Python# import the necessary packages from pyimagesearch import simple_barcode_detection import argparse import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-v", "--video", help = "path to the (optional) video file") args = vars(ap.parse_args()) # if the video path was not supplied, grab the reference to the # camera if not args.get("video", False): camera = cv2.VideoCapture(0) # otherwise, load the video else: camera = cv2.VideoCapture(args["video"])
我们开始也是导入我们需要的库。出于方便管理的目的,我们将simple_barcode_detection函数放到pyimagesearch模块中,并在此导入。然后我们导入argparse来解析命令,导入cv2来调用OpenCV的函数。
6-9行解析我们的命令行参数。我们设置了一个可选项,–video,该选项指定需要检测条形码的视频文件路径。
注意:这个切换选项对于运行源代码提供的例子视频还是很有用的。忽略这个选项默认就是用笔记本或是台式机上的摄像头。
13-18行获取一个camera引用,如果没有–video选项,那么就获取一个webcam;反之就活去一个视频文件句柄(17-18行)。
设置完成后,我们就可以开始加载我们的条形码检测模块了。
Python# keep looping over the frames while True: # grab the current frame (grabbed, frame) = camera.read() # check to see if we have reached the end of the # video if not grabbed: break # detect the barcode in the image box = simple_barcode_detection.detect(frame) # if a barcode was found, draw a bounding box on the frame cv2.drawContours(frame, [box], -1, (0, 255, 0), 2) # show the frame and record if the user presses a key cv2.imshow("Frame", frame) key = cv2.waitKey(1) & 0xFF # if the 'q' key is pressed, stop the loop if key == ord("q"): break # cleanup the camera and close any open windows camera.release() cv2.destroyAllWindows()
第2行我们开始循环抓取视频中的图像帧,直到抓取完视频中的图像或者说我们按下q键然后退出循环。
第5行中,我们访问camera。返回值是2-tuple.其一是boolean值,表示是否抓取成功(从摄像头或者视频文件)。frame这是实际抓取到的图像数据。
如果抓取失败(例如到了视频文件尾部),11和12行就退出循环。
一旦抓取到图像帧,在16行我们就利用条形码检测模块检测图像中的条形码,返回外接矩形范围。
我们将最终的包络区域绘制在图像中(20行),最后显示到屏幕上(23和24行).
最后,29和30行则检测q键是否按下,按下就退出循环。32和33行就进行camera对象的清理操作。
如你所见,我们的脚本还是比较简洁的。开始运行我们的代码,看看结果如何。
成功检测视频中的条形码
我们试一些例子,打开终端,输入如下指令:
Python$ python detect_barcode.py --video video/video_games.mov
本博客的开始部分就展示了我们脚本的输出结果。下面则是三个成功的条形码检测视频截图。
图2:在Xbox视频游戏流中,成功检测条形码
我们看一个在衣服优惠券上检测的例子:
Python$ python detect_barcode.py --video video/coupon.mov
如下是一个视频流截图:
图3:使用Python和OpenCV成功检测条形码的示例
完整视频输出:
https://www.youtube.com/watch?v=YlF8hI5BGi8
当然,如我之前所说,我们的方法只在很好的条件下才有效(稍后会详述该方法的缺点和限制)
这就是一个条形码检测失败的例子。
图4:一个失败的例子。条形码离摄像头太远了
该种情形下,条形码离摄像头太远,图像中也有太多的干扰和噪声,例如视频游戏盒子上有很多的大块的文本区。
这个也是个失败案例,我只是想开个玩笑而已。
图5:我的耳朵当然不是条形码
再一次说,我们这只是一个很简单的解决办法,并不适用于所有情况。虽说不是一个健壮的解决方案,但如果能满足下述条件的情况下,简单的图像处理还是能提供让人惊讶的够好的结果。
限制条件和缺点
就如博文中见到的,我们的方法在一定假设条件下还是能顺利检测到视频中的条形码。
第一个假设:我们的相机以90度的静态视角来观察这个条形码。以使条形码区域的图像梯度能够被条形码检测器检测到。
第二个假设:我们的视频或者摄像头是近距离查看条形码,也就是我们拿着智能手机直接对着条形码的上面,而不是远离摄像头。条形码离相机越远,成功检测的概率就越小。
那么怎样改进我们的条形码检测器呢?
好问题
Christoph Oberhofer 提供了一篇很好的综述,关于在QuaggaJS中如何实现条形码的鲁棒检测。 Tomasz Malisiewicz也写了一篇很好的文章,关于如何利用他的VMX中的机器学习算法来训练出一个条形码检测器。如果你想更近一步了解这些内容,请一定要看这些文章。
总结
基于之前在图像中检测条形码的程序,本文中我们将代码分为两部分:
- 一个部件就是检测视频帧的条形码
- 另一个则是访问视频源(摄像头或者视频文件)
然后使用条形码检测模块检测视频中的条形码。
我们的方法有如下假设:
- 第一个假设就是我们摄像头的向下看的静态视角为90度。
- 第二个假设是我们会拉近看图像中的条形码,且图像中没有其他干扰物或噪声。
事实上,能否满足这些假设全取决于你的实际应用场景。
至少,我想通过这篇博文给你说明的是一些基本的图像处理技术,以及如何采用Python和OpenCV,实现这些图像处理技术来构成一个简单的条形码检测器。
相关内容
- 15 分钟用 ML 破解一个验证码系统,ml验证码,未经许可,
- [OpenCV-Python] OpenCV 中的图像处理 部分 IV (二),,部分
- 銆怉I鍩虹銆憄ython:openCV鈥斺€斿浘鍍忕畻鏈繍绠楋
- python3.6+opencv3.4实现鼠标交互查看图片像素,
- Python实现批量修改图片格式和大小的方法【opencv库与
- Python+OpenCV实现图像融合的原理及代码,pythonopencv
- python使用opencv按一定间隔截取视频帧,pythonopencv
- python opencv 直方图反向投影的方法,pythonopencv
- python opencv之SURF算法示例,opencvsurf
- python opencv之SIFT算法示例,opencvsift
评论关闭