【Arduino UNO Q】 边缘 AI 视觉部署方案:物体识别

本文介绍了 Arduino UNO Q 开发板结合 OpenCV 和 YOLO 算法实现物体识别的项目设计。

项目介绍

Arduino UNO Q 开发板结合 OpenCV 与 YOLOv5n 算法实现快速轻量化的物体识别。

  • 准备工作:硬件连接、软件更新等;
  • 环境搭建:安装 OpenCV 库、所需软件包等;
  • YOLO:使用 OpenCV 和 YOLOv5n 算法 onnx 模型实现物体识别;

准备工作

包括硬件连接、系统安装、软件更新等。

详见:Arduino UNO Q 介绍、环境搭建、工程测试 .

硬件连接

这里采用 SSH 远程控制,使用 Type-C 数据线供电并 WiFi 联网即可。

在这里插入图片描述

软件更新

更新软件包

sudo apt update
sudo apt upgrade

环境搭建

  • 安装 OpenCV 和 opencv-data 软件包;

    sudo apt install python3-opencv
    sudo apt install opencv-data
    
  • 执行如下指令验证

python3 -c "import cv2,sys;print(cv2.__version__,sys.version)"

终端打印 opencv 版本号

在这里插入图片描述

YOLO

下载预训练模型

wget https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5n.onnx
wget https://github.com/pjreddie/darknet/blob/master/data/coco.names

使用 OpenCV 自带的 DNN 工具读取 yolov5n.onnx 模型文件,加载目标图片并弹窗显示检测结果。

流程图

开始

解析参数

加载模型

读取图片

预处理

后处理

画框

弹窗显示

按键退出

结束

代码

终端执行 touch or_yolo.py 新建程序文件,添加如下代码

#!/usr/bin/env python3
import cv2
import numpy as np
import argparse

# input image path
parser = argparse.ArgumentParser()
parser.add_argument('--image_path', default='./img/desktop.jpg', help='输入指令 python3 or_yolo.py --image_path ./img/desktop.jpg')
args = parser.parse_args()

# ========== Parameters ==========
INPUT_WIDTH  = 640
INPUT_HEIGHT = 640
SCORE_THRESHOLD   = 0.5
NMS_THRESHOLD     = 0.45
CONFIDENCE_THRESHOLD = 0.45

FONT_FACE  = cv2.FONT_HERSHEY_SIMPLEX
FONT_SCALE = 0.7
THICKNESS  = 1

BLACK  = (0,0,0)  # BGR
BLUE   = (255,178,50)
YELLOW = (0,255,255)
RED    = (0,0,255)
GREEN  = (0,255,0)
# ======================================

def draw_label(im, label, left, top):
    """绿色填充标签 + 黑色文字"""
    (tw, th), _ = cv2.getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS)
    cv2.rectangle(im, (left, top - th - 6), (left + tw + 4, top), GREEN, cv2.FILLED)
    cv2.putText(im, label, (left + 2, top - 2), FONT_FACE, FONT_SCALE, BLACK, THICKNESS, cv2.LINE_AA)

def pre_process(im, net):
    blob = cv2.dnn.blobFromImage(im, 1/255., (INPUT_WIDTH, INPUT_HEIGHT), (0,0,0), swapRB=True, crop=False)
    net.setInput(blob)
    out_layers = net.getUnconnectedOutLayersNames()
    return net.forward(out_layers)

def post_process(im, outs):
    class_ids, confidences, boxes = [], [], []
    rows = outs[0].shape[1]
    x_factor = im.shape[1] / INPUT_WIDTH
    y_factor = im.shape[0] / INPUT_HEIGHT

    for r in range(rows):
        row = outs[0][0][r]
        conf = row[4]
        if conf < CONFIDENCE_THRESHOLD: continue

        classes_scores = row[5:]
        class_id = int(np.argmax(classes_scores))
        if classes_scores[class_id] < SCORE_THRESHOLD: continue

        cx, cy, w, h = row[0], row[1], row[2], row[3]
        left   = int((cx - w/2) * x_factor)
        top    = int((cy - h/2) * y_factor)
        width  = int(w * x_factor)
        height = int(h * y_factor)

        boxes.append([left, top, width, height])
        confidences.append(float(conf))
        class_ids.append(class_id)

    indices = cv2.dnn.NMSBoxes(boxes, confidences, CONFIDENCE_THRESHOLD, NMS_THRESHOLD)
    for i in indices:
        b = boxes[i]
        left, top, w, h = b[0], b[1], b[2], b[3]
        cv2.rectangle(im, (left, top), (left + w, top + h), GREEN, 2*THICKNESS)
        label = f"{classes[class_ids[i]]}:{confidences[i]:.2f}"
        draw_label(im, label, left, top - 2)
        print(f"{label}  |  bbox=({left},{top},{w},{h})")
    return im

# ================= main =================
classes = open("./model/coco.names").read().strip().split('\n')
net = cv2.dnn.readNet("./model/yolov5n.onnx")
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)

frame = cv2.imread(args.image_path)
assert frame is not None, "目标不存在,请检查图片路径"

outs   = pre_process(frame, net)
result = post_process(frame, outs)

# 效率信息
t, _ = net.getPerfProfile()
label = f"Inference: {t*1000/cv2.getTickFrequency():.2f} ms"
cv2.putText(result, label, (20, 40), FONT_FACE, FONT_SCALE, RED, THICKNESS, cv2.LINE_AA)
print(label)

cv2.namedWindow('YOLOv5n', cv2.WINDOW_NORMAL)
cv2.imshow("YOLOv5n", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

保存代码。

效果

  • 终端运行指令 python3 or_yolo.py --image_path ./img/desktop.jpg ,打印结果

    在这里插入图片描述

  • 弹窗显示结果,按任意键关闭窗口;

    效果如下

    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结

本文介绍了 Arduino UNO Q 开发板结合 OpenCV 与 YOLO 算法、ONNX 模型实现物体识别,包括OpenCV 部署、YOLO 算法、ONNX 模型获取、关键代码和工程测试,为相关产品在边缘 AI 视觉应用的快速开发设计提供了参考。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐