本帖最后由 zoey不种土豆 于 2024-10-16 15:03 编辑
一、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 格式,并且必须包含描述模型操作参数的元数据。
行空板硬件介绍
行空板是一款专为Python学习和使用设计的新一代国产开源硬件,采用单板计算机架构,集成LCD彩屏、WiFi蓝牙、多种常用传感器和丰富的拓展接口。同时,其自带Linux操作系统和Python环境,还预装了常用的Python库,让广大师生只需两步就能进行Python教学。
行空板是一款基于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
在行空板上运行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! 
在终端输入:
source ~/.bashrc
安装完成,在终端输入:conda
终端显示:

Step 3 激活conda
在终端输入:conda activate 可以看到终端的显示由

变成

说明已经成功激活了conda
Step 4 在conda中建立MediaPipe环境
名字叫yolo,python版本选择3.10。在终端输入:conda create -n mediap python==3.10 过程中显示:

输入y
环境建立完终端显示:

Step 5 激活mediapipe环境
在终端中输入:conda activate mediapipe 
可以看到终端显示由

变成

说明激活mediapipe环境成功
Step 6 安装mediapipe
在终端输入:pip install mediapipe 
完成后终端显示:

三、快速开始:Mediapipe模型的运行
Step 1 激活mediapipe环境
在终端中输入:conda activate mediapipe 
可以看到终端显示由

变成

说明激活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如果想下载,可以在终端输入:


Step 5 编写代码
新建文件test_pic.py,并编写以下代码:
- import numpy as np
- import mediapipe as mp
- from mediapipe.tasks import python
- from mediapipe.tasks.python import vision
- import cv2
- import time
-
- # Define color mappings
- COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
- DEFAULT_COLOR = (255, 255, 255) # White for other categories
-
- def visualize(original_image, detection_result, scale_ratio) -> np.ndarray:
- """Draws bounding boxes on the input image and return it.
- Args:
- original_image: The original input RGB image.
- detection_result: The list of all "Detection" entities to be visualized.
- scale_ratio: The ratio of the resized image size to the original image size.
- Returns:
- Image with bounding boxes.
- """
- # Dictionary to store category-color mappings
- category_color_map = {}
-
- for detection in detection_result.detections:
- # Get the category of the object
- category = detection.categories[0]
- category_name = category.category_name
-
- # Assign a color to the category if not already assigned
- if category_name not in category_color_map:
- if len(category_color_map) < len(COLORS):
- category_color_map[category_name] = COLORS[len(category_color_map)]
- else:
- category_color_map[category_name] = DEFAULT_COLOR
-
- color = category_color_map[category_name]
-
- # Draw bounding box
- bbox = detection.bounding_box
- start_point = int(bbox.origin_x / scale_ratio), int(bbox.origin_y / scale_ratio)
- end_point = int((bbox.origin_x + bbox.width) / scale_ratio), int((bbox.origin_y + bbox.height) / scale_ratio)
- cv2.rectangle(original_image, start_point, end_point, color, 3)
-
- # Draw label and score
- probability = round(category.score, 2)
- result_text = category_name + ' (' + str(probability) + ')'
- text_location = (int((MARGIN + bbox.origin_x) / scale_ratio),
- int((MARGIN + ROW_SIZE + bbox.origin_y) / scale_ratio))
- cv2.putText(original_image, result_text, text_location, cv2.FONT_HERSHEY_PLAIN,
- FONT_SIZE, color, FONT_THICKNESS)
-
- return original_image
-
- def detect_objects(model_path, image_path, target_width, output_path, show_image):
- """Detect objects in an image and save/display the result.
- Args:
- model_path: Path to the model file.
- image_path: Path to the input image file.
- target_width: The width to resize the image for inference.
- output_path: Path to save the annotated image.
- show_image: Boolean flag to display the image after processing.
- """
- # STEP 1: Import the necessary modules.
- base_options = python.BaseOptions(model_asset_path=model_path)
- options = vision.ObjectDetectorOptions(base_options=base_options,
- score_threshold=0.5)
- detector = vision.ObjectDetector.create_from_options(options)
-
- # STEP 2: Create an ObjectDetector object.
- global MARGIN, ROW_SIZE, FONT_SIZE, FONT_THICKNESS
- MARGIN = 10 # pixels
- ROW_SIZE = 10 # pixels
- FONT_SIZE = 1
- FONT_THICKNESS = 1
-
- # STEP 3: Read the local image
- original_image = cv2.imread(image_path)
- if original_image is None:
- print("Error: Could not read image.")
- return
-
- # Resize the image to a smaller size to speed up inference
- scale_ratio = target_width / original_image.shape[1]
- target_height = int(original_image.shape[0] * scale_ratio)
- resized_image = cv2.resize(original_image, (target_width, target_height))
-
- # Convert the image to the format required by MediaPipe.
- mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=resized_image)
-
- # STEP 4: Detect objects in the image.
- start_time = time.time()
- detection_result = detector.detect(mp_image)
- end_time = time.time()
-
- # Print inference time
- inference_time = end_time - start_time
- print(f'Inference time: {inference_time:.2f} seconds')
-
- # STEP 5: Process the detection result. In this case, visualize it.
- annotated_image = visualize(original_image, detection_result, scale_ratio)
-
- # Save the result
- cv2.imwrite(output_path, annotated_image)
- print(f'Result saved to {output_path}')
-
- # Display the result if needed
- if show_image:
- cv2.imshow('Object Detection', annotated_image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
-
- # Example call
- detect_objects(
- model_path='efficientdet_lite0.tflite',
- image_path='bus.jpg',
- target_width=640,
- output_path='bus_640.jpg',
- show_image=False
- )
复制代码
这里使用上一步下载的 efficientdet_lite0.tflite 模型
Step 6 运行代码并查看结果
运行后终端显示:

可以看出,efficientdet_lite0 模型处理640分辨率的图片时间为2.62s。
处理后的图片结果如下

再使用efficientdet_lite2模型,耗时为8.47秒:


再使用 ssd_mobilenet_v2 运行,耗时为1.88秒:


小结
不同的模型效果和速度有所不同:
efficientdet_lite0 的准确性一般;
ssd_mobilenet_v2 的速度和准确性都较好。

四、优化:使用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模型,如:- import numpy as np
- import mediapipe as mp
- from mediapipe.tasks import python
- from mediapipe.tasks.python import vision
- import cv2
- import time
-
- # Define color mappings
- COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
- DEFAULT_COLOR = (255, 255, 255) # White for other categories
-
- def visualize(original_image, detection_result, scale_ratio) -> np.ndarray:
- (... ...)
-
- def detect_objects(model_path, image_path, target_width, output_path, show_image):
- (... ...)
-
- # Example call
- detect_objects(
- model_path='efficientdet_lite0_int8.tflite',
- image_path='bus.jpg',
- target_width=640,
- output_path='bus_640.jpg',
- show_image=False
- )
复制代码
Step 3 运行代码并查看结果
efficientdet_lite0_int8.tflite 模型运行耗时1.43秒:


efficientdet_lite2_int8.tflite 模型运行耗时4.03秒:


ssd_mobilenet_v2_int8.tflite 模型运行耗时1.82秒:


小结
量化后,det两个模型速度有明显提升,mobilenet变化不大;准确性都保持的很好。
五、进一步测试:不同的输入图片尺寸
为了进一步加快速度,我们还可以缩小推理图片的尺寸。步骤如下:
Step 1 修改代码
修改上面代码的Example call部分,例如对于efficientdet_lite0_int8.tflite 模型:
- import numpy as np
- import mediapipe as mp
- from mediapipe.tasks import python
- from mediapipe.tasks.python import vision
- import cv2
- import time
-
- <strong># Define color mappings</strong>
- COLORS = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] # Red, Green, Blue
- DEFAULT_COLOR = (255, 255, 255) # White for other categories
-
- def visualize(original_image, detection_result, scale_ratio) -> np.ndarray:
- (... ...)
-
- def detect_objects(model_path, image_path, target_width, output_path, show_image):
- (... ...)
-
- <strong># Example call</strong>
-
- for r in [640, 448, 320, 256, 128, 64]:
- print(r)
- detect_objects(
- model_path='efficientdet_lite0_int8.tflite',
- image_path='bus.jpg',
- target_width=r,
- output_path=f'bus_det_l2_{r}_int8.jpg',
- 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 模型:
 
对于 efficientdet_lite0_int8.tflite 模型:
 
对于 efficientdet_lite2.tflite 模型:
 
对于 efficientdet_lite2_int8.tflite 模型:
 
对于 ssd_mobilenet_v2.tflite 模型:
 
对于 ssd_mobilenet_v2_int8.tflite 模型:
 
小结
可以看到,随着输入尺寸的减小,模型的速度并没有明显变快。
并且,这三个模型训练的分辨率是固定的:
efficientdet_lite0.tflite:320
efficientdet_lite2.tflite:448
ssd_mobilenet_v2.tflite:256
输入的图片尺寸大反而对准确性有一定降低。
这儿有点反常的是,虽然 ssd_mobilenet_v2.tflite 的训练分辨率最低,但是其对于高分辨率图片的适应力还是较好的。
六、结论
1.可以在行空板运行Mediapipe的目标检测模型
本文详细介绍了如何在行空板上部署Mediapipe,并对几个常见模型进行了测试。
2.在行空板上,两个模型的int8量化可以带来显著的速度提升
对于 efficientdet_lite0 和 efficientdet_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.接下来会有更多测试,请持续关注!
|