Maix例程代码学习

python 复制代码
from maix import camera, display, image, nn, app

detect_conf_th = 0.5
detect_iou_th = 0.45
emotion_conf_th = 0.5
max_face_num = -1
crop_scale = 0.9

# detect face model
detector = nn.YOLOv8(model="/root/models/yolov8n_face.mud", dual_buff = False)
# we only use one of it's function to crop face from image, wo we not init model actually
landmarks_detector = nn.FaceLandmarks(model="")
# emotion classify model
classifier = nn.Classifier(model="/root/models/face_emotion.mud", dual_buff=False)

cam = camera.Camera(detector.input_width(), detector.input_height(), detector.input_format())
disp = display.Display()

# for draw result info
max_labels_length = 0
for label in classifier.labels:
    size = image.string_size(label)
    if size.width() > max_labels_length:
        max_labels_length = size.width()

max_score_length = cam.width() / 4

while not app.need_exit():
    img = cam.read()
    results = []
    objs = detector.detect(img, conf_th = detect_conf_th, iou_th = detect_iou_th, sort = 1)
    count = 0
    idxes = []
    img_std_first : image.Image = None
    for i, obj in enumerate(objs):
        img_std = landmarks_detector.crop_image(img, obj.x, obj.y, obj.w, obj.h, obj.points,
                                            classifier.input_width(), classifier.input_height(), crop_scale)
        if img_std:
            img_std_gray = img_std.to_format(image.Format.FMT_GRAYSCALE)
            res = classifier.classify(img_std_gray, softmax=True)
            results.append(res)
            idxes.append(i)
            if i == 0:
                img_std_first = img_std
            count += 1
            if max_face_num > 0 and count >= max_face_num:
                break
    for i, res in enumerate(results):
        # draw fisrt face detailed info
        if i == 0:
            img.draw_image(0, 0, img_std_first)
            for j in range(len(classifier.labels)):
                idx = res[j][0]
                score = res[j][1]
                img.draw_string(0, img_std_first.height() + idx * 16, classifier.labels[idx], image.COLOR_WHITE)
                img.draw_rect(max_labels_length, int(img_std_first.height() + idx * 16), int(score * max_score_length), 8, image.COLOR_GREEN if score >= emotion_conf_th else image.COLOR_RED, -1)
                img.draw_string(int(max_labels_length + score * max_score_length + 2), int(img_std_first.height() + idx * 16), f"{score:.1f}", image.COLOR_RED)
        # draw on all face
        color = image.COLOR_GREEN if res[0][1] >= emotion_conf_th else image.COLOR_RED
        obj = objs[idxes[i]]
        img.draw_rect(obj.x, obj.y, obj.w, obj.h, color, 1)
        img.draw_string(obj.x, obj.y, f"{classifier.labels[res[0][0]]}: {res[0][1]:.1f}", color)
    disp.show(img)

1、from maix import camera,display,image,nn,app这是属于python的模块导入语法,核心包为maix,在maix里导入五个子模块,分别为camera,image,display,nn,app模块

(1)maix.camera是硬件摄像头控制模块,封装了Maix设备上摄像头的所有操作,核心能力包括:

初始化摄像头硬件,配置摄像头参数(分辨率,帧率,像素格式,曝光,白平衡等参数),读取摄像头实时画面(返回图像对象-image),底层驱动管理(自动适配不同的摄像头模组,不用手动配置寄存器)

python 复制代码
from maix import camera,image
# 初始化摄像头(640x480分辨率,RGB888像素格式)
cam = camera.Camera(width=640, height=480, format=image.Format.FMT_RGB888)
# 读取一帧画面(返回 image.Image 对象)
img = cam.read()
# 关闭摄像头
cam.close()

(2)maix.display是硬件显示屏控制模块,封装了 Maix 设备上显示屏(LCD/HDMI 屏)的所有操作,核心能力包括:

初始化显示屏硬件(如屏幕分辨率),将图像数据传输到屏幕显示,控制屏幕亮度,帅心率,休眠和唤醒,帧缓冲管理

python 复制代码
from maix import display, camera
cam = camera.Camera()
disp = display.Display()  # 自动初始化显示屏
while True:
    img = cam.read()
    disp.show(img)  # 将摄像头画面显示到屏幕

(3)maix.iamge是图像处理核心模块,封装了所有针对图像的操作

功能分类 具体操作
图像创建 / 转换 创建空白图像、格式转换(RGB↔灰度、RGB565↔RGB888)、尺寸缩放 / 裁剪
绘图操作 画点、线、矩形、圆形、文字、图像叠加(如 draw_rect/draw_string
像素级操作 获取 / 设置像素值、图像翻转 / 旋转、对比度 / 亮度调整
数据交互 图像数据导出(转 numpy 数组)、从字节流创建图像

(4)maix.nn是AI推理大模型,封装了 Maix 芯片的 NPU(神经网络处理单元)和 AI 模型运行时,核心能力包括:

  • 加载 AI 模型(支持 .mud 格式,Maix 优化的模型格式,也支持 ONNX/TFLite);
  • 执行模型推理(人脸检测、情绪分类、目标识别等);
  • 推理结果后处理(非极大值抑制 NMS、置信度过滤);
  • NPU 资源管理(分配 / 释放计算资源,避免内存泄漏)。

(5)maix.app是应用程序生命周期管理模块,核心解决嵌入式设备中 "优雅退出程序" 的问题

python 复制代码
from maix import app
# 主循环:直到检测到退出信号才停止
while not app.need_exit():
    # 业务逻辑(摄像头采集、推理、显示)
    pass
# 程序退出时,app 自动释放所有硬件资源

2、加载AI模型

(1)detector = nn.YOLOv8(model = "/root/models/yolov8n_face.mud",dual_buff = Flase)

.mud 是 maixVision 优化的模型格式

dual_buff=False:关闭双缓冲(开启占用更多内存但提升帧率

(2)landmarks_detector = nn.FaceLandmarks(model = "")

拆分部分 逐词深度解析
nn 延续前文解析:Neural Network(神经网络)模块的缩写,封装 Maix 芯片 NPU 驱动、AI 模型加载 / 推理逻辑,是所有 AI 相关类的父模块。
. Python 属性访问符(点运算符),表示 "访问 nn 模块中的 FaceLandmarks 类"。
FaceLandmarks - 拆分:Face(/feɪs/,中文 "人脸") + Landmarks(/ˈlændmɑːrks/,中文 "关键点 / 地标",是 landmark 的复数形式); - 代码含义:nn 模块中专门封装 "人脸关键点检测" 的类,该类内置了: ✅ 关键点检测模型的加载逻辑; ✅ 关键点坐标的计算 / 输出逻辑; ✅ 基于关键点的人脸对齐 / 裁剪逻辑(核心复用功能); - 底层逻辑:该类原本设计用于加载人脸关键点检测模型(如 5 点 / 68 点模型),输出人脸特征点坐标;但 maixVision 框架做了灵活设计 ------ 即使不加载模型(model=""),也能调用其内置的 "基于人脸框的裁剪逻辑"(无需关键点,仅用框坐标即可裁剪),这是新手友好的 "功能复用" 设计。

(3)classifier = nn.Classifier(model="/root/models/face_emotion.mud", dual_buff=False)

拆分部分 逐词深度解析
nn 仍为 Neural Network 模块,所有 AI 模型相关类的父模块。
. 属性访问符,访问 nn 模块中的 Classifier 类。
Classifier - 英文释义:/ˈklæsɪfaɪə(r)/,中文 "分类器",是 maixVision 框架中专门封装 "图像分类 / 文本分类" 任务的通用类; - 代码含义:该类适配所有分类类 AI 模型(如 ResNet、MobileNet、CNN 等轻量化分类模型),内置: ✅ 分类模型的加载 / 解析逻辑; ✅ 输入数据的预处理(如归一化、格式转换); ✅ 推理结果的后处理(如 Softmax 归一化、返回类别 + 置信度); - 底层逻辑:不同于 nn.YOLOv8(专用检测类),nn.Classifier通用分类类------ 无论是什么类型的分类模型(只要转成 .mud 格式),都能通过该类加载和推理,无需针对不同分类算法写不同代码,是框架 "通用性" 的体现。

(4)参数列表:(model="/root/models/face_emotion.mud", dual_buff=False)

参数部分 逐词深度解析
(/) 圆括号,包裹分类器初始化参数列表。
model 核心参数,指定情绪分类模型的文件路径;路径 /root/models/face_emotion.mud 拆解: ✅ /root/models/:Maix 设备默认的模型存储目录(同前文); ✅ face_emotion:模型文件名,拆分: - face:表示模型输入是 "人脸图像"(而非全图); - emotion:/ɪˈməʊʃn/,中文 "情绪",表示模型的核心任务是情绪分类; ✅ .mud:maixVision 优化的模型格式(同前文),该格式针对情绪分类模型做了量化(INT8)和 NPU 适配,确保在嵌入式设备上快速推理。
, 英文逗号,分隔多个关键字参数。
dual_buff 同前文:dual buffer(双缓冲)的缩写,控制推理的缓冲机制;此处设为 False 的原因: ✅ 情绪分类是 "单帧处理",无需高帧率(10 FPS 足够); ✅ 节省内存:情绪分类模型输入尺寸小(如 48x48 灰度图),双缓冲节省的时间可忽略,关闭后减少内存占用。
= 关键字参数赋值符号。
False Python 布尔常量(假),表示关闭双缓冲机制;对比 True:若设为 True,会初始化双缓冲内存,推理帧率提升 1~2 FPS,但内存占用增加约 100KB(情绪分类模型输入小,内存影响极小,新手仍建议保持 False 以简化逻辑)。

3、硬件初始化

python 复制代码
# detector.input_width()/height():获取模型要求的输入尺寸
# detector.input_format():获取模型要求的图像格式(如 RGB565)

cam = camera.Camera(detector.input_width(), detector.input_height(), detector.input_format())

# 初始化显示屏:自动适配硬件屏幕分辨率(如 MaixCAM 的 1080P 屏)
disp = display.Display()
拆分部分 逐词深度解析
camera - 单词本义:/ˈkæm (ə) rə/,中文 "摄像头、摄影机";- 代码含义:从maix包导入的 "摄像头硬件控制模块"(前文已解析),封装了摄像头的底层驱动(如 MIPI/USB 摄像头驱动)、参数配置、画面读取等核心功能;- 底层逻辑:该模块不是纯 Python 代码,而是 C/C++ 实现的硬件驱动 + Python 封装的接口,直接操作摄像头的寄存器和帧缓冲区。
. Python 属性访问符(点运算符),表示 "访问camera模块中的Camera类"。
Camera - 单词本义:/ˈkæm (ə) rə/,首字母大写表示这是一个类(Class) (Python 中类名通常首字母大写);- 代码含义:camera模块的核心类,是操作摄像头的唯一入口,初始化该类时会完成: ✅ 硬件检测:识别设备上连接的摄像头类型(MIPI/USB); ✅ 参数配置:设置分辨率、像素格式、帧率、曝光等; ✅ 硬件打开:启动摄像头的图像采集功能,分配帧缓冲区内存;- 核心特性:支持 "参数自动适配",无需手动配置底层寄存器。
参数部分 逐词深度解析
(/) 圆括号,包裹类初始化的参数列表,向Camera类的__init__方法传递参数。
detector.input_width() - detector:前文初始化的 YOLOv8 人脸检测模型对象(nn.YOLOv8实例);- .:属性访问符,访问detector对象的方法;- input_width()nn.YOLOv8类的内置成员方法 (无参数),作用是: 1. 读取.mud模型文件中存储的 "输入宽度" 元数据(如 640); 2. 返回该数值(整数类型);- 底层逻辑:模型文件(.mud)中不仅包含权重和网络结构,还存储了输入尺寸、格式、输出类别等元数据,input_width()就是读取该元数据的接口。
, 英文逗号,分隔多个位置参数(按顺序传递,区别于关键字参数)。
detector.input_height() - 与input_width()对称,返回模型要求的输入高度(如 640);- 注意:YOLOv8 模型的输入通常是正方形(如 640×640),但也支持矩形(如 640×480),该方法会返回实际值。
, 参数分隔符。
detector.input_format() - input_format()nn.YOLOv8类的内置方法,返回模型要求的输入图像格式;- 返回值类型:不是字符串(如 "RGB565"),而是image.Format枚举常量(如image.Format.FMT_RGB565);- 核心作用:确保摄像头输出的图像格式与模型要求完全一致,避免格式转换的性能损耗(嵌入式设备格式转换会占用 CPU 资源,降低帧率)。

4. 预处理:计算可视化尺寸(保证显示美观)

python 复制代码
# ===================== 4. 预处理:计算可视化尺寸(保证显示美观) =====================
max_labels_length = 0       # 存储最长情绪标签的宽度(用于对齐得分条)
# 遍历所有情绪标签,计算文字显示的最大宽度
for label in classifier.labels:
    # 获取当前标签文字的显示尺寸(宽/高)
    size = image.string_size(label)
    # 更新最大宽度
    if size.width() > max_labels_length:
        max_labels_length = size.width()

# 得分条最大宽度:摄像头宽度的 1/4(可根据屏幕大小调整)
max_score_length = cam.width() / 4
注释内容 逐词 / 逐句解析
4. 预处理:计算可视化尺寸(保证显示美观) - #:Python 单行注释符,无执行意义;- 4. 预处理:标注这是程序第 4 个核心步骤,"预处理" 是编程术语,指 "在核心逻辑(如绘制)前,提前计算 / 准备所需的参数,避免主循环中重复计算(提升效率)";- 计算可视化尺寸:明确预处理的核心任务 ------ 计算文字、得分条的显示尺寸;- (保证显示美观):解释预处理的最终目的:避免文字和得分条重叠、错位,让屏幕显示的内容整齐对齐;- 等号=====:格式分隔符,提升代码可读性。
# 存储最长情绪标签的宽度(用于对齐得分条) - 存储最长情绪标签的宽度:解释变量max_labels_length的作用 ------ 记录所有情绪标签(如 happy/angry/neutral)中,文字显示时宽度最大的值;- (用于对齐得分条):说明该变量的核心用途:让所有得分条从 "最长标签宽度" 的位置开始绘制,确保得分条左对齐(比如 "happy" 宽 80 像素,"angry" 宽 70 像素,得分条都从 80 像素位置开始,不会错位)。
# 遍历所有情绪标签,计算文字显示的最大宽度 - 遍历:Python 循环术语(对应for循环),指 "逐个访问列表中的元素";- 所有情绪标签:指classifier.labels中的每一个标签(如 ["happy", "angry", "neutral"]);- 计算文字显示的最大宽度:说明循环的核心目的 ------ 算出所有标签文字在屏幕上显示时的最大宽度。
# 获取当前标签文字的显示尺寸(宽/高) - 获取当前标签文字:指循环中当前迭代的label变量(如第一次循环是 "happy",第二次是 "angry");- 显示尺寸(宽/高):文字在屏幕上显示时占据的像素宽度和高度(如 "happy" 显示为宽 80 像素、高 16 像素);- 补充:不同文字的显示尺寸不同(如 "开心" 和 "生气" 的中文字宽不同,英文字母也因字符数 / 字体不同而不同)。
# 更新最大宽度 - 更新:指比较当前标签宽度和已记录的最大宽度,若更大则替换;- 最大宽度:即变量max_labels_length存储的值。
# 得分条最大宽度:摄像头宽度的 1/4(可根据屏幕大小调整) - 得分条最大宽度:解释变量max_score_length的作用 ------ 限定情绪得分条的最大像素宽度(避免得分条太长占满屏幕);- 摄像头宽度的 1/4:说明宽度的计算规则(按摄像头分辨率的比例,而非固定值,适配不同硬件);- (可根据屏幕大小调整):使用建议 ------ 屏幕大则可设为 1/3,屏幕小则设为 1/5,灵活调整。

size = image.string_size(label)

部分 含义解析
image maix 的图像模块(前文解析过),封装了所有图像 / 文字绘制相关功能;
. 属性访问符,访问image模块的函数;
string_size 模块内置函数,核心作用:计算指定文字在屏幕上显示时的 "像素尺寸(宽 × 高)"; - 函数参数:string_size(text, font=None, size=None),默认使用硬件内置字体(如 16 号像素字体); - 返回值:image.Size对象,包含width()(宽度)和height()(高度)两个方法。
label 循环变量,传入当前要计算的情绪标签文字(如 "happy")。

再来就是更新最大宽度

部分 含义解析
if Python 条件判断关键字,满足条件时执行缩进的代码块;
size.width() 调用Size对象的width()方法,返回当前标签文字的显示宽度(如 80);
> 比较运算符,"大于";
max_labels_length 当前记录的最大宽度(初始为 0,后续随循环更新)。

计算得分条最大宽度

部分 含义解析
max_score_length 变量名:max(最大)+score(得分)+length(长度)→ "得分条的最大显示长度";
cam.width() 调用摄像头对象的width()方法,返回摄像头的宽度(如 640 像素);
/ Python 除法运算符,计算摄像头宽度的 1/4;
4 比例系数,可调整为 3/5/6 等,控制得分条的最大宽度。

5、主循环核心逻辑

注释内容 逐词 / 逐句解析
# ===================== 5. 主循环(核心业务逻辑) ===================== - #:Python 单行注释符;- 5. 主循环:标注这是程序第 5 个核心步骤,"主循环" 是嵌入式 / 实时应用的核心概念 ------ 无限循环执行核心业务,直到退出指令;- (核心业务逻辑):强调这是程序的核心功能(人脸检测 + 情绪分类 + 可视化),区别于之前的 "模型加载 / 硬件初始化 / 预处理" 等准备工作;- 等号=====:格式分隔符,提升可读性。
# app.need_exit():检测退出指令(如硬件按键/终端指令),优雅退出程序 - app.need_exit()app模块的核心方法,返回True/False;- 检测退出指令:说明该方法的作用 ------ 监听硬件退出键(如 MaixCAM 的按键)、终端 Ctrl+C、系统关机信号;- (如硬件按键/终端指令):举例退出指令的来源;- 优雅退出程序:解释 "非暴力退出"------ 程序退出前会自动释放摄像头 / NPU / 显示屏资源,避免硬件异常。
# 读取摄像头一帧画面(返回 image.Image 对象) - 读取摄像头一帧画面cam.read()的核心作用 ------ 从摄像头帧缓冲区读取一张实时图像;- (返回 image.Image 对象):说明返回值类型,后续所有图像处理(检测 / 裁剪 / 绘制)都基于该对象。
# 初始化临时变量 - 初始化临时变量:在每次循环(每帧画面)中重置变量,避免上一帧的数据残留;- 临时变量:仅在当前帧有效,下一帧会重新初始化。
# 存储每个人脸的情绪分类结果 解释results列表的作用 ------ 按顺序存储每个有效人脸的情绪分类结果(如[[(0,0.9),(1,0.1)], [(1,0.8),(0,0.2)]])。
# 存储有效人脸的索引(过滤裁剪失败的人脸) - 存储有效人脸的索引:解释idxes列表的作用 ------ 记录 "裁剪成功的人脸" 在objs(检测到的所有人脸)中的索引;- (过滤裁剪失败的人脸):说明目的 ------ 比如人脸框超出画面导致裁剪失败,该人脸会被过滤,不参与后续分类 / 绘制。
# 存储第一个人脸的标准化裁剪图(放大显示) 解释img_std_first变量的作用 ------ 保存第一个有效人脸的裁剪图(适配分类模型尺寸),用于在屏幕左上角放大显示,方便查看细节。
# 执行人脸检测:返回符合阈值的所有人脸框 - 执行人脸检测detector.detect()的核心作用 ------ 对当前帧图像执行 YOLOv8 人脸检测;- 返回符合阈值的所有人脸框:说明返回值是 "满足置信度 / IOU 阈值" 的人脸框列表,过滤低置信度的误检框。
# conf_th:置信度阈值;iou_th:IOU阈值;sort=1:按置信度从高到低排序 - conf_th:confidence threshold(置信度阈值),过滤置信度 < 该值的人脸框(如 0.5,仅保留置信度≥50% 的人脸);- iou_th:IOU threshold(交并比阈值),用于 NMS(非极大值抑制),过滤重叠度高的重复人脸框;- sort=1:排序规则,1 表示 "按置信度从高到低排序",0 表示不排序;- 补充:这三个参数是目标检测的核心后处理参数,确保检测结果精准。
# 计数:有效人脸数量 解释count变量的作用 ------ 统计当前帧中 "裁剪成功的有效人脸数",用于控制最大人脸数(max_face_num)。
# 遍历每一个检测到的人脸 说明for i, obj in enumerate(objs)的作用 ------ 逐个处理检测到的每个人脸框。
# 裁剪并标准化人脸:适配情绪分类模型的输入尺寸 - 裁剪并标准化人脸landmarks_detector.crop_image()的核心作用 ------ 从原始图中裁剪出人脸区域,并缩放到分类模型要求的尺寸(如 48x48);- 适配情绪分类模型的输入尺寸:说明裁剪的最终目的 ------ 分类模型要求固定尺寸输入,原始人脸框大小不一,需标准化。
# 参数:原始图、人脸框坐标、关键点、模型输入宽/高、裁剪缩放比例 逐一对crop_image的参数说明,方便理解每个参数的含义。
# 过滤裁剪失败的人脸(如人脸框超出画面) 说明if img_std:的作用 ------crop_image裁剪失败时返回None,此处过滤掉这些无效人脸,避免后续代码报错。
# 转换为灰度图:情绪分类模型要求输入灰度图(减少计算量) - 转换为灰度图img_std.to_format(...)的作用 ------ 将 RGB 图转为单通道灰度图;- 情绪分类模型要求输入灰度图:说明转换的必要性(模型训练时用灰度图,输入需匹配);- (减少计算量):补充优势 ------ 灰度图每个像素 1 字节,RGB 图 2/3 字节,减少 NPU 计算量,提升帧率。
# 执行情绪分类:softmax=True 输出 0-1 概率值 - 执行情绪分类classifier.classify()的核心作用 ------ 对标准化灰度人脸图执行情绪分类推理;- softmax=True 输出 0-1 概率值:说明参数作用 ------Softmax 归一化后,所有情绪的置信度之和为 1,直观展示概率。
# 保存结果和索引 说明results.append(res)idxes.append(i)的作用 ------ 将有效人脸的分类结果和对应索引保存,后续绘制时匹配。
# 保存第一个人脸的标准化裁剪图(用于放大显示) 说明if i == 0: img_std_first = img_std的作用 ------ 仅保存第一个有效人脸的裁剪图,用于左上角放大显示。
# 有效人脸数+1 说明count += 1的作用 ------ 统计有效人脸数量,用于控制最大人脸数。
# 达到最大人脸数则停止遍历(提升速度) - 达到最大人脸数则停止遍历:说明if max_face_num >0 and count >= max_face_num: break的作用;- (提升速度):补充优势 ------ 限制处理的人脸数(如最多处理 5 个人脸),避免人脸过多导致帧率暴跌。
# ===================== 6. 可视化结果(绘制到画面) ===================== 标注这是程序第 6 个步骤,核心是 "将检测 / 分类结果绘制到图像上,方便可视化查看"。
# 遍历每个有效人脸的情绪结果 说明for i, res in enumerate(results)的作用 ------ 逐个处理每个有效人脸的分类结果,进行绘制。
# 处理第一个人脸:放大显示裁剪图 + 所有情绪得分条 说明if i == 0 and img_std_first:的作用 ------ 仅对第一个人脸做 "放大显示 + 所有情绪得分条",避免画面杂乱。
# 在屏幕左上角绘制第一个人脸的裁剪图(坐标 0,0) 说明img.draw_image(0, 0, img_std_first)的作用 ------ 将裁剪图绘制到图像的左上角(x=0,y=0)。
# 遍历所有情绪标签,绘制标签文字 + 得分条 说明内层循环的作用 ------ 为第一个人脸绘制所有情绪的标签和对应的得分条(直观展示所有情绪的概率)。
# 计算文字绘制位置:裁剪图下方,每行间隔 16 像素(避免重叠) 说明text_y = img_std_first.height() + idx *16的作用 ------ 文字绘制在裁剪图下方,每行间隔 16 像素(字体高度),避免重叠。
# 绘制情绪标签文字(白色) 说明img.draw_string(...)的作用 ------ 绘制情绪标签文字(如 happy/angry),颜色为白色。
# 绘制得分条:绿色(≥阈值)/红色(<阈值),实心填充(-1) - 绘制得分条img.draw_rect(...)的作用 ------ 用矩形表示情绪概率(宽度 = 概率 × 最大得分条宽度);- 绿色(≥阈值)/红色(<阈值):说明颜色规则,直观区分高 / 低置信度;- 实心填充(-1):解释draw_rect最后一个参数 -------1 表示实心矩形,正数表示线宽。
# 绘制概率数值(红色,保留1位小数) 说明img.draw_string(...)的作用 ------ 在得分条右侧绘制概率值(如 0.9),保留 1 位小数,简洁易读。
# 处理所有人脸:绘制人脸框 + 主要情绪标签 说明后续代码的作用 ------ 对所有有效人脸,绘制人脸框和最可能的情绪标签(核心可视化信息)。
# 确定人脸框颜色:主要情绪置信度≥0.5为绿色,否则红色 说明color变量的赋值规则 ------ 用颜色区分置信度高低,直观展示识别结果是否可靠。
# 获取当前人脸的检测框 说明obj = objs[idxes[i]]的作用 ------ 通过idxes索引匹配到原始检测的人脸框,用于绘制。
# 绘制人脸框(线宽1像素) 说明img.draw_rect(...)的作用 ------ 绘制人脸框,线宽 1 像素(避免过粗遮挡画面)。
# 绘制主要情绪标签+概率(如"happy: 0.9") 说明img.draw_string(...)的作用 ------ 在人脸框左上角绘制最可能的情绪标签和概率,方便查看。
# 显示最终画面到屏幕 说明disp.show(img)的作用 ------ 将绘制完成的图像显示到硬件屏幕上。
# 程序退出时自动释放硬件资源(maixVision 内部已封装,无需手动处理) 说明程序退出时的资源管理 ------maixVision 框架会自动释放摄像头 / NPU / 显示屏资源,新手无需手动调用close()
相关推荐
FPGA小迷弟1 小时前
FPGA工程师面试题汇总(二)
学习·fpga开发·verilog·fpga
arvin_xiaoting2 小时前
OpenClaw学习总结_I_核心架构_9:Multi-Agent详解
网络·学习·架构·系统架构·ai agent·multi-agent·openclaw
倾心琴心2 小时前
【agent辅助pcb routing coding学习】实践7 length matching 算法学习
学习·算法·agent·pcb·routing
weiabc3 小时前
今日C/C++学习笔记20260223
c语言·c++·学习
我的xiaodoujiao3 小时前
3、API 接口自动化测试详细图文教程学习系列3--相关Python基础知识2
python·学习·测试工具·pytest
~光~~3 小时前
【嵌入式linux学习】0_3位运算整理
linux·学习
hssfscv3 小时前
软件设计师下午题二 E-R图
java·笔记·学习
RSFeegg4 小时前
【AI Agent 学习笔记task2】Day3 Hello-Agents 第二章:智能体发展史深度解读
人工智能·笔记·学习
计算机安禾5 小时前
【数据结构与算法】第1篇:为什么要学习数据结构与算法?专栏导学
c语言·开发语言·c++·学习·算法·visual studio code·visual studio