LK 博客
利用 YOLO 和 OpenCV 实现车辆计数系统:从原理到实践
项目
约 1 分钟阅读 0 赞 0 条评论 鸿蒙黑体

利用 YOLO 和 OpenCV 实现车辆计数系统:从原理到实践

Dang
党旭 @Dang
累计点赞 0 登录后每个账号只能点一次
内容长度 0 正文词元数
正文
目录会跟随阅读位置移动。
阅读进度

利用 YOLO 和 OpenCV 实现车辆计数系统:从原理到实践

引言

在当今的智能交通管理、停车场监控等场景中,准确地统计车辆数量是一项至关重要的任务。传统的车辆计数方法往往效率低下且容易出错,而计算机视觉技术的发展为我们提供了更高效、准确的解决方案。本文将详细介绍如何结合 YOLO(You Only Look Once)目标检测算法和 OpenCV 库,实现一个简单而实用的车辆计数系统。

技术背景

YOLO 算法

YOLO 是一种快速且高效的目标检测算法,它能够在图像或视频中实时检测出多个目标。YOLO 将目标检测问题转化为一个回归问题,通过一次前向传播就能预测出目标的边界框和类别。不同版本的 YOLO 不断迭代优化,如我们使用的 YOLOv8,具有更快的检测速度和更高的准确率,并且提供了预训练模型,方便我们快速应用到实际项目中。

OpenCV 库

OpenCV 是一个广泛应用于计算机视觉领域的开源库,它提供了丰富的图像处理和计算机视觉算法。在我们的车辆计数系统中,OpenCV 主要用于视频读取、图像预处理、绘制检测结果等操作,是实现整个系统不可或缺的工具。

系统实现步骤

1. 环境准备与模型加载

首先,我们需要安装所需的库,主要包括 ultralyticsopencv-python。可以使用以下命令进行安装:

pip install ultralytics opencv-python

然后加载预训练的 YOLOv8 模型:

from ultralytics import YOLO
model = YOLO('yolov8n.pt')

这里我们选择了 yolov8n.pt 模型,它是 YOLOv8 系列中的轻量级模型,适合在 CPU 或 AMD 核显上运行,速度较快。

2. 视频读取与处理

使用 OpenCV 打开视频文件,并逐帧进行处理:

import cv2
cap = cv2.VideoCapture("car two.mp4")
if not cap.isOpened():
    print("错误:无法打开视频文件,请检查路径!")
    exit()

3. 鼠标交互功能

为了实现用户自定义检测区域,我们添加了鼠标交互功能,允许用户通过鼠标绘制多边形区域,只对该区域内的车辆进行计数。以下是相关代码:

# 鼠标画圈相关全局变量
drawing = False
current_line = []
polygons = []

# 鼠标回调函数:画闭合多边形(仅边框,不填充)
def draw_callback(event, x, y, flags, param):
    global drawing, current_line
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        current_line = [(x, y)]
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            current_line.append((x, y))
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if len(current_line) > 2:
            polygons.append(current_line.copy())
        current_line = []

# 判断点是否在任意多边形内(用于只统计圈内车辆)
def is_point_in_polygon(point):
    if not polygons:
        return True  # 未画圈时,默认统计所有车辆
    for poly in polygons:
        pts = np.array(poly, np.int32)
        if cv2.pointPolygonTest(pts, point, False) >= 0:
            return True
    return False

cv2.namedWindow("YOLOv8 车辆计数", cv2.WINDOW_NORMAL)
cv2.resizeWindow("YOLOv8 车辆计数", 960, 540)
cv2.setMouseCallback("YOLOv8 车辆计数", draw_callback)

4. 目标检测与车辆计数

在主循环中,我们对每一帧视频进行处理,使用 YOLOv8 模型进行车辆检测,并根据条件进行车辆计数:

car_count = 0
counted_box_ids = set()  # 存储已计数车辆的唯一ID

while True:
    ret, frame = cap.read()
    if not ret:
        break  # 视频播放完毕,退出循环

    # YOLOv8 推理(仅检测车辆类:2=汽车,5=巴士,7=卡车)
    results = model(frame, classes=[2, 5, 7], conf=0.3, verbose=False)

    for r in results:
        boxes = r.boxes
        for box in boxes:
            # 获取检测框坐标
            x1, y1, x2, y2 = map(int, box.xyxy[0])
            w, h = x2 - x1, y2 - y1
            # 过滤过小的检测框(避免误检)
            if w < MIN_W or h < MIN_H:
                continue
            # 计算检测框中心点
            center_x = (x1 + x2) // 2
            center_y = (y1 + y2) // 2
            center_point = (center_x, center_y)
            # 检查中心点是否在多边形内
            if not is_point_in_polygon(center_point):
                continue
            # 绘制检测框和中心点
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
            cv2.circle(frame, center_point, 5, (0, 0, 255), -1)
            # 检查中心点是否通过检测线
            if abs(center_y - LINE_Y) <= OFFSET and box.id not in counted_box_ids:
                car_count += 1
                counted_box_ids.add(box.id)
    # 绘制检测线
    cv2.line(frame, (0, LINE_Y), (frame.shape[1], LINE_Y), (255, 0, 0), 2)
    # 显示车辆计数
    cv2.putText(frame, f"Car Count: {car_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    # 绘制多边形
    for poly in polygons:
        pts = np.array(poly, np.int32).reshape((-1, 1, 2))
        cv2.polylines(frame, [pts], True, (255, 255, 0), 2)
    # 显示结果
    cv2.imshow("YOLOv8 车辆计数", frame)
    # 按 'q' 键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

代码解释

  • 模型推理model(frame, classes=[2, 5, 7], conf=0.3, verbose=False) 对当前帧进行推理,只检测汽车(类别 2)、巴士(类别 5)和卡车(类别 7),置信度阈值设为 0.3。
  • 过滤小目标:通过设定 MIN_WMIN_H 过滤掉过小的检测框,避免误检。
  • 中心点计算:计算检测框的中心点,用于判断车辆是否通过检测线。
  • 多边形区域判断:使用 is_point_in_polygon 函数判断车辆中心点是否在用户绘制的多边形区域内。
  • 车辆计数:当车辆中心点通过检测线且未被计数时,车辆计数加 1。

总结

通过结合 YOLO 和 OpenCV,我们成功实现了一个简单的车辆计数系统。该系统不仅可以准确地统计车辆数量,还允许用户自定义检测区域,增加了系统的灵活性和实用性。较上一篇只利用OpenCV进行车辆检测,这里引用YOLOv8模型,更加精确与方便。

在未来,我们可以进一步优化该系统,例如:

  • 提高检测的准确性,通过调整模型参数或使用更强大的预训练模型。
  • 增加更多的功能,如车辆速度检测、车型分类等。
  • 实现多摄像头的车辆计数,扩大监控范围。

通过行车检测项目,已经完成了对OpenCV的基本学习,下一步将对模型训练与算法进行学习。

作者名片

Dang
党旭
@Dang

这个作者暂时还没有填写个人简介。

评论区
文章作者和管理员都可以管理这里的评论。
0 条评论
登录后即可参与评论。 去登录
还没有评论,欢迎留下第一条交流内容。