news 2026/4/3 4:17:07

基于YOLOv8的车辆过线计数与检测区域设置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于YOLOv8的车辆过线计数与检测区域设置

基于YOLOv8的车辆过线计数与检测区域设置

在城市交通管理、智能安防和车流监控等实际场景中,对道路上行驶车辆进行自动统计是一项基础但关键的任务。传统的人工计数方式效率低、成本高,而基于视频分析的自动化方案正成为主流。最近我尝试使用 YOLOv8 搭配目标追踪算法实现一个轻量级、可复现的车辆过线计数系统,整个过程无需复杂环境配置,也不依赖收费框架,所有代码均可本地运行。

项目基于 Ultralytics 官方提供的YOLO-V8 Docker 镜像,该镜像已预装 PyTorch 2.2.1 + CUDA 12.1 + Ultralytics 库,支持 Ubuntu 20.04/22.04 系统,开箱即用。如果你已有满足python>=3.8torch>=2.2.1的环境,也可以跳过容器部署直接进入开发阶段。


快速启动:两种接入方式

使用 Jupyter Lab 进行交互式开发

容器启动后,默认会开启 Jupyter Lab 服务(端口 8888),通过浏览器访问:

http://<your-server-ip>:8888

首次登录需输入 token(可在容器日志中查看),后续建议设置密码以方便长期使用。

进入/root/ultralytics目录即可开始编码:

from ultralytics import YOLO # 加载COCO预训练模型 model = YOLO("yolov8n.pt") # 查看模型结构(可选) model.info() # 对图片推理 results = model("path/to/car.jpg") results[0].show() # 显示带框结果图

你还可以上传自己的测试视频如car.mp4,用于后续功能验证。

这种方式适合快速原型验证和教学演示,尤其适合初学者上手。


使用 SSH 登录进行深度定制

若需要修改源码或调试底层逻辑,推荐使用 SSH 登录容器内部:

ssh root@<your-server-ip> -p 2222

默认用户名为root,密码根据初始化脚本设定。

登录成功后进入项目目录:

cd /root/ultralytics

此时可以自由编辑.py文件、运行命令行脚本或集成第三方工具,灵活性更高。

对于需要自定义检测流程、扩展绘图功能或集成业务系统的开发者来说,这是更合适的开发模式。


初步验证:YOLOv8 推理能力测试

在正式开发前,先确认基础检测功能是否正常工作。

图片检测示例

from ultralytics import YOLO model = YOLO("yolov8n.pt") results = model("path/to/car.jpg") results[0].save("output_car.jpg") # 保存标注后的图像

视频实时检测

results = model.predict( source="car.mp4", show=True, # 实时显示窗口 save=True, # 保存输出视频 conf=0.5, # 置信度阈值 classes=[2], # 只检测 car 类别(COCO中ID=2) )

输出视频将自动保存至runs/detect/predict/路径下。这一步不仅能验证模型可用性,也能帮助我们观察原始画面中的车辆分布情况,为后续设置检测区域提供参考。


设置固定检测区域(ROI)

为了提升检测准确率并减少边缘干扰(例如行人、背景晃动),我们应限定一个感兴趣区域(Region of Interest, ROI),仅在此范围内执行目标检测。

修改预处理函数以应用遮罩

文件路径:ultralytics/engine/predictor.py

我们在preprocess方法中添加图像遮罩逻辑:

import cv2 import numpy as np def preprocess(self, im): """ 在原始图像上应用ROI遮罩后再送入模型。 Args: im (list[np.ndarray]): 输入图像列表 [(H, W, C)]。 """ # 定义ROI坐标(左上x, y;右下x, y) left, upper, right, lower = 0, 165, 640, 265 # 根据实际视频调整 masked_images = [] for image in im: height, width = image.shape[:2] mask = np.zeros((height, width), dtype=np.uint8) cv2.rectangle(mask, (left, upper), (right, lower), 255, thickness=-1) masked_image = cv2.bitwise_and(image, image, mask=mask) cv2.rectangle(image, (left, upper), (right, lower), (0, 255, 0), 2) # 绘制绿色边框 masked_images.append(masked_image) not_tensor = not isinstance(masked_images, torch.Tensor) if not_tensor: masked_images = np.stack(self.pre_transform(masked_images)) masked_images = masked_images[..., ::-1].transpose((0, 3, 1, 2)) # HWC -> CHW masked_images = np.ascontiguousarray(masked_images) masked_images = torch.from_numpy(masked_images) masked_images = masked_images.to(self.device) masked_images = masked_images.half() if self.model.fp16 else masked_images.float() if not_tensor: masked_images /= 255.0 return masked_images

📌说明
- 使用 OpenCV 创建矩形掩膜,非 ROI 区域像素被清零;
- 原图上绘制绿色矩形便于可视化检测范围;
- 所有后续推理均只关注该区域内目标,有效降低误检率。


添加中间计数线与状态显示

要在检测区域内判断车辆是否“过线”,我们需要画一条水平线作为基准,并在画面上动态显示统计数据。

参数传递机制设计

(1)在track.py中添加命令行参数
parser.add_argument('--hidecls', action='store_true', help='不显示类别标签') parser.add_argument('--draw-line', action='store_true', help='绘制中间计数线')
(2)在BasePredictor.__init__中接收参数
self.hidecls = args.hidecls self.whereline = None # 存储计数线起点和终点 self.numlabel = "count: 0" # 显示文本
(3)在preprocess中设置计数线位置
# 计数线位于ROI垂直中点 self.whereline = [ (0, int(upper + (lower - upper) / 2)), (width, int(upper + (lower - upper) / 2)) ]

扩展绘图工具类 Annotator

文件路径:ultralytics/utils/plotting.py

Annotator类添加两个辅助方法:

def draw_line(self, pt1, pt2, color=(0, 255, 255), thickness=4): """绘制黄色计数线""" cv2.line(self.im, pt1, pt2, color=color, thickness=thickness) def put_text(self, text, pos, scale=1.5, color=(0, 0, 255), thickness=3): """在指定位置写文本""" cv2.putText(self.im, text, pos, cv2.FONT_HERSHEY_SIMPLEX, scale, color, thickness)

修改Results.plot()方法以支持新参数

文件路径:ultralytics/engine/results.py

更新plot()方法签名并加入绘图逻辑:

def plot( self, ... whereline=None, numlabel=None, hidecls=False, **kwargs ): annotator = Annotator(...) if pred_boxes and show_boxes: for d in reversed(pred_boxes): c, conf = int(d.cls), float(d.conf) name = names[c] if not hidecls else "" label = f"{name} {conf:.2f}" if conf and not hidecls else name annotator.box_label(d.xyxy.squeeze(), label, color=colors(c, True)) # 绘制中心点用于轨迹追踪 xywh = d.xywh.int().cpu().tolist()[0] midpoint = (int(xywh[0]), int(xywh[1])) cv2.circle(annotator.im, midpoint, radius=5, color=(0, 0, 0), thickness=-1) # 绘制计数线 if whereline is not None: annotator.draw_line(whereline[0], whereline[1]) # 显示统计信息 if numlabel is not None: annotator.put_text(numlabel, (50, 50)) return annotator.result()

实现车辆过线计数逻辑

核心思路是:利用目标追踪 ID 和 bbox 中心点的历史轨迹,判断其运动路径是否穿越计数线,并结合移动方向区分“上行”与“下行”。

添加辅助函数至BasePredictor

import math from collections import deque, defaultdict def tlbr_midpoint(self, box): """计算边界框中心点""" minX, minY, maxX, maxY = box return (int((minX + maxX) / 2), int((minY + maxY) / 2)) def ccw(self, A, B, C): """判断三点是否逆时针排列""" return (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0]) def intersect(self, A, B, C, D): """判断线段AB与CD是否相交""" return self.ccw(A, C, D) != self.ccw(B, C, D) and self.ccw(A, B, C) != self.ccw(A, B, D) def vector_angle(self, curr_pt, prev_pt): """计算移动向量的角度(相对于x轴)""" dx = curr_pt[0] - prev_pt[0] dy = curr_pt[1] - prev_pt[1] return math.degrees(math.atan2(dy, dx))

stream_inference中集成计数逻辑

在主循环开始前初始化全局变量:

# 初始化路径缓存与计数器 self.paths = defaultdict(lambda: deque(maxlen=2)) self.up_count = 0 self.down_count = 0

然后在每帧处理中加入判断逻辑:

for i in range(n): self.seen += 1 p, im0 = path[i], im0s[i].copy() det = self.results[i].boxes.data.cpu().numpy() if len(det) == 0: continue for *xyxy, conf, cls_id, track_id in det: track_id = int(track_id) cls_id = int(cls_id) if cls_id != 2: # 仅统计 car continue midpoint = self.tlbr_midpoint(xyxy) if track_id not in self.paths: self.paths[track_id].append(midpoint) self.paths[track_id].append(midpoint) else: self.paths[track_id].append(midpoint) if len(self.paths[track_id]) < 2: continue prev_point = self.paths[track_id][-2] curr_point = self.paths[track_id][-1] line_start, line_end = self.whereline # 判断是否穿越计数线 if self.intersect(prev_point, curr_point, line_start, line_end): angle = self.vector_angle(curr_point, prev_point) if angle > 0 and abs(angle) > 30: # 向右上方 → 上行 self.up_count += 1 elif angle < 0 and abs(angle) > 30: # 向右下方 → 下行 self.down_count += 1 # 更新显示文本 total = self.up_count + self.down_count self.numlabel = f"Total: {total} | Up: {self.up_count} | Down: {self.down_count}"

确保绘图参数正确传入

write_results或主流程中调用plot时传参:

plot_args = { 'hidecls': self.args.hidecls, 'whereline': self.whereline, 'numlabel': self.numlabel, } self.plotted_img = result.plot(**plot_args)

这样就能实现实时渲染计数线与统计信息。


完整调用命令示例

python track.py \ --source car.mp4 \ --yolo-model yolov8n.pt \ --tracking-method bytetrack \ --classes 2 \ --hidecls \ --draw-line \ --save \ --device 0

📌 参数说明:
---classes 2:仅检测车辆(COCO 数据集中 car 类别 ID 为 2);
---hidecls:隐藏类别标签,使画面更简洁;
---draw-line:启用计数线与数据展示;
---tracking-method bytetrack:使用 ByteTrack 提升追踪稳定性,避免 ID 切换导致重复计数。


效果展示与优化方向

最终输出视频包含以下元素:
- ✅ 绿色矩形框标出检测区域(ROI);
- ✅ 黄色横线作为计数基准线;
- ✅ 左上角实时显示总数量及上下行统计;
- ✅ 每辆车中心有黑色圆点辅助轨迹观察。

🎯进一步优化建议
1.多区域支持:扩展为多个 ROI + 多条计数线,适用于十字路口或多车道场景;
2.分类计数:分别统计 car/truck/bus 等不同类型车辆;
3.流量报警机制:当单位时间车流量超过阈值时触发告警;
4.Web 可视化平台:结合 Flask/FastAPI 构建前端监控界面,支持远程查看与历史回放;
5.性能调优:改用yolov8syolov8m提升小目标检测精度,或使用 TensorRT 加速推理。


这种基于 YOLOv8 和几何判断的轻量级解决方案,不仅实现了稳定可靠的车辆过线计数,还具备良好的可移植性和扩展性。整个流程依托官方 Docker 镜像,避免了繁琐的环境配置,特别适合科研验证、教学演示以及中小型项目落地。随着边缘计算设备(如 Jetson、瑞芯微)的普及,这类方案将在智慧城市、园区管理和交通疏导中发挥更大价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/28 10:51:09

Octavia实现HTTPS健康检查的SNI与证书问题解析

Octavia实现HTTPS健康检查的SNI与证书问题解析 在现代云原生架构中&#xff0c;负载均衡器不仅是流量分发的核心组件&#xff0c;更是保障服务高可用的关键环节。OpenStack Octavia 作为社区推荐的标准负载均衡服务&#xff0c;基于 HAProxy 实现了从 L4 到 L7 的完整代理能力。…

作者头像 李华
网站建设 2026/3/27 18:39:54

检验vtk版本

一&#xff1a;主要的知识点 1、说明 本文只是教程内容的一小段&#xff0c;因博客字数限制&#xff0c;故进行拆分。主教程链接&#xff1a;vtk教程——逐行解析官网所有Python示例-CSDN博客 2、知识点纪要 本段代码主要涉及的有①检查vtk版本 二&#xff1a;代码及注释 …

作者头像 李华
网站建设 2026/3/31 10:49:13

TensorFlow与PyTorch中提取图像patch的方法解析

TensorFlow与PyTorch中提取图像patch的方法解析 在深度学习的计算机视觉任务中&#xff0c;从图像或特征图中提取局部邻域块&#xff08;即“patch”&#xff09;是一项看似基础却极为关键的操作。无论是自监督学习中的对比学习&#xff08;如SimCLR、MoCo&#xff09;&#xf…

作者头像 李华
网站建设 2026/3/29 5:51:15

揭秘Open-AutoGLM与国外顶尖模型的5大核心差距:你不可不知的技术真相

第一章&#xff1a;Open-AutoGLM与国外顶尖模型对比的背景与意义 在人工智能技术迅猛发展的当下&#xff0c;大语言模型已成为推动自然语言处理进步的核心动力。Open-AutoGLM作为国内自主研发的高性能语言模型&#xff0c;其设计理念聚焦于自动化推理与任务适配能力&#xff0c…

作者头像 李华
网站建设 2026/3/30 5:50:13

基于多目标遗传算法的分布式电源选址定容:MATLAB 代码探秘

MATLAB代码&#xff1a;基于多目标遗传算法的分布式电源选址定容研究 关键词&#xff1a;分布式电源 选址定容 多目标遗传算法 参考文档&#xff1a;《店主自写文档》基本复现&#xff1b; 仿真平台&#xff1a;MATLAB 主要内容&#xff1a;代码主要做的是基于多目标遗传算…

作者头像 李华
网站建设 2026/3/29 8:02:12

智普AutoGLM究竟强在哪?:3大核心技术解析带你全面看懂

第一章&#xff1a;智普Open-AutoGLM沉思在人工智能与自动化深度融合的当下&#xff0c;智普推出的 Open-AutoGLM 项目为开发者提供了一个开放、可扩展的自动代码生成框架。该工具基于 GLM 大语言模型&#xff0c;聚焦于理解自然语言指令并将其转化为高质量代码片段&#xff0c…

作者头像 李华