使用Python和OpenCV在视频中实时监测条形码

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,开始编码:

如果你看过之前的博客,那么这段关于在图像中检测条形码的代码将非常熟悉。

第一件事就是导入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,开始构建第二个部件:

我们开始也是导入我们需要的库。出于方便管理的目的,我们将simple_barcode_detection函数放到pyimagesearch模块中,并在此导入。然后我们导入argparse来解析命令,导入cv2来调用OpenCV的函数。

6-9行解析我们的命令行参数。我们设置了一个可选项,–video,该选项指定需要检测条形码的视频文件路径。

注意:这个切换选项对于运行源代码提供的例子视频还是很有用的。忽略这个选项默认就是用笔记本或是台式机上的摄像头。

13-18行获取一个camera引用,如果没有–video选项,那么就获取一个webcam;反之就活去一个视频文件句柄(17-18行)。

设置完成后,我们就可以开始加载我们的条形码检测模块了。

第2行我们开始循环抓取视频中的图像帧,直到抓取完视频中的图像或者说我们按下q键然后退出循环。

第5行中,我们访问camera。返回值是2-tuple.其一是boolean值,表示是否抓取成功(从摄像头或者视频文件)。frame这是实际抓取到的图像数据。

如果抓取失败(例如到了视频文件尾部),11和12行就退出循环。

一旦抓取到图像帧,在16行我们就利用条形码检测模块检测图像中的条形码,返回外接矩形范围。

我们将最终的包络区域绘制在图像中(20行),最后显示到屏幕上(23和24行).

最后,29和30行则检测q键是否按下,按下就退出循环。32和33行就进行camera对象的清理操作。

如你所见,我们的脚本还是比较简洁的。开始运行我们的代码,看看结果如何。

成功检测视频中的条形码

我们试一些例子,打开终端,输入如下指令:


本博客的开始部分就展示了我们脚本的输出结果。下面则是三个成功的条形码检测视频截图。

图2:在Xbox视频游戏流中,成功检测条形码

 我们看一个在衣服优惠券上检测的例子:


如下是一个视频流截图:

图3:使用Python和OpenCV成功检测条形码的示例

完整视频输出:

https://www.youtube.com/watch?v=YlF8hI5BGi8

当然,如我之前所说,我们的方法只在很好的条件下才有效(稍后会详述该方法的缺点和限制)

这就是一个条形码检测失败的例子。

图4:一个失败的例子。条形码离摄像头太远了

该种情形下,条形码离摄像头太远,图像中也有太多的干扰和噪声,例如视频游戏盒子上有很多的大块的文本区。

这个也是个失败案例,我只是想开个玩笑而已。

图5:我的耳朵当然不是条形码

再一次说,我们这只是一个很简单的解决办法,并不适用于所有情况。虽说不是一个健壮的解决方案,但如果能满足下述条件的情况下,简单的图像处理还是能提供让人惊讶的够好的结果。

限制条件和缺点

就如博文中见到的,我们的方法在一定假设条件下还是能顺利检测到视频中的条形码。

第一个假设:我们的相机以90度的静态视角来观察这个条形码。以使条形码区域的图像梯度能够被条形码检测器检测到。

第二个假设:我们的视频或者摄像头是近距离查看条形码,也就是我们拿着智能手机直接对着条形码的上面,而不是远离摄像头。条形码离相机越远,成功检测的概率就越小。

那么怎样改进我们的条形码检测器呢?

好问题

Christoph Oberhofer 提供了一篇很好的综述,关于在QuaggaJS中如何实现条形码的鲁棒检测。 Tomasz Malisiewicz也写了一篇很好的文章,关于如何利用他的VMX中的机器学习算法来训练出一个条形码检测器。如果你想更近一步了解这些内容,请一定要看这些文章。

总结

基于之前在图像中检测条形码的程序,本文中我们将代码分为两部分:

  • 一个部件就是检测视频帧的条形码
  • 另一个则是访问视频源(摄像头或者视频文件)

然后使用条形码检测模块检测视频中的条形码。

我们的方法有如下假设:

  • 第一个假设就是我们摄像头的向下看的静态视角为90度。
  • 第二个假设是我们会拉近看图像中的条形码,且图像中没有其他干扰物或噪声。

事实上,能否满足这些假设全取决于你的实际应用场景。

至少,我想通过这篇博文给你说明的是一些基本的图像处理技术,以及如何采用Python和OpenCV,实现这些图像处理技术来构成一个简单的条形码检测器。

2 3 收藏 评论

关于作者:Den

简介还没来得及写 :) 个人主页 · 我的文章 · 14

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部