2,852
社区成员




测试手机型号:Redmi K60 Pro
处理器:第二代骁龙8移动--8gen2
运行内存:8.0GB ,LPDDR5X-8400,67.0 GB/s
摄像头:前置16MP+后置50MP+8MP+2MP
AI算力:NPU 48Tops INT8 && GPU 1536ALU x 2 x 680MHz = 2.089 TFLOPS
提示:任意手机均可以,性能越好的手机运行速度越快
APP:AidLux2.0
系统环境:Ubuntu 20.04.3 LTS
提示:AidLux登录后代码运行更流畅,在代码运行时保持AidLux APP在前台运行,避免代码运行过程中被系统回收进程,另外屏幕保持常亮,一般息屏后一段时间,手机系统会进入休眠状态,如需长驻后台需要给APP权限。
这段代码实现了一个基于深度学习的实时人像分割应用,它通过摄像头捕获视频流,利用轻量级推理引擎 Aidlite 运行人像分割模型,实时识别画面中的人物区域,并将人物与背景以视觉上的蓝色轮廓效果进行区分。下面详细介绍其功能和工作流程:
视频流捕获
VideoCapture
接口打开前置摄像头(设备 ID=1),持续读取视频帧。人像分割模型推理
.nb
格式,由 Aidlite 优化)。实时图像处理
cv2.addWeighted
),将蓝色半透明轮廓叠加到原始画面的人物区域上。性能监控与显示
Aidlite 是一个轻量级的深度学习推理引擎,专为嵌入式设备和移动设备优化。它具有以下特点:
在这段代码中,Aidlite 被配置为使用 PaddlePaddle 框架训练的模型,并通过 CPU 进行推理。
2. 计算机视觉库 - OpenCV (cv2)
OpenCV 是一个强大的计算机视觉库,在这段代码中主要用于:
cv2.VideoCapture
获取摄像头视频流cv2.resize
)、翻转 (cv2.flip
)cv2.addWeighted
实现半透明效果cv2.imshow
显示处理后的图像3. AI 模型功能
代码中使用的 AI 模型是一个人像分割模型,它能够:
这个代码示例可以应用于以下场景:
通过调整transfer
函数,可以实现更多样化的视觉效果,如背景模糊、背景替换、动态滤镜等。
import cv2
import time
from time import sleep
import remi
import os
import sys
import numpy as np
import aidlite
def transfer(image, mask):
"""
将分割掩码与原始图像融合,创建半透明效果
参数:
image: 原始图像,BGR格式
mask: 分割掩码,单通道二值图像(0表示背景,255表示人物)
返回:
融合后的图像
"""
# 调整掩码大小以匹配原始图像
mask = cv2.resize(mask, (image.shape[1], image.shape[0]))
# 创建三通道掩码图像(只在蓝色通道填充值)
mask_n = np.zeros_like(image)
mask_n[:, :, 0] = mask # 将掩码值赋给蓝色通道,产生蓝色轮廓效果
# 图像融合参数(alpha透明度)
alpha = 0.7
beta = (1.0 - alpha)
# 加权融合原始图像和掩码图像
dst = cv2.addWeighted(image, alpha, mask_n, beta, 0.0)
return dst
# 模型输入输出参数配置
w = 513 # 模型输入宽度
h = 513 # 模型输入高度
inShape = [[1, 3, 513, 513]] # 输入张量形状: [批次大小, 通道数, 高度, 宽度]
outShape = [[1, w, h]] # 输出张量形状: [批次大小, 高度, 宽度]
model_path = "models/model.nb" # 模型文件路径(.nb格式为Aidlite优化后的模型格式)
# ------------------------ Aidlite推理引擎初始化 ------------------------
# 创建Aidlite模型实例
model = aidlite.Model.create_instance(model_path)
if model is None:
print("Create model failed !")
# 设置模型输入输出数据类型和形状
model.set_model_properties(inShape, aidlite.DataType.TYPE_FLOAT32, outShape, aidlite.DataType.TYPE_INT64)
# 创建配置实例,设置模型框架类型和加速类型
config = aidlite.Config.create_instance()
config.framework_type = aidlite.FrameworkType.TYPE_PADDLE # 模型基于PaddlePaddle框架训练
config.accelerate_type = aidlite.AccelerateType.TYPE_CPU # 使用CPU进行推理(也支持GPU、NPU等)
# 构建并初始化解释器
fast_interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
if fast_interpreter is None:
print("build_interpretper_from_model_and_config failed !")
result = fast_interpreter.init()
if result != 0:
print("interpreter init failed !")
result = fast_interpreter.load_model()
if result != 0:
print("interpreter load model failed !")
print("model load success!")
# ------------------------ 视频流处理与推理 ------------------------
# 尝试打开前置摄像头(设备ID为1)
camId = 1
opened = False
while not opened:
# 使用mipi接口打开摄像头(适用于某些嵌入式设备)
cap = cv2.VideoCapture(camId, device='mipi')
if cap.isOpened():
opened = True
else:
print("open camera failed")
cap.release()
time.sleep(0.5)
# 主循环: 捕获视频帧并进行实时处理
while True:
ret, frame = cap.read()
if not ret:
continue
if frame is None:
continue
# 如果使用前置摄像头,水平翻转图像以获得自然的镜像效果
frame = cv2.flip(frame, 1)
# 图像预处理: 调整大小并转换为模型输入格式
img = cv2.resize(frame, (w, h))
input = img.astype(np.float32) # 转换为浮点类型
input = np.transpose(input, (2, 0, 1)) # 调整通道顺序: [H,W,C] -> [C,H,W]
print('input', input.shape)
# 设置输入数据到推理引擎
print('paddle: start set')
result = fast_interpreter.set_input_tensor(0, input)
if result != 0:
print("interpreter set_input_tensor() failed")
# 记录推理开始时间
start_time = time.time()
print('bnn: start invoke')
# 执行模型推理
result = fast_interpreter.invoke()
if result != 0:
print("interpreter invoke() failed")
print('invoke end')
# 计算推理耗时并转换为毫秒
t = (time.time() - start_time)
print('elapsed_ms invoke:', t * 1000)
# 计算帧率并显示在画面上
lbs = 'Fps: '+ str(int(1 / t)) + " ~~ Time:" + str(t * 1000) + "ms"
# 获取模型输出结果
print('paddle: start get')
pred_0 = fast_interpreter.get_output_tensor(0, output_type=aidlite.DataType.TYPE_INT64)
if pred_0 is None:
print("sample : interpreter->get_output_tensor(0) failed !")
# 后处理: 重塑输出张量并创建二值人物掩码
pred0 = (pred_0).reshape(w, h)
# 将模型预测结果中类别为1的像素设为255(人物),其余设为0(背景)
person = np.where(pred0 == 1, 255, 0).astype(np.uint8)
# 将掩码与原始图像融合
dst = transfer(frame, person)
# 显示结果
cv2.imshow("", dst)
# 按 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
/opt/aidlux/app/aid-examples//portrait_seg