You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV与YOLOv3的无人机航拍车辆检测追踪问题求助

无人机航拍视频YOLOv3车辆检测问题排查与优化方案

问题背景

我尝试使用YOLOv3结合OpenCV对无人机航拍视频进行车辆检测与追踪,目标是实现:

  • 区分轿车和卡车
  • 返回车辆总数
  • 重点追踪车辆进出视频帧的位置

视频帧示例:
无人机航拍视频帧

运行以下代码时所有检测结果的置信度均为0.00,尝试过包括mAP较高的YOLOv3-spp在内的多个预训练模型,均无匹配结果:

import cv2
import numpy as np

# Load Yolo 
net = cv2.dnn.readNet("yolov3-spp.weights", "yolov3-spp.cfg")

# Get the names of all the layers in the network
layer_names = net.getLayerNames()

# Get the indices of the output layers, i.e. the layers with unconnected outputs
output_layer_indices = net.getUnconnectedOutLayers()


# Get the names of the output layers using the indices

output_layers = []
for i in output_layer_indices:
  output_layers.append(layer_names[i-1])

# Open the video file
cap = cv2.VideoCapture("small-mud.mp4")

# Get the video writer initialized to save the output video
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('outpy.mp4',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))

print(f"Frame dimensions are {frame_width} by {frame_height} px");
print(f"OUT IS: {type(out)}")

while(cap.isOpened()):
    ret, img = cap.read()
    if not ret:
        break

    height, width, channels = img.shape

    # Detecting objects
    blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
    
    #print("Detecting...")
    net.setInput(blob)
    outs = net.forward(output_layers)

    # Showing informations on the screen
    class_ids = []
    confidences = []
    boxes = []
    for inp in outs:
        for detection in inp:
            #print("INNER LOOP...")
            scores = detection[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            #print(confidence) #0.0
            if confidence > 0.5:
                # Object detected
                print("OBJECT DETECTED!")
                center_x = int(detection[0] * width)
                center_y = int(detection[1] * height)
                w = int(detection[2] * width)
                h = int(detection[3] * height)

                # Rectangle coordinates
                x = int(center_x - w / 2)
                y = int(center_y - h / 2)

                boxes.append([x, y, w, h])
                confidences.append(float(confidence))
                class_ids.append(class_id)
    
    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)

    font = cv2.FONT_HERSHEY_PLAIN
    for i in range(len(boxes)):
        if i in indexes:
            x, y, w, h = boxes[i]
            label = str(classes[class_ids[i]])
            color = colors[i]
            cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
            cv2.putText(img, label, (x, y + 30), font, 3, color, 2)

    # Write the frame into the output file
    out.write(img)

cap.release()
out.release()
cv2.destroyAllWindows()

一、置信度为0的核心排查步骤

1. 验证模型文件完整性

  • 确保yolov3-spp.weights和yolov3-spp.cfg文件完整且版本匹配,建议从官方渠道重新下载对应预训练权重与配置文件。
  • 检查代码中模型路径是否正确,避免相对路径错误导致加载无效模型。

2. 补充代码缺失的关键变量

代码中未定义classes和colors变量,这会导致标注环节报错,同时需确认COCO类别包含目标(轿车car、卡车truck均在COCO类别中)。添加以下代码到模型加载后:

# 加载COCO类别名称
classes = []
with open("coco.names", "r") as f:
    classes = [line.strip() for line in f.readlines()]
# 生成随机颜色用于标注
colors = np.random.uniform(0, 255, size=(len(classes), 3))

需下载对应COCO类别文件coco.names并放在代码同目录下。

3. 调整检测参数适配航拍场景

无人机航拍视角下车辆尺寸较小,需针对性调整参数:

  • 降低置信度阈值:将if confidence > 0.5:改为if confidence > 0.2:,先捕捉低置信度结果再逐步优化。
  • 提升输入尺寸:将blobFromImage的(416,416)改为(608,608),增强小目标检测能力。
  • 检查色彩通道:确认blobFromImage的swapRB=True是否匹配视频格式(OpenCV默认读取BGR格式,该参数无需修改)。

4. 验证模型推理流程

  • 在循环中临时打印scores数组,查看是否有非零值,确认模型是否正常输出。
  • 单独测试单帧图片:截取视频中的一帧保存为图片,用代码单独检测,排除视频读取问题。

二、进阶功能实现(区分车辆、计数、追踪进出)

1. 区分轿车与卡车

利用COCO类别中的car(类别ID 2)和truck(类别ID 7),在检测时通过class_ids判断类别并分别统计:

car_count = 0
truck_count = 0
for i in range(len(boxes)):
    if i in indexes:
        class_id = class_ids[i]
        if classes[class_id] == "car":
            car_count +=1
        elif classes[class_id] == "truck":
            truck_count +=1
print(f"当前帧轿车数量:{car_count},卡车数量:{truck_count}")

2. 车辆总数统计与进出追踪

  • 使用IOU匹配或DeepSORT追踪算法为每个车辆分配唯一ID,避免重复计数。
  • 定义视频帧的进出区域(如上下边缘),当车辆检测框首次进入区域时计数加1,离开时标记为已离开。示例逻辑:
    # 初始化追踪字典,key为车辆ID,value为是否已计数
    tracked_vehicles = {}
    total_count = 0
    # 假设进出区域为帧底部1/5区域
    entry_line = frame_height * 4 // 5
    
    # 结合追踪ID处理(需先实现追踪逻辑)
    for vehicle_id in tracked_ids:
        box = tracked_boxes[vehicle_id]
        y1, y2 = box[1], box[1]+box[3]
        # 车辆进入底部区域且未被计数
        if y2 > entry_line and vehicle_id not in tracked_vehicles:
            tracked_vehicles[vehicle_id] = True
            total_count +=1
    

三、其他优化建议

  • 启用GPU加速:添加以下代码启用CUDA推理,提升处理速度:
    net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
    net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
    
  • 尝试新版本YOLO:YOLOv5/YOLOv8在小目标检测和易用性上更优,适配航拍场景效果更好。

内容的提问来源于stack exchange,提问作者Alex R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 01:43:21