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

[M10教程] Mediapipe在行空板上的运行

[复制链接]
本帖最后由 zoey不种土豆 于 2024-9-9 14:44 编辑

一、Mediapipe介绍
MediaPipe Solutions 提供了一套库和工具,可帮助您在您的应用中快速应用人工智能 (AI) 和机器学习 (ML) 技术。您可以立即将这些解决方案插入到您的应用中,根据需要对其进行自定义,并在多个开发平台上使用。MediaPipe Solutions 是 MediaPipe 开源项目的一部分,因此您可以进一步自定义解决方案代码以满足您的应用需求。
借助 MediaPipe Object Detector 任务,您可以检测图片或视频中多类对象的存在和位置。例如,对象检测器可以定位图片中的狗。此任务使用机器学习 (ML) 模型对图片数据执行操作,接受静态数据或连续视频串流作为输入并输出检测结果列表。每个检测结果代表图片或视频中出现的一个对象。
Mediapipe所用模型介绍
①EfficientDet-Lite0 模型介绍

EfficientDet-Lite0 模型使用具有 320x320 输入大小和 BiFPN 特征网络的 EfficientNet-Lite0 骨干网络。该模型是使用 COCO 数据集训练的,COCO 数据集是一种大型对象检测数据集,其中包含 150 万个对象实例和 80 个对象标签。请参阅支持的标签的完整列表。EfficientDet-Lite0 提供 int8、float16 或 float32。推荐使用此模型,因为它能够在延迟时间和准确率之间取得平衡。它既准确又轻量,对于许多使用场景来说都足够。
②EfficientDet-Lite2 模型介绍
EfficientDet-Lite2 模型使用具有 448x448 输入大小和 BiFPN 特征网络的 EfficientNet-Lite2 骨干网络。该模型是使用 COCO 数据集训练的,COCO 数据集是一种大型对象检测数据集,其中包含 150 万个对象实例和 80 个对象标签。请参阅支持的标签的完整列表。EfficientDet-Lite2 作为 int8、float16 或 float32 模型提供。此模型通常比 EfficientDet-Lite0 更准确,但速度也更慢且内存占用量更大。此模型适用于准确性比速度和规模更重要的用例。
③SSD MobileNetV2 模型介绍
SSD MobileNetV2 模型使用具有 256x256 输入大小和 SSD 功能网络的 MobileNetV2 骨干网络。该模型是使用 COCO 数据集训练的,COCO 数据集是一种大型对象检测数据集,其中包含 150 万个对象实例和 80 个对象标签。请参阅支持的标签的完整列表。SSD MobileNetV2 提供 int8 和 float 32 模式。此模型比 EfficientDet-Lite0 更快、更轻量,但通常也不太准确。此模型适用于需要快速、轻量级模型(牺牲一定程度的准确度)的用例。
④自定义模型
如果您决定构建用于此任务的模型,本部分介绍了自定义模型的要求。自定义模型必须采用 TensorFlow Lite 格式,并且必须包含描述模型操作参数的元数据。Mediapipe在行空板上的运行图16Mediapipe在行空板上的运行图15Mediapipe在行空板上的运行图17
行空板硬件介绍
行空板是一款专为Python学习和使用设计的新一代国产开源硬件,采用单板计算机架构,集成LCD彩屏、WiFi蓝牙、多种常用传感器和丰富的拓展接口。同时,其自带Linux操作系统和Python环境,还预装了常用的Python库,让广大师生只需两步就能进行Python教学。
Mediapipe在行空板上的运行图1
行空板是一款基于RK3308 Arm 64位四核处理器的开发板,主频达到1.2GHz,配备512MB DDR3内存和16GB eMMC硬盘,运行Debian 10操作系统。此外,它支持2.4G Wi-Fi和蓝牙4.0,采用RTL8723DS芯片。行空板还集成了GD32VF103C8T6 RISC-V协处理器,主频108MHz,具备64KB Flash和32KB SRAM。
行空板拥有多种板载元件,包括Home按键、A/B按键,2.8英寸可触控彩色屏幕,分辨率为240x320。设备还配备了电容式硅麦克风、PT0603光敏三极管光线传感器、无源蜂鸣器和蓝色LED。此外,它还内置了ICM20689六轴传感器,包括三轴加速度和三轴陀螺仪。
在接口方面,行空板提供了多种连接选项。具有USB Type-C接口,用于将CPU与PC连接进行编程或为主板供电。还有USB TYPE-A接口,用于连接外部USB设备。此外,板上还有microSD卡接口用于扩展存储空间,3Pin I/O支持3路10位PWM和2路12位ADC,独立的4Pin I2C接口,以及与micro:bit兼容的19路独立I/O金手指,支持多种通信协议和功能。
Mediapipe在行空板上的运行图2
在行空板上运行Mediapipe
在行空板上运行MediaPipe的尝试具有重要意义,主要体现在以下几个方面:
1.教育与实践:行空板是一款专为Python学习和使用设计的国产开源硬件,预装了常用的Python库,适合广大师生进行Python教学和实践。通过在行空板上运行MediaPipe,可以让学生和开发者更直观地理解和应用人工智能和机器学习技术。
2.高效开发:MediaPipe提供了一套高效的库和工具,能够快速实现AI和ML应用的开发。行空板集成了LCD彩屏、WiFi、蓝牙和多种传感器,提供了丰富的开发环境和硬件支持,使得在其上运行MediaPipe可以快速验证和展示AI应用。
3.硬件性能:行空板基于RK3308 Arm 64位四核处理器,配备512MB DDR3内存和16GB eMMC硬盘,性能足以支持MediaPipe的简单模型运行。其内置的六轴传感器、麦克风和其他传感器也为AI应用提供了丰富的数据输入源。
4.开源和定制化:MediaPipe作为开源项目,允许用户根据需求进行深度定制。而行空板的开源硬件设计也支持用户进行硬件和软件的定制和扩展,两者结合可以满足不同应用场景的需求。
5.便携性和集成度:行空板体积小巧,功能齐全,适合便携式AI应用开发和展示。在其上运行MediaPipe,可以实现实时的对象检测和其他AI功能,适用于物联网设备、智能家居、教育机器人等多种场景。
通过在行空板上运行MediaPipe,可以充分利用其硬件资源和软件环境,快速实现和展示AI应用,为教育、研究和开发提供强有力的支持。
本文将演示如何在行空板上部署Mediapipe三个小型物体检测模型,主要分为以下几部分:
  • 行空板上运行Mediapipe的环境准备;
  • 进行行空板上使用Mediapipe物体检测的代码运行;
  • 使用int8量化版本的模型对运行速度进行加速;
  • 测试不同分辨率图片对这几个模型性能的影响。
二、准备:运行Mediapipe的环境配置
step 1 下载mini conda
在终端输入:
wget https://github.com/conda-forge/m ... e3-Linux-aarch64.sh
下载完后终端显示:
已保存 “Miniforge3-Linux-aarch64.sh”
step 2 安装mini conda
在终端输入:
sudo bash Miniforge3-Linux-aarch64.sh
过程中遇到需要输入ENTER键或者yes键的照做。最后终端显示:
Added mamba to /root/.bashrc
==> For changes to take effect, close and re-open your current shell. <==
Thank you for installing Miniforge3!
Mediapipe在行空板上的运行图3
在终端输入:
source ~/.bashrc
安装完成,在终端输入:
conda
终端显示:
Mediapipe在行空板上的运行图4
Step 3 激活conda
在终端输入:
conda activate
可以看到终端的显示由
Mediapipe在行空板上的运行图5
变成
Mediapipe在行空板上的运行图6
说明已经成功激活了conda
Step 4 在conda中建立MediaPipe环境
名字叫yolo,python版本选择3.10。在终端输入:
conda create -n mediap python==3.10
过程中显示:
Mediapipe在行空板上的运行图8
输入y
环境建立完终端显示:
Mediapipe在行空板上的运行图7
Step 5 激活mediapipe环境
在终端中输入:
conda activate mediapipe
Mediapipe在行空板上的运行图9
可以看到终端显示由
Mediapipe在行空板上的运行图10
变成
Mediapipe在行空板上的运行图11
说明激活mediapipe环境成功
Step 6 安装mediapipe
在终端输入:
pip install mediapipe
Mediapipe在行空板上的运行图12
完成后终端显示:
Mediapipe在行空板上的运行图13
三、快速开始:Mediapipe模型的运行
Step 1 激活mediapipe环境
在终端中输入:
conda activate mediapipe
Mediapipe在行空板上的运行图19
可以看到终端显示由
Mediapipe在行空板上的运行图18
变成
Mediapipe在行空板上的运行图20
说明激活mediapipe环境成功
Step 2 创建目录mediapipe
在终端输入:
mkdir mediapipe
创建mediapipe目录,然后终端输入:
cd mediapipe
进入目录。
Step 3 下载模型文件
可以在下面网址下载所要运行的模型:
https://ai.google.dev/edge/mediapipe/solutions/vision/object_detector/index?hl=zh-cn#models
如Introduction中所介绍,官方提供了三个物体检测模型
EfficientDet-Lite0
EfficientDet-Lite2
SSDMobileNet-V2
可以分别下载这三个模型进行运行。
Step 4 准备图片
这里仍然使用bus.jpg如果想下载,可以在终端输入:
Mediapipe在行空板上的运行图49
Mediapipe在行空板上的运行图48
Step 5 编写代码
新建文件test_pic.py,并编写以下代码:
  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. # Define color mappings
  8. COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # Red, Green, Blue
  9. DEFAULT_COLOR = (255, 255, 255)  # White for other categories
  10. def visualize(original_image, detection_result, scale_ratio) -> np.ndarray:
  11.     """Draws bounding boxes on the input image and return it.
  12.     Args:
  13.       original_image: The original input RGB image.
  14.       detection_result: The list of all "Detection" entities to be visualized.
  15.       scale_ratio: The ratio of the resized image size to the original image size.
  16.     Returns:
  17.       Image with bounding boxes.
  18.     """
  19.     # Dictionary to store category-color mappings
  20.     category_color_map = {}
  21.     for detection in detection_result.detections:
  22.         # Get the category of the object
  23.         category = detection.categories[0]
  24.         category_name = category.category_name
  25.         # Assign a color to the category if not already assigned
  26.         if category_name not in category_color_map:
  27.             if len(category_color_map) < len(COLORS):
  28.                 category_color_map[category_name] = COLORS[len(category_color_map)]
  29.             else:
  30.                 category_color_map[category_name] = DEFAULT_COLOR
  31.         color = category_color_map[category_name]
  32.         # Draw bounding box
  33.         bbox = detection.bounding_box
  34.         start_point = int(bbox.origin_x / scale_ratio), int(bbox.origin_y / scale_ratio)
  35.         end_point = int((bbox.origin_x + bbox.width) / scale_ratio), int((bbox.origin_y + bbox.height) / scale_ratio)
  36.         cv2.rectangle(original_image, start_point, end_point, color, 3)
  37.         # Draw label and score
  38.         probability = round(category.score, 2)
  39.         result_text = category_name + ' (' + str(probability) + ')'
  40.         text_location = (int((MARGIN + bbox.origin_x) / scale_ratio),
  41.                          int((MARGIN + ROW_SIZE + bbox.origin_y) / scale_ratio))
  42.         cv2.putText(original_image, result_text, text_location, cv2.FONT_HERSHEY_PLAIN,
  43.                     FONT_SIZE, color, FONT_THICKNESS)
  44.     return original_image
  45. def detect_objects(model_path, image_path, target_width, output_path, show_image):
  46.     """Detect objects in an image and save/display the result.
  47.     Args:
  48.       model_path: Path to the model file.
  49.       image_path: Path to the input image file.
  50.       target_width: The width to resize the image for inference.
  51.       output_path: Path to save the annotated image.
  52.       show_image: Boolean flag to display the image after processing.
  53.     """
  54.     # STEP 1: Import the necessary modules.
  55.     base_options = python.BaseOptions(model_asset_path=model_path)
  56.     options = vision.ObjectDetectorOptions(base_options=base_options,
  57.                                            score_threshold=0.5)
  58.     detector = vision.ObjectDetector.create_from_options(options)
  59.     # STEP 2: Create an ObjectDetector object.
  60.     global MARGIN, ROW_SIZE, FONT_SIZE, FONT_THICKNESS
  61.     MARGIN = 10  # pixels
  62.     ROW_SIZE = 10  # pixels
  63.     FONT_SIZE = 1
  64.     FONT_THICKNESS = 1
  65.     # STEP 3: Read the local image
  66.     original_image = cv2.imread(image_path)
  67.     if original_image is None:
  68.         print("Error: Could not read image.")
  69.         return
  70.     # Resize the image to a smaller size to speed up inference
  71.     scale_ratio = target_width / original_image.shape[1]
  72.     target_height = int(original_image.shape[0] * scale_ratio)
  73.     resized_image = cv2.resize(original_image, (target_width, target_height))
  74.     # Convert the image to the format required by MediaPipe.
  75.     mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=resized_image)
  76.     # STEP 4: Detect objects in the image.
  77.     start_time = time.time()
  78.     detection_result = detector.detect(mp_image)
  79.     end_time = time.time()
  80.     # Print inference time
  81.     inference_time = end_time - start_time
  82.     print(f'Inference time: {inference_time:.2f} seconds')
  83.     # STEP 5: Process the detection result. In this case, visualize it.
  84.     annotated_image = visualize(original_image, detection_result, scale_ratio)
  85.     # Save the result
  86.     cv2.imwrite(output_path, annotated_image)
  87.     print(f'Result saved to {output_path}')
  88.     # Display the result if needed
  89.     if show_image:
  90.         cv2.imshow('Object Detection', annotated_image)
  91.         cv2.waitKey(0)
  92.         cv2.destroyAllWindows()
  93. # Example call
  94. detect_objects(
  95.     model_path='efficientdet_lite0.tflite',
  96.     image_path='bus.jpg',
  97.     target_width=640,
  98.     output_path='bus_640.jpg',
  99.     show_image=False
  100. )
复制代码

这里使用上一步下载的 efficientdet_lite0.tflite 模型
Step 6 运行代码并查看结果
运行后终端显示:
Mediapipe在行空板上的运行图14
可以看出,efficientdet_lite0 模型处理640分辨率的图片时间为2.62s。
处理后的图片结果如下
Mediapipe在行空板上的运行图23
再使用efficientdet_lite2模型,耗时为8.47秒:
Mediapipe在行空板上的运行图21
Mediapipe在行空板上的运行图24
再使用 ssd_mobilenet_v2 运行,耗时为1.88秒:
Mediapipe在行空板上的运行图22
Mediapipe在行空板上的运行图25
小结
不同的模型效果和速度有所不同:
efficientdet_lite0 的准确性一般;
ssd_mobilenet_v2 的速度和准确性都较好。
Mediapipe在行空板上的运行图26
四、优化:使用int8量化的模型

我们可以使用官方提供的int8模型进行加速。步骤如下:
Step 1 下载官方int8模型
直接到下载官方的int8模型即可。地址如下:
EfficientDet-Lite0 (int8)
EfficientDet-Lite2 (int8)
SSDMobileNet-V2 (int8)
分别保存为:
efficientdet_lite0_int8.tflite
efficientdet_lite2_int8.tflite
ssd_mobilenet_v2_int8.tflite

Step 2 修改代码
将上一步中的代码中的模型替换成上面下载的int8模型,如:
  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. # Define color mappings
  8. COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # Red, Green, Blue
  9. DEFAULT_COLOR = (255, 255, 255)  # White for other categories
  10. def visualize(original_image, detection_result, scale_ratio) -> np.ndarray:
  11.     (... ...)
  12. def detect_objects(model_path, image_path, target_width, output_path, show_image):
  13.     (... ...)
  14. # Example call
  15. detect_objects(
  16.     model_path='efficientdet_lite0_int8.tflite',
  17.     image_path='bus.jpg',
  18.     target_width=640,
  19.     output_path='bus_640.jpg',
  20.     show_image=False
  21. )
复制代码
Step 3 运行代码并查看结果
efficientdet_lite0_int8.tflite 模型运行耗时1.43秒:
Mediapipe在行空板上的运行图28
Mediapipe在行空板上的运行图29
efficientdet_lite2_int8.tflite 模型运行耗时4.03秒:
Mediapipe在行空板上的运行图27
Mediapipe在行空板上的运行图31
ssd_mobilenet_v2_int8.tflite 模型运行耗时1.82秒:
Mediapipe在行空板上的运行图30
Mediapipe在行空板上的运行图32
小结
量化后,det两个模型速度有明显提升,mobilenet变化不大;准确性都保持的很好。
Mediapipe在行空板上的运行图33
  • 本测试中准确性的判断标准为(下文同):
Mediapipe在行空板上的运行图34
五、进一步测试:不同的输入图片尺寸
为了进一步加快速度,我们还可以缩小推理图片的尺寸。步骤如下:
Step 1 修改代码
修改上面代码的Example call部分,例如对于efficientdet_lite0_int8.tflite 模型:
  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. <strong># Define color mappings</strong>
  8. COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # Red, Green, Blue
  9. DEFAULT_COLOR = (255, 255, 255)  # White for other categories
  10. def visualize(original_image, detection_result, scale_ratio) -> np.ndarray:
  11.     (... ...)
  12. def detect_objects(model_path, image_path, target_width, output_path, show_image):
  13.     (... ...)
  14. <strong># Example call</strong>
  15. for r in [640, 448, 320, 256, 128, 64]:
  16.     print(r)
  17.     detect_objects(
  18.     model_path='efficientdet_lite0_int8.tflite',
  19.     image_path='bus.jpg',
  20.     target_width=r,
  21.     output_path=f'bus_det_l2_{r}_int8.jpg',
  22.     show_image=False)</code></pre></div><span data-lark-record-data="{"rootId":"H1QFdiICyo9ed2xHbeBcNUr5nxf","text":{"initialAttributedTexts":{"text":{"0":"import numpy as np\nimport mediapipe as mp\nfrom mediapipe.tasks import python\nfrom mediapipe.tasks.python import vision\nimport cv2\nimport time\n\n# Define color mappings\nCOLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # Red, Green, Blue\nDEFAULT_COLOR = (255, 255, 255)  # White for other categories\n\ndef visualize(original_image, detection_result, scale_ratio) -> np.ndarray:\n    (... ...)\n\ndef detect_objects(model_path, image_path, target_width, output_path, show_image):\n    (... ...)\n\n# Example call\n\nfor r in [640, 448, 320, 256, 128, 64]:\n    print(r) \n    detect_objects(\n    model_path='efficientdet_lite0_int8.tflite', \n    image_path='bus.jpg', \n    target_width=r, \n    output_path=f'bus_det_l2_{r}_int8.jpg', \n    show_image=False)"},"attribs":{"0":"*0|7+3z*0*1+n*0|a+8y*0*1+e*0|9+63*0+l"}},"apool":{"numToAttrib":{"0":["author","7360571945601384452"],"1":["bold","true"]},"nextNum":2}},"type":"text","referenceRecordMap":{},"extra":{"channel":"saas","pasteRandomId":"6d2e8d82-caef-41a8-9a3d-95f5b148996c","mention_page_title":{},"external_mention_url":{}},"isKeepQuoteContainer":false,"isFromCode":true,"selection":[{"id":210,"type":"text","selection":{"start":0,"end":742},"recordId":"QgWRdUfmsoKwLgxNoADcO3kNnmh"}],"payloadMap":{},"isCut":false}" data-lark-record-format="docx/text" class="lark-record-clipboard"></span>
复制代码
Step 2 运行代码并查看结果
对于 efficientdet_lite0.tflite 模型:
Mediapipe在行空板上的运行图36Mediapipe在行空板上的运行图35
对于 efficientdet_lite0_int8.tflite  模型:
Mediapipe在行空板上的运行图37Mediapipe在行空板上的运行图38
对于 efficientdet_lite2.tflite 模型:
Mediapipe在行空板上的运行图39Mediapipe在行空板上的运行图40
对于 efficientdet_lite2_int8.tflite 模型:

Mediapipe在行空板上的运行图41Mediapipe在行空板上的运行图42
对于 ssd_mobilenet_v2.tflite 模型:
Mediapipe在行空板上的运行图43Mediapipe在行空板上的运行图44
对于 ssd_mobilenet_v2_int8.tflite 模型:
Mediapipe在行空板上的运行图45Mediapipe在行空板上的运行图46
小结
可以看到,随着输入尺寸的减小,模型的速度并没有明显变快。
并且,这三个模型训练的分辨率是固定的:
efficientdet_lite0.tflite:320
efficientdet_lite2.tflite:448
ssd_mobilenet_v2.tflite:256
输入的图片尺寸大反而对准确性有一定降低。
这儿有点反常的是,虽然 ssd_mobilenet_v2.tflite 的训练分辨率最低,但是其对于高分辨率图片的适应力还是较好的。
Mediapipe在行空板上的运行图47
六、结论
1.可以在行空板运行Mediapipe的目标检测模型
本文详细介绍了如何在行空板上部署Mediapipe,并对几个常见模型进行了测试。
2.在行空板上,两个模型的int8量化可以带来显著的速度提升
对于 efficientdet_lite0efficientdet_lite2 模型,int8量化有显著的速度提升,而且精度表现没有明显下降;对于 ssd_mobilenet_v2 模型,int8量化并没有带来速度提升(不确定官方的模型是否正确)。
3.在行空板上使用Mediapipe进行目标检测时的模型推荐
随着输入尺寸的减小,模型的速度并没有明显变快;有的模型,随着输入图片尺寸变大,性能反而下降。对于中小分辨率的图片(128-448),推荐使用 efficientdet_lite0_int8.tflite 模型;对于较大分辨率的图片(>448),推荐使用 ssd_mobilenet_v2.tflite 模型。
4.较小分辨率时,模型 efficientdet_lite0_int8.tflite 准确率最好;较大分辨率时,模型 efficientdet_lite2_int8.tflite 准确率较好。
5.接下来会有更多测试,请持续关注!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

硬件清单

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

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

mail