Camera

USB cameras following v4l2 are supported by the Debian based Raspberry PI OS, however the Raspberry PI OS standard way is using the camera stack libcamera and picamera2 a python API binding that is optimized for the raspberries camera interface hardware.

Important

If a virtual python environment is used allow it to use picamera2 installed in the system,, so do something as: python -m venv .venv --system-site-packages

rpicam-apps

The rpicam-apps package apt show rpicam-apps comes with the rpicam-hello program and others. It uses DRM to show the preview in case the system has no graphical desktop.

rpicam-hello -t0 shows a preview, without -t0 is times out after 5 seconds

rpicam-jpeg --output "$(date +%Y-%m-%d_%H-%M-%S).jpg" to take pictures

rpicam-hello supports post processing https://www.raspberrypi.com/documentation/computers/camera_software.html#post-processing-with-rpicam-apps. Post processing is configured in a *.json file that will be passed via command line. A stage processes camera images. Multiple stage can operate sequentially and are put into the *.json file https://github.com/raspberrypi/rpicam-apps/tree/main/assets.or /usr/share/rpi-camera-assets hold such *.json files

Important

Open and observe those *.json files thy might write to locations as /home/pi that might not exist. In such cases create copies and adapt.

cd /usr/share/rpi-camera-assets and rpicam-hello --post-process-file negate.json

Important

Some *.json files contain in their name _cv. Some of those files as sobel_cv.json work. Others as face_detect_cv.json will fail due to missing OpenCV features..

sudo apt install python3-opencv might improve however to have OpenCV (and also TFlite) support rpicam-apps and libcamera must be recompiled to use it https://www.raspberrypi.com/documentation/computers/camera_software.html#build-libcamera-and-rpicam-apps

The sample program can be started with the verbose -v 2 option, this prints metadata as for object detection and bounding boxes into the console: rpicam-hello -t 0s --post-process-file /usr/share/rpi-camera-assets/imx500_mobilenet_ssd.json --viewfinder-width 1920 --viewfinder-height 1080 --framerate 30 -v 2

This is debug information and therefore not well documented and not recommended for productive solutions.

AI Camera

In edge computing the camera gets CPU power. The AI camera has the imx500 chip from Sony that has Iimage Signal Processor and a AI accelerator that can load a neuronal network.

See https://www.raspberrypi.com/products/ai-camera/ and https://www.raspberrypi.com/products/ai-camera/

To get the firmware sudo apt install imx500-all to get the firmware sudo reboot to get it recognized by the system

/usr/share/imx500-models/ holds neuronal networks in *.rpk format to be loaded into the AI camera

The object detection sample program is started as rpicam-hello -t 0s --post-process-file /usr/share/rpi-camera-assets/imx500_mobilenet_ssd.json --viewfinder-width 1920 --viewfinder-height 1080 --framerate 30

The pose detection is started as rpicam-hello -t 0s --post-process-file /usr/share/rpi-camera-assets/imx500_posenet.json --viewfinder-width 1920 --viewfinder-height 1080 --framerate 30

For advanced things https://mlsysbook.ai/kits/contents/raspi/raspi.html

picamera2

picamera2 ttps://github.com/raspberrypi/picamera2https://pip-assets.raspberrypi.com/categories/652-raspberry-pi-camera-module-2/documents/RP-008156-DS-2-picamera2-manual.pdf?disposition=inlinehttps://pip-assets.raspberrypi.com/categories/652-raspberry-pi-camera-module-2/documents/RP-008156-DS-2-picamera2-manual.pdf?disposition=inline is based on libcamera and is a python library for Raspberry Pi cameras. As sudo dpkg-query -l | grep picamera2 shows, python3-picamera2 is already installed.

However dpkg -L python3-picamera2 shows that it got installed without its valuable examples.

Those example python scripts are a good start to create applications.

Therefore git clone https://github.com/raspberrypi/picamera2.git

Using picamera2 run python imx500_object_detection_demo.py --model /usr/share/imx500-models/imx500_network_ssd_mobilenetv2_fpnlite_320x320_pp.rpk

python imx500_object_detection_demo.py -h shows the help

--iou <values between 0.0 and 1.0> Intersection-over-Union threshold handles how overlapped boxes are dealt

--max-detections <n> defines maximum of boxes to be displayed

python imx500_object_detection_demo.py --print-intrinsics shows information and exits.

/usr/share/imx500-models/ or https://github.com/raspberrypi/imx500-models/tree/main contain the models and lists what example applications can be used

git clone https://github.com/raspberrypi/imx500-models.git to get the newest models as the yolo models that require the command line option to find the label file --labels picamera2/examples/imx500/assets/coco_labels.txt

https://github.com/raspberrypi/picamera2/tree/main/examples/imx500 contains the example programs for the AI camera.

For the object detection there are different versions

imx500_object_detection_demo_mp.py that uses multiprocess and gives smoother video. This demo comes with a menu that allows to take screen shots

imx500_object_detection_injection_demo.py allows customization by injecting the results into the camera pipeline

Streaming video

RTSP is a standard for streams it is robust but creates delays. WebRTC is commonly used for browsers and has little delay.

Mediamtx

RTSP is mature and can stream directly to other devices that understand and use RTSP. But today WebRTC might be preferred since it runs in browsers and produces significantly less delay.

On the local machine RTSP can therefore be streamed into mediamtx and mediamtx then forwards it to WebRTC.

Mediamtx is then used to establish the connection to different IP addresses and is not busing shuffling the data. It however could optionally transcode streams.

RTSP and mediamtx

mediamxt is known to work reliable as streaming session manager that supports RTSP, WebRTC and others. It is probably not available for the linux distribution. Since it is just a simple binary it can be installed manually. sudo mkdir /opt/mediamtx and cd /opt/mediamtx

sudo wget https://github.com/bluenviron/mediamtx/releases/download/v1.16.0/mediamtx_v1.16.0_linux_arm64.tar.gz and sudo tar xzf mediamtx_v1.16.0_linux_arm64.tar.gz

add to mediamtx.yml

paths:
  stream1:
    source: rpiCamera

start /opt/mediamtx/mediamtx /opt/mediamtx/mediamtx.yml

ffplay rtsp://192.168.1.134:8554/stream1 to get the RTSP stream

or in the browser tp://192.168.1.134:8889/stream1/ on the other computer using WebRTC

Now adapt the systemd service /etc/systemd/system/mediamtx.service

[Unit]
Description=MediaMTX RTSP server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/opt/mediamtx/mediamtx /opt/mediamtx/mediamtx.yml
Restart=always
RestartSec=2

# Security / cleanliness
User=<user name>
WorkingDirectory=/opt/mediamtx
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

and sudo systemctl daemon-reload

Adding audio to the stream

The source rpiCamera and also rpicam-vid do not allow adding audio from an external device.

It is also possible to separate mediatmx from rpiCamera to get more flexibility

paths:
  cam:
    source: udp://127.0.0.1:1234

then launch rpicam-vid or an other program to feed it, first without audio

rpicam-vid -t 0 -n --codec libav --low-latency --libav-format mpegts -o udp://127.0.0.1:1234?pkt_size=1316

To get audio rpicam-vid has to write into a pipe and ffmpeg that reads it and adds an audio stream

rpicam-vid -t 10000 --width 1920 --height 1080 --framerate 30 --codec h264 --inline -o - | ffmpeg -i - -f alsa -ac 1 -ar 44100 -i plughw:2,0 -t 10 -c:v copy -c:a aac -b:a 128k recording.mp4

to reduce delay rpicam-vid -t 0 -n --codec libav --low-latency --libav-format mpegts -o - | \ ffmpeg -y -loglevel error \ -thread_queue_size 32 -i pipe:0 \ -f alsa -thread_queue_size 32 -ac 1 -i plughw:2,0 \ -c:v copy \ -c:a aac -b:a 128k \ -fflags nobuffer+flush_packets \ -flags low_delay \ -f mpegts "udp://127.0.0.1:1234?pkt_size=1316"

Once the command works a systemd service can be created cat /etc/systemd/system/rpi-camera.service

[Unit]
Description=Raspberry Pi Camera Audio-Video Stream
After=network.target mediamtx.service
Requires=mediamtx.service

[Service]
User=<username>
Group=video
ExecStart=/bin/bash -c "rpicam-vid -t 0 -n --codec libav --low-latency --libav-format mpegts -o - | \
ffmpeg -y -thread_queue_size 32 -i pipe:0 \
-f alsa -thread_queue_size 32 -ac 1 -i plughw:2,0 \
-c:v copy -c:a aac -b:a 128k \
-fflags nobuffer+flush_packets -flags low_delay \
-f mpegts udp://127.0.0.1:1234?pkt_size=1316"

Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Important

ps -a should not list a running ffmpeg or rpicam-vid process otherwise the service will fail due to busy audio or camera. Therefore pkill -9 ffmpeg and pkill -9 rpicam-vid

WebRTC

WebRTC requires Opus Codec for Audio

rpicam-vid -t 0 -n --codec libav --low-latency --libav-format mpegts -o - | \
ffmpeg -y \
  -thread_queue_size 1024 -i pipe:0 \
  -f alsa -thread_queue_size 1024 -ac 1 -i plughw:2,0 \
  -c:v copy \
  -c:a libopus -ar 48000 -ac 2 \
  -f mpegts "udp://127.0.0.1:1234?pkt_size=1316"

RTSP and rpicam

This way is faster to set up but will not support audio.

rpicam-vid -t 0 -n --codec libav --libav-format mpegts -o - | cvlc stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/stream1}' puts a stream to the raspberries RTSP server.

On an other device ffplay rtsp://<ip-addr-of-server>:8554/stream1 -fflags nobuffer -flags low_delay -framedrop will then show the video

To have this more automated create a script as /opt/rtsp/mediamtx.sh

#!/bin/bash
# RTSP stream using command from Raspberry Pi documentation

exec rpicam-vid -t 0 -n --codec libav --libav-format mpegts -o - | \
     cvlc stream:///dev/stdin --sout "#rtp{sdp=rtsp://:8554/stream1}"

A simple service for systemd sudo touch /etc/systemd/system/rpi-rtsp.service

[Unit]
Description=Raspberry Pi Camera RTSP Stream
After=network.target
Wants=network.target

[Service]
Type=simple
User=<username>
ExecStart=/opt/rtsp/rpi-rtsp-stream.sh
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload

Note

even it is a system process a User gets used since root might fail

As ss -ltnup | grep 8554 shows

tcp LISTEN 0 4096 0.0.0.0:8554 0.0.0.0:* users:(("vlc",pid=1937,fd=3))

tcp LISTEN 0 4096 [::]:8554 [::]:* users:(("vlc",pid=1937,fd=5))

vlc acts as RTSP server but it is limited. It is better to install mediamxt


Linurs startpage