学习OpenCV——对图像中的多个条形码进行定位

最近搞了搞条码识别相关的东西,今天总结一下。

我们常用的条码识别工具有zxing、zbar等等。zxing的使用比较简单,一个函数直接调用就可以了,但是目前我发现它只能识别一张图中的一个条码,如果你要读多个条码那是不行的。这里贴一下使用方法:

Bitmap code_bmp = roi.ToBitmap();
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
reader.Options.PureBarcode = false;
using (Bitmap bmp = code_bmp)
{
    Result result = reader.Decode(bmp);
    inf = result.Text.ToString();
}

然后就是zbar,python有pyzbar这个包,亲测是比较好用的,它可以同时识别一张图上的多个条码,而且还可以给出每个条码的位置信息。这是我在网上找到的代码,并且也自己试了一下:

    frame = cv2.imread('/test/9.bmp')
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    barcodes = pyzbar.decode(gray)
    for barcode in barcodes:
        # 提取条形码的边界框的位置
        # 画出图像中条形码的边界框
        (x, y, w, h) = barcode.rect
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)

        # 条形码数据为字节对象,所以如果我们想在输出图像上
        #  画出来,就需要先将它转换成字符串
        barcodeData = barcode.data.decode("utf-8")
        # 绘出图像上条形码的数据和条形码类型
        barcodeType = barcode.type

        # 把cv2格式的图片转成PIL格式的图片然后在上标注二维码和条形码的内容
        img_PIL = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

        font = ImageFont.truetype('STFANGSO.TTF', 25)

        # 字体颜色
        fillColor = (0, 255, 0)

        # 文字输出位置
        position = (x, y - 25)

        # 输出内容
        strl = barcodeData
        # 需要先把输出的中文字符转换成Unicode编码形式(str.decode("utf-8))

        # 创建画笔
        draw = ImageDraw.Draw(img_PIL)
        draw.text(position, strl, font=font, fill=fillColor)
        # 使用PIL中的save方法保存图片到本地
        img_PIL.save('结果图.jpg', 'jpeg')
        # 向终端打印条形码数据和条形码类型
        print("扫描结果==》 类别: {0} 内容: {1}".format(barcodeType, barcodeData))

测试了一些图片,可以同时解析条码和QR二维码。但是会出现一些漏检的情况。

我需要在C#上实现这个功能,去找了相关的库,而且只能在x86平台上运行,目前还不知道怎么搞在x64上,如果有好心的大佬指点一二就好了。为什么没有深究呢?也是因为我测试之后发现准确率不够,因此就放弃了。

后来在网上调研了一些条码定位的方法,在此基础上我根据自己的需求做了一些修改和优化,目前达到了比较好的效果。下面是用OpenCVSharp实现的源码:

这个算法的前提是条码是水平放置的,不能歪斜。因为我们需要计算图像在X和Y方向上的梯度。条码由于它的特征,在Y方向上的梯度几乎是0,X方向上几乎是1,如图:

因此根据这个性质,我们可以滤掉一些条码外的信息,得到一个比较好的条码二值图。但是在对多种条码类型进行测试时,我发现很多码的中间间隔是很稀疏的,因此采用直接二值化再膨胀腐蚀的方法就不太好,不好调参。中间搁置了几天,有一天突然想着把图像伸缩一下会不会好点,结果确实很有效。

伸缩之后,这种条码区域就已经非常的明显了。接下来是要过滤掉一下其他的信息,由于条码上下通常就会印有对应的字符,有的格式还好,码和字隔得很开,用简单的开运算就可以过滤掉,但是有的就隔得很近,很容易粘连在一起。而且条码中间始终会有空隙,所以效果不好。后来想到再不同方向上先做膨胀腐蚀,就可以很好的填充条码中心,并分开字符和条码了。

这样初步可以得到以下结果:

最后再做一次后处理。我们能看到条码基本上是矩形的,我们可以计算它的轮廓以及最小外接矩,通过计算轮廓面积与最小外接矩的面积比,来判断这个区域是否最接近矩形。

最后就是检测结果啦~在很多图像上试验了表明效果还挺好~ 

 

目前该方法只适用于条码基本水平的情况,我在尝试使用频谱图先检测出文字方向,把图片校正之后再识别的方法,后续继续更新~

如果大佬有更好的方法,希望多多交流哦~

源码请移步:https://github.com/zhanzhanmiao/BarCode-Location-Recognition

  • 3
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值