ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

使用Python和OpenCV检测图像中的条形码

2020-12-04 18:32:57  阅读:389  来源: 互联网

标签:条形码 阈值 Python 梯度 image cv2 OpenCV 图像


使用Python和OpenCV检测图像中的条形码

这篇博客将介绍使用计算机视觉和图像处理技术进行条形码检测的必要步骤,并演示使用Python编程语言和OpenCV库实现检测算法及其检测效果。

1. 效果图

原图
在这里插入图片描述
灰度图 VS 梯度渐变图
x梯度减y梯度,梯度渐变获取定位条形码大致区域;
在这里插入图片描述高斯模糊图 VS 阈值化图
高斯模糊去掉高频噪音的干扰;
阈值化图使得图像的黑白区域更加明显。阈值的值的设置很重要。该方法应用的是大于225的直接为255白色,不大于255的为0,黑色
在这里插入图片描述闭合核图 VS 腐蚀膨胀图
闭合核作用:使得条形码之间的细线差距更小;
腐蚀膨胀:去掉条形码周围的小斑点的干扰,要么消亡,要么生长成为条形码区域;
在这里插入图片描述最终效果图:
在这里插入图片描述

2. 算法的步骤

该算法的步骤是:

  1. 计算x和y方向上的Scharr梯度幅度表示。
  2. 从x梯度中减去y梯度以显示条形码区域。
  3. 模糊和阈值图像。
  4. 将封闭内核应用于阈值图像。
  5. 执行一系列的膨胀和腐蚀。
  6. 找到图像中最大的轮廓,就是条形码。

该算法并不适用于所有条形码。注意,由于此方法对图像的渐变表示进行了假设,因此仅适用于水平条形码。

优化:
如果要实施更强大的条形码检测算法,则需要考虑图像的方向,或者更好的方法是应用机器学习技术(例如Haar级联或HOG +线性SVM)“扫描”图像以进行条形码区域扫描。

3. 源码

# USAGE
# python detect_barcode.py --image images/barcode_02.jpg

import argparse

import cv2
import imutils
# 导入必要的包
import numpy as np

# 构建命令行参数及解析
# --image 包含条形码的输入图像路径
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
                help="path to the image file")
args = vars(ap.parse_args())

# 加载图像,转换为灰度图
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("origin", image)
cv2.waitKey(0)

# 使用Scharr运算符(指定ksize = -1)构造水平和垂直方向上灰度图像的梯度幅度表示。
ddepth = cv2.cv.CV_32F if imutils.is_cv2() else cv2.CV_32F
gradX = cv2.Sobel(gray, ddepth=ddepth, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=ddepth, dx=0, dy=1, ksize=-1)

# 用Scharr运算符的x梯度中减去Scharr运算符的y梯度,剩下的图像区域具有较高的水平梯度和较低的垂直梯度。
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
cv2.imshow("gray VS gradient", np.hstack([gray, gradient]))
cv2.waitKey(0)

# 以上可得到条码图像的梯度表示
# 请注意,渐变操作是如何检测图像的条形码区域的。下一步将滤除图像中的噪点,并仅关注条形码区域。
# 高斯平滑以及阈值化图像
# 使用9 x 9内核将平均模糊应用于渐变图像,用以消除图像梯度表示的高频噪声。
blurred = cv2.blur(gradient, (9, 9))
# 对模糊图像进行阈值处理。渐变图像中任何不大于225的像素都将设为0(黑色)。否则,像素设置为255(白色)。
(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
cv2.imshow("blurred VS thresh", np.hstack([blurred, thresh]))
cv2.waitKey(0)

# 条形码的竖线之间存在间隙。为了弥合这些差距,并使算法更容易检测条形码的“斑点”状区域,我们需要执行一些基本的形态学操作:
# 构造一个闭合核并将其应用于阈值图像
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# 执行完成后,缝隙实际上更加封闭:
# 图像中出现了小的斑点,这些斑点不是实际条形码的一部分,但可能会干扰轮廓检测。
# 继续尝试删除这些小斑点:
# 执行4次腐蚀迭代,然后进行4次膨胀迭代。腐蚀将“侵蚀”图像中的白色像素,从而消除小斑点,而膨胀将“膨胀”剩余的白色像素并使白色区域重新生长。
eroded = cv2.erode(closed, None, iterations=4)
dilated = cv2.dilate(eroded, None, iterations=4)
cv2.imshow("closede VS eroded and dilated", np.hstack([closed, dilated]))
cv2.waitKey(0)

# 只要在侵蚀过程中去除了小斑点,它们就不会在扩张过程中重新出现。
# 经过一系列侵蚀和膨胀后,可以看到小斑点已被成功去除,并且剩下条形码区域:

# 在阈值化的图像中寻找轮廓,轮廓面积排序,只保留最大的一个
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,
                        cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]

# 确定最大轮廓的最小边界框
rect = cv2.minAreaRect(c)
box = cv2.cv.BoxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect)
box = np.int0(box)

# 在检测到的条形码上绘制边界框,并显示图像
cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
cv2.imshow("Image", image)
cv2.waitKey(0)

参考

标签:条形码,阈值,Python,梯度,image,cv2,OpenCV,图像
来源: https://blog.csdn.net/qq_40985985/article/details/110632145

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有