点击上方“”,选择加"
重磅干货,第一时间送达
在学习中找到快乐,在应用中找到价值。这是我第五期分享图像技术应用的文章。
欢迎前四期阅读分享:
第一期《扫描全能王》
第二期《来吧,看看科技的力量,不用手动找拍贴图》
第三期以这种方式开会ctrl的流量明星cxk,简直就是魔鬼。
第四期《酷炫骚操作,票圈装13神技,极坐标全景图》
在日常生活中,我们经常看到条形码的应用,比如超市购物的生活,图书馆借书的时候。
那么如何准确检测条形码的位置呢?
这就是今天要介绍的。
本文的目标是利用计算机视觉和图像处理技术演示条形码的检测。
对于下面的例子,我们将检测下图中的条形码:
目标:找到条形码的位置,消除干扰因素
思路:
利用
让我们继续写一些代码。打开一个新文件,将其命名为 detect_barcode.py,如何开始写代码:
# 导入必要的包/库 import numpy as np import argparse import imutils import cv2 # 分析结构参数,分析参数 ap = argparse.ArgumentParser() ap.add_argument("-i","--image", required = True, help = "path to the image file") args = vars(ap.parse_args())
我们要做的第一件事就是导入我们需要的包。我们将使用它numpy数字处理,argparse对命令行参数进行分析,cv2进行opencv绑定。
然后我们将设置命令行参数。我们只需要一个开关,即 --image,它是我们图像的路径,包括我们想要检测的条形码。
现在,让我进行实际的图像处理 导入图片并转化为灰度图片
image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 计算图片x和y方向的Scharr梯度大小 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) # 使用x方向的梯度减去y方向的梯度 gradient = cv2.subtract(gradX,gradY) gradient=cv2.convertScaleAbs(gradient)
首先,我们先读图片并将其转换为灰度图;
然后我们用Scharr操作符(此处制定ksize=1)在水平和垂直方向上构建图片的梯度幅度。
在这里,我们用Scharr算子的x方向梯度减去y方向的梯度。通过这种相减操作,我们只剩下高水平梯度和低垂直梯度的图像区域。
上述原始图像的梯度如下图所示
请注意梯度操作是如何检测图片的条形码区域的。下一步是如何过滤图片中的噪并关注条形码区域。
# 模糊和阈值化图片 blurred = cv2.blur(gradient,(9,9)) (_,thresh) = cv2.threshold(blurred, 255, 255, cv2.THRESH_BINARY)
我们做的第一件事就是用9卷积核x9的平均滤波器作用于梯度图片。此操作将有助于平滑图片中的高频噪声。
然后我将模糊的图片阈值化。在梯度图片中,所有像素点的灰度值低于255,其余为255(白色)。
模糊和阈值处理后的输出结果如下:
然而,正如你所看到的,上面的阈值图片在条形码的垂直方向上为了缩小这些间隙,使我们的算法更容易检测条形码的斑点区域,我们需要执行一些基本的形态操作:
# 构造一个闭合核并应用于阈值图片 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
我们使用函数cv2.getStructuringElement构建矩形核。该核的宽度大于高度,因此允许我们缩小条形码垂直条带之间的间隙。
当然,图片中的非条形码区域很多斑点,会干扰轮廓的检测。
现在,我们继续尝试去除这些小斑点
# 执行一系列腐蚀和膨胀操作 closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4)
我们现在要做的是进行四次腐蚀操作,然后进行四次膨胀操作。腐蚀操作会腐蚀图片中的白色像素点,从而去除这些小点,膨胀操作会扩展剩余的白色像素,延长白色区域。
若在腐蚀过程中去除小斑点,则在膨胀过程中不会再次出现。
经过一系列的腐蚀和膨胀操作,这些小斑点已成功去除,只留下条形码。
最后,在图片中找到条形码区域的轮廓。
# 找到阈值化后图片中的轮廓,然后根据区域进行排序,只保留最大区域 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)
幸运的是,opencv它提供了相应的接口,可以很容易地找到图像中最大的轮廓,如果我们正确地完成了图像处理步骤,它应该对应于条形码区域。
然后,我们确定最大轮廓的最小边界框,最后显示检测到的条形码。
如下图所示,我们已成功检测到条形码
详细代码链接:https://github.com/DWCTOD/AI_study/tree/master/合格的CV工程师/实战文章/实战文章/工程师/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文章/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战文/实战opencv/EF%BC%88%E4%BA%94%EF%BC%89%E7%94%A8python%E5%92%8Copencv%E6%A3%80%E6%B5%8B%E5%9B%BE%E5%83%8F%E4%B8%AD%E7%9A%84%E6%9D%A1%E5%BD%A2%E7%A0%81
使用方法:python3 detect_barcode.py --image images/barcode_01.jpg
另外还提供了其他的测试图片
英文原文链接:https://www.pyimagesearch.com/2014/11/24/detecting-barcodes-images-python-opencv/
值得去思考的点
1、为啥要转变成灰度图
2、如何去除干扰因素,特别是条形码下面的材料说明的区域是采用什么办法去除的,小的斑点是如何去除的
在「
在「
在「
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。