在PC和树莓派上部署 YOLOv10 做检测

人工智能 机器学习
在本文中,我测试了最新的(在撰写本文时)YOLO v10模型,该模型于2024年5月发布,结果很有趣。

计算机视觉可以是不同规模的机器学习应用的重要组成部分,从价值20,000美元的特斯拉机器人或自动驾驶汽车到智能门铃和吸尘器。这也是一个具有挑战性的任务,因为与云基础设施相比,在“真实”的边缘设备上,硬件规格通常更加受限。

YOLO(You Only Look Once,你只需看一次)是一个流行的目标检测库;它的第一版是在2015年制作的。YOLO对于嵌入式设备特别有趣,因为它几乎可以在任何地方运行;不仅有Python版本,还有C++(ONNX和OpenVINO)和Rust版本可用。一年前,我在树莓派4上测试了YOLO v8。现在,许多事情都发生了变化——新的树莓派5已经可用,而且更新的YOLO v10也已经发布。因此,我期望在新硬件上的新模型能够更快、更精确地工作。

本文中介绍的代码是跨平台的,所以没有树莓派的读者也可以在Windows、Linux或OS X电脑上运行它。

树莓派

对于可能从未听说过树莓派的人来说,让我们做一个简短的介绍。树莓派是一个小型信用卡大小的单板计算机,拥有4-8GB的RAM,并且能够运行完整的Linux版本:

树莓派小巧、安静且相对便宜,价格约为100美元。它还有很多端口(USB、GPIO、SPI/I2C、HDMI等)与不同的硬件通信。树莓派不仅被业余爱好者广泛使用,而且在工业中也有应用(树莓派计算模块专门为嵌入式应用设计)。这就是为什么看到我们可以使用最新的YOLO模型在最新的树莓派上获得什么样的性能是很有趣的。

安装

要在树莓派上运行YOLO,我将使用Ubuntu 64位。这是最简单的方式,因为Ubuntu不仅是最受欢迎的Linux发行版,而且也是官方认证适用于树莓派的。64位的Raspbian操作系统也应该可以工作,但在上面安装最新的库和框架可能具有挑战性。上次我尝试时,很多库和组件都过时了,而且apt仓库中没有最新版本。32位操作系统根本不支持Python YOLO版本,因为PyTorch(依赖项之一)不再支持32位架构。

在编写代码之前,让我们准备树莓派上的虚拟环境(这里,我使用“pi”作为树莓派用户的默认名称):

mkdir /home/pi/Documents/YOLO
cd /home/pi/Documents/YOLO
python3 -m venv yolo
source yolo/bin/activate

现在,我们准备安装所需的库:

sudo apt install libgl1
pip3 install opencv-python ultralytics supervision

不同的YOLO模型可用,我们可以从GitHub下载它们。我将使用YOLO v10 Large (x)、Medium (m)和Nano (n)模型:

wget https://github.com/THU-MIG/yolov10/releases/download/v1.0/yolov10n.pt
wget https://github.com/THU-MIG/yolov10/releases/download/v1.0/yolov10m.pt
wget https://github.com/THU-MIG/yolov10/releases/download/v1.0/yolov10x.pt

基本使用

当模型加载后,我们可以使用Python。要获得结果,我们只需要几行代码:


from ultralytics import YOLO


model = YOLO("yolov10m.pt")
results = model.predict("image.jpg",
                        save=False, save_txt=False,
                        verbose=False, conf=0.75)
results[0].show()

在这里,我指定了75%的置信度阈值。库为我们做了所有必要的工作,在屏幕上显示了注释后的图像。输出看起来像这样:

我们还可以得到文本形式的数据,这对于没有屏幕的“无头”系统可能有用:

model = YOLO("yolov10m.pt")
results = model.predict("image.jpg",
                        save=False, save_txt=False,
                        verbose=False, conf=0.75)

boxes = results[0].boxes
confidence, class_ids = boxes.conf, boxes.cls.int()
rects = boxes.xyxy.int()
for ind in range(boxes.shape[0]):
    print(model.names[class_ids[ind].item()],
          confidence[ind].item(),
          rects[ind].tolist())

在那种情况下,输出看起来像这样:

car 0.9247599244117737 [561, 311, 719, 420]
car 0.9067108035087585 [464, 303, 554, 380]
car 0.9027121663093567 [402, 300, 481, 367]
car 0.8614686727523804 [524, 310, 592, 396]
bicycle 0.8476000428199768 [181, 321, 241, 400]
person 0.8029575347900391 [71, 271, 126, 421]
person 0.7965097427368164 [186, 278, 237, 381]
bicycle 0.7882957458496094 [111, 330, 156, 414]

自定义注释

正如我们从前面的示例中看到的,results[0].show()方法正在做添加框架和标签到输出图像所需的工作。在Supervision库的帮助下,我们可以使用更复杂的自定义注释:

import supervision as sv


img = cv2.imread('image.jpg')
results = model.predict(img, ...)

detections = sv.Detections.from_ultralytics(results[0])
# Add Boxes
sv.BoxCornerAnnotator(thickness=2).annotate(
    scene=img,
    detections=detections
)
# Add Labels
labels = []
for ind, class_id in enumerate(detections.class_id):
    labels.append(f"{model.model.names[class_id]}: {detections.confidence[ind]:.2f}")

sv.LabelAnnotator().annotate(
    scene=img,
    detections=detections,
    labels=labels
)

# Show
cv2.imshow("Image", img_out)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里,我首先创建了一个标签列表,然后使用了LabelAnnotator和BoxCornerAnnotator类在图像上绘制结果。输出看起来像这样:

摄像头流

在前面的示例中,我使用了一个静态的JPEG图像。这对于测试很好,但在实际应用中,来自USB摄像头的实时流可能更有用。

我们可以使用OpenCV轻松获取摄像头流,并使用与之前相同的代码:

def predict_and_annotate(model: YOLO, img: Any):
    """ Predict the labels and return the annotated image """
    results = model.predict(source=img,
                            save=False, save_txt=False, verbose=False,
                            conf=0.75)
    detections = sv.Detections.from_ultralytics(results[0])

    ...

    img = img.copy()    
    sv.LabelAnnotator().annotate(
        scene=img,
        detections=detections,
        labels=labels
    )
    return img


# Run the camera stream
model = YOLO("yolov10m.pt")

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
while True:
    ret, frame = cap.read()
    frame = predict_and_annotate(model, frame)

    cv2.imshow("WebCam", frame)

    if cv2.waitKey(30) == 27: # Stop with Escape key
        break

cap.release()
cv2.destroyAllWindows()

显然,除了cv2.imshow调用之外,还可以使用其他数据处理。

结果

最后,我们拥有了所有需要的代码,是时候看看结果了!正如文章开头所写的,在过去的一年中,有两件事发生了变化:发布了新的YOLO v10模型,并且新的树莓派5也变得可用。因此,分别检查这些因素是有意义的。

准确性

为了比较准确性,我使用相同的图像运行了YOLO v8和v10 Medium模型:

正如我们所看到的,结果几乎相同。然而,YOLO v10模型错过了一个被v8检测到的人。显然,一张图片不足以作为“基准”,读者欢迎使用自己的数据进行更多测试。

性能

首先,比较YOLO v10与v8的性能很有趣。正如YOLOv10论文中所写,“我们从效率和准确性的角度全面优化了YOLO的各种组件”,所以我期望新模型更快。树莓派没有GPU,所以我在桌面上进行了这个测试:

确实,YOLO v10稍微(5-15%)更快,这是一个不错的改进。其次,看看YOLO v10模型(Nano、Medium和X-Large)在不同版本的树莓派上的表现也很有趣:

结果很有趣。确实,树莓派5比树莓派4快了2倍以上。在树莓派5上,使用最小的Nano模型,单张图像处理大约需要0.6秒。然而,这台微型计算机与全尺寸桌面PC相比,计算能力仍然要小得多。

结论

在本文中,我测试了最新的(在撰写本文时)YOLO v10模型,该模型于2024年5月发布,结果很有趣。

首先,与一年前可用的新YOLO v10模型相比,速度略快,这是一个不错的改进。其次,树莓派5也比前一个模型更快,我们可以使用最小的“Nano”模型从摄像头流中实现大约0.6秒每张图像的性能。一般来说,0.6秒的处理时间还不错。树莓派是一台小型且低成本的计算机;它不足以用于实时应用,如街道导航,但可以足够好,例如,用于检测停车场上的汽车或通过每分钟拍照来估计商店中的人数。如果我们想要更快的速度,可以使用像NVIDIA Jetson这样的板子;它们更强大,但也更昂贵。

责任编辑:赵宁宁 来源: 小白玩转Python
相关推荐

2021-12-21 21:00:23

Ansible树莓派语音助手

2024-10-07 10:12:50

2023-05-09 10:16:42

人工智能python版本

2024-05-29 09:25:38

2024-05-27 09:27:02

2019-05-06 13:52:00

树莓派Ubuntu MATEUbuntu

2024-07-03 09:39:52

2024-10-14 17:43:05

2024-06-17 13:39:45

2020-06-01 20:00:28

树莓派TT-RSSLinux

2024-09-09 16:35:10

YOLO模型

2021-03-19 13:00:39

树莓派Linux

2024-05-28 14:46:00

2009-07-31 09:08:16

Intel部署Wind

2018-11-08 09:00:31

树莓派WordPressLinux

2009-06-01 11:23:08

Glassfish部署Glassfish

2019-07-31 09:32:06

2020-03-31 12:50:34

树莓派K3sKubernetes集

2017-04-24 17:00:26

Linux树莓派Fedora 25

2017-11-23 08:30:27

数据库Postgres树莓派
点赞
收藏

51CTO技术栈公众号