25521浏览
查看: 25521|回复: 0

[M10教程] 行空板上YOLO和Mediapipe视频物体检测的测试

[复制链接]
1. 简介:
经过前面三篇教程帖子(yolov8n在行空板上的运行yolov10n在行空板上的运行Mediapipe在行空板上的运行)的介绍,我们对如何使用官方代码在行空板上运行物体检测的AI模型有了基本的概念,并对常见的模型进行了简单的测试和对比。
行空板上YOLO和Mediapipe图片物体检测的测试中,我们对于行空板上使用YOLO和Mediapipe进行图片物体检测进行了测试。
进一步的,本文将
- 对不同模型的视频物体检查进行详细的对比分析;
- 进行针对在行空板上的视频物体检测进行代码编写和优化;
- 对不同模型的帧率对比测试。
Note: 因为视频物体检测和图片物体检测用的是相同的模型,所以在检测准确性上不会有区别,所以检测结果的准确性可以直接参考以行空板上YOLO和Mediapipe图片物体检测的测试所做的测试。

2. yolo视频物体检测
2.1 不同onnx模型导出设置的表现对比
设置和代码
导出onnx模型的官方代码为:
  1. from ultralytics import YOLO
  2. # Load a pretrained YOLOv10n model
  3. model = YOLO("yolov10n.pt")
  4. #export onnx
  5. model.export(format='onnx')
复制代码
yolo系列模型在使用官方代码导出onnx格式模型的时候,有几个不同的选项:行空板上YOLO和Mediapipe视频物体检测的测试图1
- 其中,dynamic与imgsz不兼容;dynamic与half不兼容。
我们将分别对这几个选项的不同组合进行对比测试,分辨率都采用640。共包括以下模型:

行空板上YOLO和Mediapipe视频物体检测的测试图4
测试结果
对不同设置的模型进行行空板+USB摄像头的视频物体检测测试,结果如下:

行空板上YOLO和Mediapipe视频物体检测的测试图5
分析
通过测试结果的统计,可以分析得到以下特点:
  • dynamic设置可以略微减小模型大小,也会略微降低运行速度;
  • simplify也可以略微减小模型大小,但极不显著,也会略微降低运行速度;
  • 如果simplify和dynamic同时开启,不如值开启dynamic在模型尺寸上减少的明显;
  • half设置并没有速度上的提升,反而有降低,这是因为行空板没有半精度优化的硬件支持。

小结
  • 如果能事先知道输入图片的尺寸,就不要使用任何参数设置,只用imgsz设置图片尺寸;
  • 如果实现不知道图片输入的尺寸,就使用dynamic=True;
  • 不要设置half=True和simplify=True
2.2 不同尺寸输入的表现对比
yolo的测试结果(模型文件见附录)

行空板上YOLO和Mediapipe视频物体检测的测试图2
分析
可以看出,随着输入尺寸的减小,帧率显著提高。
yolov10n的帧率比yolov8n略高10%左右,同时模型大小减少25%。
小结
  • 对于视频检测,在行空板上以128的分辨率运行勉强可以使用;
  • 建议选择yolov10n,相较v8,内存占用和速度方面都有优势。
3. Mediapipe视频物体检测
设置
针对Mediapipe中的三个模型,我们分别测试了非量化和int8量化下的不同分辨率。
分辨率包括:
640、448、320、256、128
测试结果

行空板上YOLO和Mediapipe视频物体检测的测试图6
小结
- 与图片的目标检测结果类似,不同的分辨率对这些模型而言没有影响;
- 对于efficientdet_lite0和efficientdet_lite2,int8量化可以显著提速;int8量化对于ssd_mobilenet_v2没有影响

4. 视频物体检测总结
行空板上YOLO和Mediapipe视频物体检测的测试图7
我们在统计测试后发现了以下特点:
- yolo系列随着图片分辨率下调,检测耗时显著减少;而Mediapipe不明显。这说明在小分辨率图片检测中,yolo系列有显著的速度优势;
- det的两个模型进行int8量化之后速度显著提升,几乎不会损失准确性;
- Mediapipe的模型在较大分辨率的时候相比yolo有显著的速度优势,但是准确性略低一点。在应用的时候,需要在准确性和速度上进行权衡。

模型选择建议
- 限于视频帧率问题,我们认为最多使用320分辨率,使帧率达到1;
- 如果物体较近或者较大,在低分辨率图片上也可以方便地提取特征,这种情况下推荐使用较低分辨率而速度较快的模型,如64帧率的yolov8n;
- 如果物体较远或者物体较小,则需要分辨率更高才能提取到足够的特征,这种情况下推荐选择yolov10n。如果需要更高分辨率的图片,而且可以接收帧率较低,可以采用ssd_mobilenet_v2.tflite模型。可以参考下面的流程来选取模型:
行空板上YOLO和Mediapipe视频物体检测的测试图3

附录
   1. 使用yolov10n视频检测的代码
行空板+USB摄像头使用yolov10n进行物体检测的代码代码如下:
  1. import cv2
  2. import numpy as np
  3. import onnxruntime as ort
  4. import yaml
  5. import time
  6. def preprocess(frame, input_size):
  7.     #这里的resize使用nearest,可以提速大约0.3-0.5帧
  8.     image = cv2.resize(frame, input_size,interpolation=cv2.INTER_NEAREST)
  9.     # 转换图片到数组
  10.     image_data = np.array(image).transpose(2, 0, 1)  # 转换成CHW
  11.     image_data = image_data.astype(np.float32)
  12.     image_data /= 255.0  # 归一化
  13.     image_data = np.expand_dims(image_data, axis=0)  # 增加batch维度
  14.     return image_data
  15. def postprocess(output, image, input_size, show_size, classes):
  16.     for detection in output:
  17.         x1, y1, x2, y2, conf , class_id = detection
  18.         if conf > 0.4:
  19.             x1 = int(x1 / input_size[0] * show_size[0])
  20.             x2 = int(x2 / input_size[0] * show_size[0])
  21.             y1 = int(y1 / input_size[1] * show_size[1])
  22.             y2 = int(y2 / input_size[1] * show_size[1])
  23.             class_id = int(class_id)  
  24.             cv2.rectangle(image, (x1, y1), (x2, y2), (255, 0, 0), 2)  # 画框
  25.             class_name = classes[class_id]
  26.             cv2.putText(image, class_name, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
  27.     return image
  28. def main():
  29.     input_size = (128, 128)
  30.     with open('ultralytics/cfg/datasets/coco.yaml', 'r', encoding='utf-8') as f:
  31.         data = yaml.safe_load(f)
  32.     classes = data['names']
  33.     window_name = 'FullScreen Image'
  34.     cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
  35.     cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
  36.     # 加载模型
  37.     session = ort.InferenceSession('yolov10n.onnx')
  38.     input_name = session.get_inputs()[0].name
  39.     # 打开摄像头。
  40.     cap = cv2.VideoCapture(0)
  41.     if not cap.isOpened():
  42.         print("Cannot open camera")
  43.         exit()
  44.     prev_time = 0
  45.     while True:
  46.         ret, frame = cap.read()
  47.         show_size = [320,240]
  48.         if not ret:
  49.             print("Can't receive frame (stream end?). Exiting ...")
  50.             break
  51.         current_time = time.time()
  52.         # 预处理图像
  53.         input_tensor = preprocess(frame, input_size)
  54.         # 进行推理
  55.         outputs = session.run(None, {input_name: input_tensor})
  56.         output = outputs[0][0]
  57.         # 后处理
  58.         show_image = postprocess(output, frame, input_size, show_size, classes)
  59.         fps = 1.0 / (current_time - prev_time)
  60.         prev_time = current_time  # 更新前一帧的时间
  61.         cv2.putText(show_image, f"FPS: {fps:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
  62.         # 显示结果
  63.         cv2.imshow(window_name, show_image)
  64.         if cv2.waitKey(1) == ord('q'):
  65.             break
  66.     # 释放资源
  67.     cap.release()
  68.     cv2.destroyAllWindows()
  69. if __name__ == '__main__':
  70.     main()
复制代码
   2. 使用Mediapipe视频检测的代码
行空板+USB摄像头使用Mediapipe进行物体检测的代码代码如下:
  1. import numpy as np
  2. import mediapipe as mp
  3. from mediapipe.tasks import python
  4. from mediapipe.tasks.python import vision
  5. import cv2
  6. import time
  7. input_size = (640,640)
  8. # STEP 1: Import the necessary modules.
  9. base_options = python.BaseOptions(model_asset_path='efficientdet_lite0.tflite')
  10. options = vision.ObjectDetectorOptions(base_options=base_options,
  11.                                        score_threshold=0.5)
  12. detector = vision.ObjectDetector.create_from_options(options)
  13. # STEP 2: Create an ObjectDetector object.
  14. MARGIN = 10  # pixels
  15. ROW_SIZE = 10  # pixels
  16. FONT_SIZE = 1
  17. FONT_THICKNESS = 1
  18. TEXT_COLOR = (255, 0, 0)  # red
  19. def visualize(image, detection_result) -> np.ndarray:
  20.     """Draws bounding boxes on the input image and return it.
  21.     Args:
  22.       image: The input RGB image.
  23.       detection_result: The list of all "Detection" entities to be visualize.
  24.     Returns:
  25.       Image with bounding boxes.
  26.     """
  27.     for detection in detection_result.detections:
  28.         # Draw bounding_box
  29.         bbox = detection.bounding_box
  30.         start_point = bbox.origin_x, bbox.origin_y
  31.         end_point = bbox.origin_x + bbox.width, bbox.origin_y + bbox.height
  32.         cv2.rectangle(image, start_point, end_point, TEXT_COLOR, 3)
  33.         # Draw label and score
  34.         category = detection.categories[0]
  35.         category_name = category.category_name
  36.         probability = round(category.score, 2)
  37.         result_text = category_name + ' (' + str(probability) + ')'
  38.         text_location = (MARGIN + bbox.origin_x,
  39.                          MARGIN + ROW_SIZE + bbox.origin_y)
  40.         cv2.putText(image, result_text, text_location, cv2.FONT_HERSHEY_PLAIN,
  41.                     FONT_SIZE, TEXT_COLOR, FONT_THICKNESS)
  42.     return image
  43. # STEP 3: Initialize the video capture from the webcam.
  44. cap = cv2.VideoCapture(0)
  45. prev_time = 0
  46. while cap.isOpened():
  47.     ret, frame = cap.read()
  48.     if not ret:
  49.         break
  50.     frame = cv2.resize(frame, input_size, interpolation=cv2.INTER_NEAREST)
  51.     # Convert the frame to the format required by MediaPipe.
  52.     image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frame)
  53.     # STEP 4: Detect objects in the frame.
  54.     detection_result = detector.detect(image)
  55.     # STEP 5: Process the detection result. In this case, visualize it.
  56.     annotated_frame = visualize(frame, detection_result)
  57.     # Calculate and display the frame rate
  58.     current_time = time.time()
  59.     fps = 1 / (current_time - prev_time)
  60.     prev_time = current_time
  61.     fps_text = f'FPS: {fps:.2f}'
  62.     print(fps_text)
  63.     cv2.putText(annotated_frame, fps_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
  64.     cv2.imshow('Object Detection', annotated_frame)
  65.     # Break the loop if the user presses 'q'.
  66.     if cv2.waitKey(1) & 0xFF == ord('q'):
  67.         break
  68. # Release the resources.
  69. cap.release()
  70. cv2.destroyAllWindows()
复制代码
模型文件网盘链接:https://pan.baidu.com/s/18UpdaOMlC8uBsydk5DpwJQ?pwd=2t9f  提取码: 2t9f
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail