zoukankan      html  css  js  c++  java
  • 用 Python 和 OpenCV 检测图片上的条形码(转载)

    原文地址:http://python.jobbole.com/80448/

    假设我们要检测下图中的条形码:

    图1:包含条形码的示例图片

    现在让我们开始写点代码,新建一个文件,命名为detect_barcode.py,打开并编码:

    我们首先做的是导入所需的软件包,我们将使用NumPy做数值计算,argparse用来解析命令行参数,cv2是OpenCV的绑定。

    然后我们设置命令行参数,我们这里需要一个简单的选择,–image是指包含条形码的待检测图像文件的路径。

    现在开始真正的图像处理:

    12~13行:从磁盘载入图像并转换为灰度图。

    17~18行:使用Scharr操作(指定使用ksize = -1)构造灰度图在水平和竖直方向上的梯度幅值表示。

    21~22行:Scharr操作之后,我们从x-gradient中减去y-gradient,通过这一步减法操作,最终得到包含高水平梯度和低竖直梯度的图像区域。

    上面的gradient表示的原始图像看起来是这样的:

    图:2:条形码图像的梯度表示

    注意条形码区域是怎样通过梯度操作检测出来的。下一步将通过去噪仅关注条形码区域。

    25行:我们要做的第一件事是使用9*9的内核对梯度图进行平均模糊,这将有助于平滑梯度表征的图形中的高频噪声。

    26行:然后我们将模糊化后的图形进行二值化,梯度图中任何小于等于255的像素设为0(黑色),其余设为255(白色)。

    模糊并二值化后的输出看起来是这个样子:

    图3:二值化梯度图以此获得长方形条形码区域的粗略近似

    然而,如你所见,在上面的二值化图像中,条形码的竖杠之间存在缝隙,为了消除这些缝隙,并使我们的算法更容易检测到条形码中的“斑点”状区域,我们需要进行一些基本的形态学操作:

    29行:我们首先使用cv2.getStructuringElement构造一个长方形内核。这个内核的宽度大于长度,因此我们可以消除条形码中垂直条之间的缝隙。

    30行:这里进行形态学操作,将上一步得到的内核应用到我们的二值图中,以此来消除竖杠间的缝隙。

    现在,你可以看到这些缝隙相比上面的二值化图像基本已经消除:

    图4:使用形态学中的闭运算消除条形码竖条之间的缝隙

    当然,现在图像中还有一些小斑点,不属于真正条形码的一部分,但是可能影响我们的轮廓检测。

    让我们来消除这些小斑点:

    我们这里所做的是首先进行4次腐蚀(erosion),然后进行4次膨胀(dilation)。腐蚀操作将会腐蚀图像中白色像素,以此来消除小斑点,而膨胀操作将使剩余的白色像素扩张并重新增长回去。

    如果小斑点在腐蚀操作中被移除,那么在膨胀操作中就不会再出现。

    经过我们这一系列的腐蚀和膨胀操作,可以看到我们已经成功地移除小斑点并得到条形码区域。

    图5:应用一系列的腐蚀和膨胀来移除不相关的小斑点

    最后,让我们找到图像中条形码的轮廓:

    38~40行:幸运的是这一部分比较容易,我们简单地找到图像中的最大轮廓,如果我们正确完成了图像处理步骤,这里应该对应于条形码区域。

    43~44行:然后我们为最大轮廓确定最小边框

    48~50行:最后显示检测到的条形码

    正如你在下面的图片中所见,我们已经成功检测到了条形码:

    图6:成功检测到示例图像中的条形码

    下一部分,我们将尝试更多图像。

    成功的条形码检测

    要跟随这些结果,请使用文章下面的表单去下载本文的源码以及随带的图片。

    一旦有了代码和图像,打开一个终端来执行下面的命令:

    图7:使用OpenCV检测图像中的一个条形码

    检测椰油瓶子上的条形码没有问题。

    让我们试下另外一张图片:

    图8:使用计算机视觉检测图像中的一个条形码

    我们同样能够在上面的图片中找到条形码。

    关于食品的条形码检测已经足够了,书本上的条形码怎么样呢:

    图9:使用Python和OpenCV检测书本上的条形码

    没问题,再次通过。

    那包裹上的跟踪码呢?

    图10:使用计算机视觉和图像处理检测包裹上的条形码

    我们的算法再次成功检测到条形码。

    最后,我们再尝试一张图片,这个是我最爱的意大利面酱—饶氏自制伏特加酱(Rao’s Homemade Vodka Sauce):

    图11:使用Python和Opencv很容易检测条形码

    我们的算法又一次检测到条形码!

    总结

    这篇博文中,我们回顾了使用计算机视觉技术检测图像中条形码的必要步骤,使用Python编程语言和OpenCV库实现了我们的算法。

    算法概要如下:

    1. 计算x方向和y方向上的Scharr梯度幅值表示
    2. 将x-gradient减去y-gradient来显示条形码区域
    3. 模糊并二值化图像
    4. 对二值化图像应用闭运算内核
    5. 进行系列的腐蚀、膨胀
    6. 找到图像中的最大轮廓,大概便是条形码

    需要注意的是,该方法做了关于图像梯度表示的假设,因此只对水平条形码有效。

    如果你想实现一个更加鲁棒的条形码检测算法,你需要考虑图像的方向,或者更好的,应用机器学习技术如Haar级联或者HOG + Linear SVM去扫描图像条形码区域。





  • 相关阅读:
    洛谷P1022计算器的改良(字符串+各种细节坑点考虑)
    hdu5974Math Problem(数学,思维,公式,取巧猜)
    牛客练习赛26A平面(数学公式)
    洛谷P1217回文质数(特判筛选,取巧判断顺序)
    尺取法
    51nod1006最长公共子序列(lcs输出路径)
    51nod1175区间第k大(小)数(主席树模板)
    51nod1174区间中最大的数(rmq模板或线段树 && 线段树标准模板)
    51nod1094和为k连续区间(前缀和+map判断优化)
    矩阵快速幂求递推数列
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/7441727.html
Copyright © 2011-2022 走看看