【“星睿O6”AI PC开发套件评测】物体识别
本文介绍了瑞莎星睿 O6 (Radxa Orion O6) 开发板结合 YOLO 模型实现物体识别的项目设计,包括通过 CPU 和 NPU 实现板端推理的相关流程。
项目介绍
- 准备工作:包括所需 Python 环境以及软件包的安装部署等;
- CPU 推理:使用 YOLOv5n 等轻量化 ONNX 模型实现物体识别的板端推理;
- NPU 推理:结合官方 NPU SDK 实现预训练模型导出、实现板端 NPU 对目标图片的物体识别。
ONNX
Open Neural Network Exchange (ONNX) 是一个开放的生态系统,为 AI 开发人员提供支持 随着项目的发展选择正确的工具。
ONNX 为 AI 模型(包括深度学习和传统 ML)提供开源格式。它定义了一个可扩展的计算图模型,以及内置运算符和标准的定义 数据类型。
详见:onnx/onnx: Open standard for machine learning interoperability .
YOLO
YOLO(You Only Look Once)是一种流行的目标检测算法,它以其快速和准确性而闻名。YOLO算法的核心思想是将目标检测问题转化为一个回归问题,通过一个单一的卷积神经网络(CNN)直接从输入图像预测边界框和类别概率。
YOLO 的主要优点是速度快,能够实时处理视频流。它还具有较强的通用性,能够迁移到新的领域。
YOLOv5n 代表了目标检测方法的进步,源于 Ultralytics 开发的 YOLOv5 模型的基础架构,调整优化了模型架构,从而在目标检测任务中实现了更高的精度-速度权衡。YOLOv5 为那些在研究和实际应用中寻求稳健解决方案的人们提供了高效的解决方案。
准备工作
主要包括硬件连接、系统安装、环境部署、模型下载等。
硬件连接
采用 SSH 远程登录操作,需连接电源供电、网线;
- 系统安装详见:【“星睿O6”AI PC开发套件评测】介绍、系统安装 .
库安装
- 执行指令
sudo apt install python3-opencv安装 OpenCV - 安装解析 ONNX 模型所需的 onnxruntime 库,终端执行
sudo apt install python3-pip
sudo pip3 install onnxruntime --break-system-packages模型下载
- 下载 CPU 推理所需的 ONNX 模型文件
wget https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5n.onnx- 下载 radxa 预编译完成的 yolov8_l.cix 模型文件
wget https://modelscope.cn/models/cix/ai_model_hub_24_Q4/resolve/master/models/ComputeVision/Object_Detection/onnx_yolov8_l/yolov8_l.cix体积约 40MB
CPU 推理
包括流程图、关键代码、效果演示等。
流程图
代码
终端执行 touch or_cpu.py 指令新建文件,并使用 nano 文本编辑器添加如下代码
#!/usr/bin/env python3
import cv2, numpy as np, onnxruntime as ort
from pathlib import Path
COCO_NAMES = ["person","bicycle","car","motorcycle","airplane","bus","train","truck","boat","traffic light",
"fire hydrant","stop sign","parking meter","bench","bird","cat","dog","horse","sheep","cow",
"elephant","bear","zebra","giraffe","backpack","umbrella","handbag","tie","suitcase","frisbee",
"skis","snowboard","sports ball","kite","baseball bat","baseball glove","skateboard","surfboard",
"tennis racket","bottle","wine glass","cup","fork","knife","spoon","bowl","banana","apple",
"sandwich","orange","broccoli","carrot","hot dog","pizza","donut","cake","chair","couch",
"potted plant","bed","dining table","toilet","tv","laptop","mouse","remote","keyboard","cell phone",
"microwave","oven","toaster","sink","refrigerator","book","clock","vase","scissors","teddy bear",
"hair drier","toothbrush"]
MODEL_PATH = "models/yolov5n.onnx"
IMG_PATH = "img/desktop.jpg"
# ---------- 1. 加载 FP16 模型 ----------
sess = ort.InferenceSession(MODEL_PATH, providers=['CPUExecutionProvider'])
in_name = sess.get_inputs()[0].name # 期望 tensor(float16)
out_name = sess.get_outputs()[0].name
# ---------- 2. 读图 ----------
img0 = cv2.imread(IMG_PATH)
if img0 is None: raise FileNotFoundError(IMG_PATH)
# ---------- 3. 预处理(FP16 + 640×640) ----------
blob = cv2.resize(img0, (640, 640))
blob = (blob.astype(np.float16) / 255.0).transpose(2, 0, 1)[None] # <- 关键:float16
# ---------- 4. 推理 ----------
outputs = sess.run([out_name], {in_name: blob})[0]
outputs = np.squeeze(outputs) # [25200,85]
# ---------- 5. 后处理 + 画框 ----------
boxes, scores, class_ids = [], [], []
for pred in outputs:
x, y, w, h, conf = pred[:5]
if conf < 0.25: continue
cls = int(np.argmax(pred[5:]))
scores.append(float(conf))
class_ids.append(cls)
# 映射回原图
x1 = int((x - w / 2) * img0.shape[1] / 640)
y1 = int((y - h / 2) * img0.shape[0] / 640)
x2 = int((x + w / 2) * img0.shape[1] / 640)
y2 = int((y + h / 2) * img0.shape[0] / 640)
boxes.append([x1, y1, x2 - x1, y2 - y1])
indices = cv2.dnn.NMSBoxes(boxes, scores, score_threshold=0.25, nms_threshold=0.45)
if indices is not None:
for i in indices.flatten():
x, y, w, h = boxes[i]
label = f"{COCO_NAMES[class_ids[i]]} {scores[i]:.2f}"
cv2.rectangle(img0, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(img0, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# ---------- 6. 弹窗 ----------
cv2.imshow("YOLOv5n-FP16-ORT", img0)
cv2.waitKey(0)
cv2.destroyAllWindows()保存代码。
效果
终端执行 python or_cpu.py ,弹窗显示推理后的图片
NPU 推理
包括流程图、关键代码、效果演示等。
加载预编译的 *.cix 格式模型文件;
python3 inference_npu.py --image_path ./test_data/ --model_path ./yolov8_l.cix流程图
代码
打开 inference_npu.py 文件,代码如下
import cv2
import numpy as np
import argparse
import os
import sys
from tqdm import tqdm
_abs_path = os.path.join(os.path.dirname(__file__), "../../../../")
sys.path.append(_abs_path)
from utils.tools import get_file_list
from utils.image_process import preprocess_object_detect_method1
from utils.object_detect_postprocess import postprocess_yolo, xywh2xyxy
from utils.draw import draw_coco as draw
from utils.NOE_Engine import EngineInfer
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--image_path",
default="test_data",
help="path to the image file",
)
parser.add_argument(
"--model_path",
default="yolov12_n.cix",
help="path to the quant model file",
)
parser.add_argument(
"--output_dir", default="./output", help="path to the result output"
)
parser.add_argument(
"--conf_thr",
type=float,
default=0.3,
help="Score threshould to filter the result.",
)
parser.add_argument(
"--nms_thr", type=float, default=0.45, help="NMS threshould to the object."
)
args = parser.parse_args()
return args
if __name__ == "__main__":
args = get_args()
os.makedirs(args.output_dir, exist_ok=True)
# Get list of images from the specified path
image_list = get_file_list(args.image_path)
model = EngineInfer(args.model_path)
image_list = get_file_list(args.image_path)
for img_name in tqdm(image_list):
# Preprocess the image for inference
src_shape, new_shape, show_image, data = preprocess_object_detect_method1(
img_name, target_size=(640, 640), mode="BGR"
)
# Run inference and get predictions
pred = model.forward(data.astype(np.float32))[0]
pred = np.reshape(pred, (84, 8400))
pred = np.transpose(pred, (1, 0))
# bboxes, conf, class_id
results = postprocess_yolo(pred, args.conf_thr, args.nms_thr)
if len(results) == 0:
output_path = os.path.join(args.output_dir,"npu_" + os.path.basename(img_name))
# Save the resulting image to the output directory
cv2.imwrite(output_path, show_image)
continue
bbox_xywh = results[:, :4]
bbox_xyxy = xywh2xyxy(bbox_xywh)
x_scale = src_shape[1] / new_shape[1]
y_scale = src_shape[0] / new_shape[0]
bbox_xyxy *= (x_scale, y_scale, x_scale, y_scale)
ret_img = draw(show_image, bbox_xyxy, results[:, 5], results[:, 4])
output_path = os.path.join(args.output_dir, "npu_" + os.path.basename(img_name))
# Save the resulting image to the output directory
cv2.imwrite(output_path, ret_img)
model.clean()终端执行 NPU 推理程序 python3 inference_npu.py ,输出推理结果
v) radxa@orion-o6:~/NOE/ai_model_hub/models/ComputeVision/Object_Detection/onnx_yolov8_l$ time python3 inference_npu.py --image_path ./test_data/ --model_path ./yolov8_l.cix
npu: noe_init_context success
npu: noe_load_graph success
Input tensor count is 1.
Output tensor count is 1.
npu: noe_create_job success
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 8.08it/s]
npu: noe_clean_job success
npu: noe_unload_graph success
npu: noe_deinit_context success
real 0m3.884s
user 0m3.391s
sys 0m0.400s结果保存在 output_npu 文件夹。
效果
- 将目标图片放置于
test_data文件夹,执行python3 inference_npu.py指令; - 打开
output_npu文件夹中输出的图片,识别结果被精准地框选出来;
- 更多场景应用举例
运动
骑行
小路
户外
路口
家居
总结
本文介绍了瑞莎星睿 O6 (Radxa Orion O6) 开发板结合 YOLO 模型实现物体识别的项目设计,包括通过 CPU 和 NPU 实现板端推理的相关流程,为相关产品在 AI 视觉领域的开发设计和快速应用提供了参考。