基于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
相关产品推荐
相关产品推荐

