前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战 | 基于YOLOv8和OpenCV实现目标检测、跟踪与计数(步骤+源码)

实战 | 基于YOLOv8和OpenCV实现目标检测、跟踪与计数(步骤+源码)

作者头像
Color Space
发布2024-07-25 18:39:51
590
发布2024-07-25 18:39:51
举报
文章被收录于专栏:OpenCV与AI深度学习

视觉/图像重磅干货,第一时间送达!

介绍

目标检测:识别并定位图像或视频中的物体,用边界框指定它们的位置。YOLO(You Only Look Once)是一种流行的单阶段物体检测算法,以其速度和准确性而闻名。与两阶段检测器不同,YOLO 一次性处理整个图像,使实时检测成为可能。这种方法通过提供高效可靠的物体检测功能,彻底改变了自动驾驶、监控和机器人等应用。

目标跟踪:在视频的多个帧中跟踪已识别的对象。SORT(简单在线实时跟踪)算法被广泛用于此目的,因为它通过预测对象的运动并实时更新其位置来有效地跟踪对象。结合使用 YOLO 进行检测和 SORT 进行跟踪可以持续监控和分析对象,确保在整个视频序列中进行准确且一致的跟踪。

实现步骤

我们将使用 YOLOv8m、OpenCV 和 SORT 进行对象检测来计算通过视频中特定区域的汽车数量,以确保准确性和效率。

1. 选择视频

2. 创建掩码

我们只想识别桥下的汽车。为此,我们将使用画布创建一个蒙版。蒙版通常是二进制图像,其中像素为黑色 (0) 或白色 (255)。在 RGB 图像中,这意味着蒙版仅使用两个值:

白色(255, 255, 255)表示感兴趣的区域,算法将在此进行处理。

黑色(0, 0, 0)表示要忽略或排除在处理之外的区域。

使用按位运算将掩码与视频结合起来,我们得到以下结果:

3. 定义区域

我们将在视频中定义两个区域:一个区域用于计数下行的汽车数量,另一个区域用于计数上行的汽车数量。

当在指定区域内识别出汽车时,我们会将该区域的颜色更改为绿色,表示检测到。

4. 构建布局

让我们使用 cvzone 构建计数器的布局。

5. 编写代码

  • cv2:执行图像和视频处理
  • cvzone:与 OpenCV 协同工作
  • numpy:处理数值运算
  • YOLO:应用物体检测
  • sort:用于跟踪检测到的对象(SORT)库。

代码语言:javascript
复制
import cv2
import numpy as np
from ultralytics import YOLO
import cvzone
from sort import sort

class_names = [
  'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 
  'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 
  'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 
  'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 
  'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 
  'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'
]

class_names_goal = ['car']

model = YOLO('yolov8m.pt')
tracker = sort.Sort(max_age=20) 

mask = cv2.imread('mask.png') 

video = cv2.VideoCapture('traffic.mp4')

width = 1280
height = 720

line_left_road_x1 = 256
line_left_road_x2 = 500
line_left_road_y = 472

line_right_road_x1 = 672
line_right_road_x2 = 904
line_right_road_y = 472

vehicle_left_road_id_count = []
vehicle_right_road_id_count = []

while True:
  success, frame = video.read()

  if not success:
    break

  frame = cv2.resize(frame, (width, height))

  image_region = cv2.bitwise_and(frame, mask) 

  results = model(image_region, stream=True) 

  detections = []
  
  cv2.line(frame, (line_left_road_x1, line_left_road_y) ,(line_left_road_x2, line_left_road_y), (0, 0, 255))
  cv2.line(frame, (line_right_road_x1, line_right_road_y) ,(line_right_road_x2, line_right_road_y), (0, 0, 255))

  for result in results:
    for box in result.boxes:
      class_name = class_names[int(box.cls[0])]

      if not class_name in class_names_goal:
        continue

      confidence = round(float(box.conf[0]) * 100, 2)

      if confidence < 30:
        continue

      x1, y1, x2, y2 = box.xyxy[0]
      x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)

      detections.append([x1, y1, x2, y2, float(box.conf[0])])

    tracked_objects = tracker.update(np.array(detections))

    for obj in tracked_objects:
      x1, y1, x2, y2, obj_id = [int(i) for i in obj]

      confidence_pos_x1 = max(0, x1)
      confidence_pos_y1 = max(36, y1)

      cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 255), 2)
      cvzone.putTextRect(frame, f'ID: {obj_id}', (confidence_pos_x1, confidence_pos_y1), 1, 1)

      center_x = (x1 + x2) // 2
      center_y = (y1 + y2) // 2

      if  line_left_road_y - 10 < center_y < line_left_road_y + 10 and line_left_road_x1 < center_x < line_left_road_x2:
        if not obj_id in vehicle_left_road_id_count:
          vehicle_left_road_id_count.append(obj_id)

          cv2.line(frame, (line_left_road_x1, line_left_road_y) ,(line_left_road_x2, line_left_road_y), (0, 255, 0), 2)

      if  line_right_road_y - 10 < center_y < line_right_road_y + 10 and line_right_road_x1 < center_x < line_right_road_x2:
        if not obj_id in vehicle_right_road_id_count:
          vehicle_right_road_id_count.append(obj_id)

          cv2.line(frame, (line_right_road_x1, line_right_road_y) ,(line_right_road_x2, line_right_road_y), (0, 255, 0), 2)

  cvzone.putTextRect(frame, f'Car Left Road Count: {len(vehicle_left_road_id_count)}', (50, 50), 2, 2, offset=20, border=2, colorR=(140, 57, 31), colorB=(140, 57, 31))
  cvzone.putTextRect(frame, f'Car Right Road Count: {len(vehicle_right_road_id_count)}', (width - 460, 50), 2, 2, offset=20, border=2, colorR=(140, 57, 31), colorB=(140, 57, 31))

  cv2.imshow('Image', frame)

  if cv2.waitKey(1) & 0xFF == ord('q'):
    break

video.release()
cv2.destroyAllWindows()

6. 运行结果

完整代码与视频素材下载:

代码语言:javascript
复制
https://github.com/VladeMelo/car-counter
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV与AI深度学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
媒体处理
媒体处理(Media Processing Service,MPS)是一种云端音视频处理服务。基于腾讯多年音视频领域的深耕,为您提供极致的编码能力,大幅节约存储及带宽成本、实现全平台播放,同时提供视频截图、音视频增强、内容理解、内容审核等能力,满足您在各种场景下对视频的处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档