Skip to content

Commit 18a49dc

Browse files
d4l3kmalfet
andauthored
realtime_rpi: updated for raspberry pi 5 (#3601)
This updates the raspberry pi tutorial with the latest `picamera2` and Raspberry Pi 5. Test plan: manually ran instructions + code CI --------- Co-authored-by: Nikita Shulga <[email protected]>
1 parent 26936b3 commit 18a49dc

File tree

1 file changed

+68
-57
lines changed

1 file changed

+68
-57
lines changed

intermediate_source/realtime_rpi.rst

Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
Real Time Inference on Raspberry Pi 4 (30 fps!)
1+
Real Time Inference on Raspberry Pi 4 and 5 (40 fps!)
22
=================================================
33
**Author**: `Tristan Rice <https://github.com/d4l3k>`_
44

5-
PyTorch has out of the box support for Raspberry Pi 4. This tutorial will guide
6-
you on how to setup a Raspberry Pi 4 for running PyTorch and run a MobileNet v2
7-
classification model in real time (30 fps+) on the CPU.
5+
PyTorch has out of the box support for Raspberry Pi 4 and 5. This tutorial will guide
6+
you on how to setup a Raspberry Pi for running PyTorch and run a MobileNet v2
7+
classification model in real time (30-40 fps) on the CPU.
88

99
This was all tested with Raspberry Pi 4 Model B 4GB but should work with the 2GB
1010
variant as well as on the 3B with reduced performance.
1111

1212
.. image:: https://user-images.githubusercontent.com/909104/153093710-bc736b6f-69d9-4a50-a3e8-9f2b2c9e04fd.gif
1313

1414
Prerequisites
15-
~~~~~~~~~~~~~~~~
15+
---------------
1616

17-
To follow this tutorial you'll need a Raspberry Pi 4, a camera for it and all
17+
To follow this tutorial you'll need a Raspberry Pi 4 or 5, a camera for it and all
1818
the other standard accessories.
1919

2020
* `Raspberry Pi 4 Model B 2GB+ <https://www.raspberrypi.com/products/raspberry-pi-4-model-b/>`_
@@ -25,12 +25,12 @@ the other standard accessories.
2525
* SD card read/writer
2626

2727

28-
Raspberry Pi 4 Setup
29-
~~~~~~~~~~~~~~~~~~~~~~~
28+
Raspberry Pi Setup
29+
----------------------
3030

3131
PyTorch only provides pip packages for Arm 64bit (aarch64) so you'll need to install a 64 bit version of the OS on your Raspberry Pi
3232

33-
You can download the latest arm64 Raspberry Pi OS from https://downloads.raspberrypi.org/raspios_arm64/images/ and install it via rpi-imager.
33+
You'll need to install the `official rpi-imager <https://www.raspberrypi.com/software/>`_ to install Rasbperry Pi OS.
3434

3535
**32-bit Raspberry Pi OS will not work.**
3636

@@ -45,7 +45,12 @@ Time to put your sdcard in your Raspberry Pi, connect the camera and boot it up.
4545
.. image:: https://user-images.githubusercontent.com/909104/152869862-c239c980-b089-4bd5-84eb-0a1e5cf22df2.png
4646

4747

48-
Once that boots and you complete the initial setup you'll need to edit the ``/boot/config.txt`` file to enable the camera.
48+
Raspberry Pi 4 Config
49+
~~~~~~~~~~~~~~~~~~~~~~~~
50+
51+
If you're using a Raspberry Pi 4, you'll need some additional config changes. These changes are not required on Raspberry Pi 5.
52+
53+
Once the OS boots and you complete the initial setup you'll need to edit the ``/boot/config.txt`` file to enable the camera.
4954

5055
.. code:: toml
5156
@@ -55,21 +60,17 @@ Once that boots and you complete the initial setup you'll need to edit the ``/bo
5560
# This needs to be at least 128M for the camera processing, if it's bigger you can just leave it as is.
5661
gpu_mem=128
5762
58-
# You need to commment/remove the existing camera_auto_detect line since this causes issues with OpenCV/V4L2 capture.
59-
#camera_auto_detect=1
60-
61-
And then reboot. After you reboot the video4linux2 device ``/dev/video0`` should exist.
63+
And then reboot.
6264

63-
Installing PyTorch and OpenCV
64-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65+
Installing PyTorch and picamera2
66+
-------------------------------
6567

6668
PyTorch and all the other libraries we need have ARM 64-bit/aarch64 variants so you can just install them via pip and have it work like any other Linux system.
6769

6870
.. code:: shell
6971
70-
$ pip install torch torchvision torchaudio
71-
$ pip install opencv-python
72-
$ pip install numpy --upgrade
72+
$ sudo apt install -y python3-picamera2 python3-libcamera
73+
$ pip install torch torchvision --break-system-packages
7374
7475
.. image:: https://user-images.githubusercontent.com/909104/152874260-95a7a8bd-0f9b-438a-9c0b-5b67729e233f.png
7576

@@ -84,41 +85,49 @@ We can now check that everything installed correctly:
8485

8586

8687
Video Capture
87-
~~~~~~~~~~~~~~
88+
-------------------
8889

89-
For video capture we're going to be using OpenCV to stream the video frames
90-
instead of the more common ``picamera``. `picamera` isn't available on 64-bit
91-
Raspberry Pi OS and it's much slower than OpenCV. OpenCV directly accesses the
92-
``/dev/video0`` device to grab frames.
90+
Test the camera is working first, by running ``libcamera-hello`` in a terminal.
91+
92+
For video capture we're going to be using picamera2 to capture the video frames.
9393

9494
The model we're using (MobileNetV2) takes in image sizes of ``224x224`` so we
95-
can request that directly from OpenCV at 36fps. We're targeting 30fps for the
95+
can request that directly from picamera2 at 36fps. We're targeting 30fps for the
9696
model but we request a slightly higher framerate than that so there's always
9797
enough frames.
9898

9999
.. code:: python
100100
101-
import cv2
102-
from PIL import Image
101+
from picamera2 import Picamera2
102+
103+
picam2 = Picamera2()
104+
105+
# print available sensor modes
106+
print(picam2.sensor_modes)
103107
104-
cap = cv2.VideoCapture(0)
105-
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 224)
106-
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 224)
107-
cap.set(cv2.CAP_PROP_FPS, 36)
108+
config = picam2.create_still_configuration(main={
109+
"size": (224, 224),
110+
"format": "BGR888",
111+
}, display="main")
112+
picam2.configure(config)
113+
picam2.set_controls({"FrameRate": 36})
114+
picam2.start()
108115
109-
OpenCV returns a ``numpy`` array in BGR so we need to read and do a bit of
110-
shuffling to get it into the expected RGB format.
116+
To capture the frames we can call ``capture_image`` to return a ``PIL.Image``
117+
object that we can use with PyTorch.
111118

112119
.. code:: python
113120
114-
ret, image = cap.read()
115-
# convert opencv output from BGR to RGB
116-
image = image[:, :, [2, 1, 0]]
121+
# read frame
122+
image = picam2.capture_image("main")
123+
124+
# show frame for testing
125+
image.show()
117126
118127
This data reading and processing takes about ``3.5 ms``.
119128

120129
Image Preprocessing
121-
~~~~~~~~~~~~~~~~~~~~
130+
----------------------
122131

123132
We need to take the frames and transform them into the format the model expects. This is the same processing as you would do on any machine with the standard torchvision transforms.
124133

@@ -139,7 +148,7 @@ We need to take the frames and transform them into the format the model expects.
139148
input_batch = input_tensor.unsqueeze(0)
140149
141150
Model Choices
142-
~~~~~~~~~~~~~~~
151+
----------------
143152

144153
There's a number of models you can choose from to use with different performance
145154
characteristics. Not all models provide a ``qnnpack`` pretrained variant so for
@@ -178,7 +187,7 @@ Raspberry Pi 4 Benchmark Results:
178187
+--------------------+------+-----------------------+-----------------------+--------------------+
179188

180189
MobileNetV2: Quantization and JIT
181-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
190+
-------------------------------------
182191

183192
For optimal performance we want a model that's quantized and fused. Quantized
184193
means that it does the computation using int8 which is much more performant than
@@ -208,7 +217,7 @@ We then want to jit the model to reduce Python overhead and fuse any ops. Jit gi
208217
net = torch.jit.script(net)
209218
210219
Putting It Together
211-
~~~~~~~~~~~~~~~~~~~~~~~~~
220+
------------------------
212221

213222
We can now put all the pieces together and run it:
214223

@@ -217,18 +226,23 @@ We can now put all the pieces together and run it:
217226
import time
218227
219228
import torch
220-
import numpy as np
221229
from torchvision import models, transforms
222-
223-
import cv2
224-
from PIL import Image
230+
from picamera2 import Picamera2
225231
226232
torch.backends.quantized.engine = 'qnnpack'
227233
228-
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
229-
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 224)
230-
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 224)
231-
cap.set(cv2.CAP_PROP_FPS, 36)
234+
picam2 = Picamera2()
235+
236+
# print available sensor modes
237+
print(picam2.sensor_modes)
238+
239+
config = picam2.create_still_configuration(main={
240+
"size": (224, 224),
241+
"format": "BGR888",
242+
}, display="main")
243+
picam2.configure(config)
244+
picam2.set_controls({"FrameRate": 36})
245+
picam2.start()
232246
233247
preprocess = transforms.Compose([
234248
transforms.ToTensor(),
@@ -246,13 +260,8 @@ We can now put all the pieces together and run it:
246260
with torch.no_grad():
247261
while True:
248262
# read frame
249-
ret, image = cap.read()
250-
if not ret:
251-
raise RuntimeError("failed to read frame")
263+
image = picam2.capture_image("main")
252264
253-
# convert opencv output from BGR to RGB
254-
image = image[:, :, [2, 1, 0]]
255-
permuted = image
256265
257266
# preprocess
258267
input_tensor = preprocess(image)
@@ -263,6 +272,7 @@ We can now put all the pieces together and run it:
263272
# run model
264273
output = net(input_batch)
265274
# do something with output ...
275+
print(output.argmax())
266276
267277
# log model performance
268278
frame_count += 1
@@ -272,7 +282,8 @@ We can now put all the pieces together and run it:
272282
last_logged = now
273283
frame_count = 0
274284
275-
Running it shows that we're hovering at ~30 fps.
285+
286+
Running it shows that we're hovering at ~30 fps on a Raspberry Pi 4 and ~41 fps on a Raspberry Pi 5.
276287

277288
.. image:: https://user-images.githubusercontent.com/909104/152892609-7d115705-3ec9-4f8d-beed-a51711503a32.png
278289

@@ -312,7 +323,7 @@ Detecting a mug:
312323

313324

314325
Troubleshooting: Performance
315-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
326+
--------------------------------
316327

317328
PyTorch by default will use all of the cores available. If you have anything
318329
running in the background on the Raspberry Pi it may cause contention with the
@@ -329,7 +340,7 @@ increases best case latency to ``72 ms`` from ``60 ms`` but eliminates the
329340
latency spikes of ``128 ms``.
330341

331342
Next Steps
332-
~~~~~~~~~~~~~
343+
------------
333344

334345
You can create your own model or fine tune an existing one. If you fine tune on
335346
one of the models from

0 commit comments

Comments
 (0)