使用树莓派4进行yolov5推理

官方ISO下载镜像

https://www.raspberrypi.com/software/

无屏幕配置

sudo nmap -sS -p 22 192.168.123.0/24 --open

输出

Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-23 15:42 +0800
Nmap scan report for 192.168.123.21
Host is up (0.076s latency).

PORT   STATE SERVICE
22/tcp open  ssh
MAC Address: E4:5F:01:23:F0:E0 (Raspberry Pi Trading)

Nmap scan report for 192.168.123.18
Host is up (0.000080s latency).

PORT   STATE SERVICE
22/tcp open  ssh

Nmap done: 256 IP addresses (19 hosts up) scanned in 13.03 seconds
ssh pi@192.168.123.21

物理网络直连,一根网线

编辑文件/etc/dhcpcd.conf

末尾添加

interface eth0
static ip_address=169.254.17.233/16

进行连接

ssh pi@169.254.17.233
pi@169.254.17.233's password:

进入系统:

Linux RIP 6.12.47+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.12.47-1+rpt1 (2025-09-16) aarch64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Mar 23 15:59:03 2026 from 169.254.17.238
pi@RIP:~ $

配置软件源

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bk
sudo nano /etc/apt/sources.list

编辑sources.list

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie main contrib non-free non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ trixie-updates main contrib non-free non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security trixie-security main contrib non-free non-free-firmware

进行更新

sudo apt update

配置Yolo

当前环境:

python --version
Python 3.13.5

lsb_release  -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 13 (trixie)
Release:	13
Codename:	trixie

name -a
Linux RIP 6.12.47+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.12.47-1+rpt1 (2025-09-16) aarch64 GNU/Linux

安装依赖

pip install opencv-python-headless

简单推理:

result

import cv2
import numpy as np
import onnxruntime as ort

# ========== 参数 ==========
MODEL_PATH = "yolov5n.onnx"
IMG_SIZE = 640

# ========== 加载模型 ==========
session = ort.InferenceSession(MODEL_PATH)

input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name

# ========== 预处理 ==========
def preprocess(img):
    img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
    img = img[:, :, ::-1]  # BGR -> RGB
    img = img.astype(np.float32) / 255.0
    img = np.transpose(img, (2, 0, 1))  # HWC -> CHW
    img = np.expand_dims(img, axis=0)
    return img

# ========== NMS ==========
def nms(boxes, scores, iou_threshold=0.5):
    idxs = scores.argsort()[::-1]
    keep = []
    while len(idxs) > 0:
        i = idxs[0]
        keep.append(i)
        if len(idxs) == 1:
            break
        ious = compute_iou(boxes[i], boxes[idxs[1:]])
        idxs = idxs[1:][ious < iou_threshold]
    return keep

def compute_iou(box, boxes):
    x1 = np.maximum(box[0], boxes[:, 0])
    y1 = np.maximum(box[1], boxes[:, 1])
    x2 = np.minimum(box[2], boxes[:, 2])
    y2 = np.minimum(box[3], boxes[:, 3])

    inter = np.maximum(0, x2 - x1) * np.maximum(0, y2 - y1)
    area1 = (box[2]-box[0])*(box[3]-box[1])
    area2 = (boxes[:, 2]-boxes[:, 0])*(boxes[:, 3]-boxes[:, 1])

    return inter / (area1 + area2 - inter + 1e-6)

# ========== 推理 ==========
img = cv2.imread("test.jpg")
input_tensor = preprocess(img)

outputs = session.run([output_name], {input_name: input_tensor})[0]

# YOLOv5 输出格式:[1, N, 85]
pred = outputs[0]

boxes = pred[:, :4]
scores = pred[:, 4]
class_scores = pred[:, 5:]

# 过滤低置信度
mask = scores > 0.5
boxes = boxes[mask]
scores = scores[mask]
class_ids = np.argmax(class_scores[mask], axis=1)

# NMS
keep = nms(boxes, scores)

# 画框
for i in keep:
    x, y, w, h = boxes[i]
    x1 = int(x - w/2)
    y1 = int(y - h/2)
    x2 = int(x + w/2)
    y2 = int(y + h/2)

    cv2.rectangle(img, (x1,y1), (x2,y2), (0,255,0), 2)
    cv2.putText(img, str(class_ids[i]), (x1,y1-10),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2)

cv2.imwrite("result.jpg", img)
print("done")

comment: