ICode9

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

使用Python,OpenCV在视频中进行实时条形码检测

2021-01-05 12:30:04  阅读:188  来源: 互联网

标签:条形码 Python 检测 frame cv2 OpenCV video 图像


使用Python,OpenCV在视频中进行实时条形码检测

上一篇博客介绍了如何检测和查找图像中的条形码。这篇博客将进行一些优化以检测实时视频中的条形码。

1. 步骤

  • 图像/视频帧中进行条形码检测
  • 驱动程序以访问视频流,并调用条形码检测程序

计算x梯度与y梯度的差值(由于是x减y的,故只能检测横向的条形码,算法并不通用)

2. 适用场景及优化

适用场景:

  1. 静态摄像头,以90度角“向下”看条形码。这将确保程序可以找到条形码图像的梯度区域。
  2. 视频带有条形码的正视角的特写,即智能手机直接放在条形码的上方,而不是将条形码远离镜头。将条形码移离相机的距离越远,简单条形码检测器的成功就越少。

该方法并不适用于所有的条形码检测,仅在最佳条件下有效,并且是横向条形码;
当条形码离相机太远,图像中有太多的“干扰”和“噪音”时,都不会奏效。

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

3. 总结

这篇博客拓展了上一篇检测图像中的条形码,主要分为俩部分:

  • 用于检测视频各个帧中的条形码的方法;
  • “驱动程序”,用于访问摄像机或视频文件的方法;

当将其应用于检测视频中的条形码时,并不通用。仅在:

  • 有一个静态相机视图,它以90度角在条形码上“向下看”。
  • 拥有较清晰的,近的条形码的“特写”视图,并且框架视图中没有其他干扰对象或噪声。
    下效果比较好。
    优化可以通过使用机器学习来训练更强壮的条形码检测器。

4. 源码

# USAGE
# python detect_real_barcode.py --video video/video_games.mov
# python detect_real_barcode.py

# 导入必要的包
import argparse
import time

import cv2
import imutils
import numpy as np
from imutils.video import VideoStream


# 检测图像中的条形码
def detect(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梯度的差值(由于是x减y的,故只能检测横向的条形码,算法并不通用),获取到条形码的大致范围
    gradient = cv2.subtract(gradX, gradY)
    gradient = cv2.convertScaleAbs(gradient)

    # 高斯平滑(去掉高频噪音干扰) 阈值化图像(是的图像的黑白区域更加明显,阈值的设置很重要)
    blurred = cv2.blur(gradient, (9, 9))
    (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)

    # 构建一个闭合内核应用在阈值化的图像上,使得条形码之间的细线空隙更小;
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

    # 构建一系列腐蚀、膨胀操作(去掉条形码周围的小斑点的干扰,要么消亡,要么生长成为条形码区域;)
    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)

    # 如果没有轮廓,返回None,认为图像中不存在条形码
    if len(cnts) == 0:
        return None

    # 否则,根据外接圆面积排序,留下最大的轮廓认为是条形码区域
    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)

    # 返回条形码区域的边界框
    return box


# 构建命令行参数及解析
# --video,视频文件的路径
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="path to the (optional) video file")
args = vars(ap.parse_args())

# 如果提供了视频文件,则读取视频文件
if not args.get("video", False):
    vs = VideoStream(src=0).start()
    time.sleep(2.0)
# 否则,加载电脑自带的摄像头
else:
    vs = cv2.VideoCapture(args["video"])

# 循环遍历帧
while True:
    # 获取当前帧
    # 如果是从视频中VideoStram获取则直接获取当前帧,否则,当前视频流VideoCapture中捕获下一帧
    frame = vs.read()
    frame = frame[1] if args.get("video", False) else frame

    # 检测是否到了视频尾部
    if frame is None:
        break

    # 检测视频帧的条形码
    box = detect(frame)

    # 如果检测到了条形码,在其上绘制绿色框
    if box is not None:
        cv2.drawContours(frame, [box], -1, (0, 255, 0), 2)

    # 展示帧,并记录用户是否有按键
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    # 按下‘q’键,结束循环
    if key == ord("q"):
        break

# 清除视频流对象的指针
# 如果未使用视频文件,停止视频文件流
if not args.get("video", False):
    vs.stop()
# 否则,释放摄像头指针
else:
    vs.release()

# 关闭所有展示的窗口
cv2.destroyAllWindows()

参考

标签:条形码,Python,检测,frame,cv2,OpenCV,video,图像
来源: https://blog.csdn.net/qq_40985985/article/details/110817080

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

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

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

ICode9版权所有