Введение
Raspberry Pi имеет официальную поддержку подключаемых модулей камеры через специальный разъём CSI, программный доступ к которым в современных версиях Raspberry Pi OS реализован через библиотеку libcamera, заменившую устаревший проприетарный стек. В статье разберём интеграцию камеры Raspberry Pi с Qt Multimedia (основной цикл статей, статья 251), продолжая тему компьютерного зрения, упоминавшуюся ранее как возможное направление (OpenCV).
Концепция
libcamera — современный, открытый фреймворк управления камерами в Linux, заменивший закрытый стек raspicam/picamera из более старых версий Raspberry Pi OS — Qt Multimedia на современных версиях Qt (начиная с Qt 6.5+) поддерживает libcamera как один из бэкендов для QCamera, что позволяет использовать тот же API QCamera/QMediaCaptureSession из основного цикла статей без специфичного для платформы кода, если бэкенд правильно настроен на уровне сборки Qt.
Пример кода: Камера Raspberry Pi
# Проверка обнаружения подключённой камеры через libcamera
libcamera-hello --list-cameras
# Быстрый тест захвата изображения без какого-либо кода — диагностика перед написанием Qt-приложения
libcamera-still -o test.jpg
// cameraviewer.h — использование QCamera с камерой Raspberry Pi через libcamera-бэкенд
#pragma once
#include <QMediaCaptureSession>
#include <QCamera>
#include <QVideoWidget>
#include <QMediaDevices>
#include <QWidget>
class CameraViewer : public QWidget
{
Q_OBJECT
public:
explicit CameraViewer(QWidget *parent = nullptr) : QWidget(parent)
{
auto *layout = new QVBoxLayout(this);
m_videoWidget = new QVideoWidget(this);
layout->addWidget(m_videoWidget);
// QMediaDevices::videoInputs() автоматически обнаруживает камеру Raspberry Pi
// через libcamera-бэкенд, без необходимости указывать путь к устройству вручную
const auto cameras = QMediaDevices::videoInputs();
if (cameras.isEmpty()) {
qWarning() << "Камера не обнаружена — проверьте подключение и libcamera-hello --list-cameras";
return;
}
m_camera = new QCamera(cameras.first(), this);
m_captureSession.setCamera(m_camera);
m_captureSession.setVideoOutput(m_videoWidget);
m_camera->start();
}
private:
QVideoWidget *m_videoWidget;
QCamera *m_camera = nullptr;
QMediaCaptureSession m_captureSession;
};
// Захват отдельного снимка — аналогично основному циклу статей про Qt Multimedia (статья 251)
#include <QImageCapture>
void captureSnapshot(QMediaCaptureSession &session)
{
auto *imageCapture = new QImageCapture();
session.setImageCapture(imageCapture);
QObject::connect(imageCapture, &QImageCapture::imageSaved, [](int id, const QString &fileName) {
qDebug() << "Снимок сохранён:" << fileName;
});
imageCapture->captureToFile("/home/pi/snapshot.jpg");
}
Пояснения к коду
QMediaDevices::videoInputs() — единый, кросс-платформенный способ обнаружения доступных камер, работающий одинаково и на десктопе (USB-веб-камера, основной цикл статей), и на Raspberry Pi с подключённым через CSI модулем камеры, при условии, что Qt собран с поддержкой libcamera-бэкенда — это значимое архитектурное преимущество: код приложения, использующего QCamera, не нуждается в специфичных для Raspberry Pi ветвлениях, если правильно настроен сам бэкенд на уровне сборки Qt. libcamera-hello/libcamera-still — диагностические утилиты командной строки, не связанные напрямую с Qt, но крайне полезные для быстрой проверки физического подключения и работоспособности камеры до перехода к написанию и отладке кода Qt-приложения.
Подводные камни
- Использование версии Qt, собранной без поддержки
libcamera-бэкенда (что особенно вероятно для системного Qt из репозиториев более старых версий Raspberry Pi OS, статья 342) —QMediaDevices::videoInputs()в таком случае может вернуть пустой список, даже если камера физически подключена и работает (что подтверждается черезlibcamera-hello), что приводит к ложному впечатлению о неисправности оборудования, тогда как реальная причина — отсутствие нужного бэкенда в используемой сборке Qt. - Путаница между устаревшим
raspicam/legacy camera stack и современнымlibcamera— некоторые старые образы Raspberry Pi OS по умолчанию используют устаревший стек камеры, который не работает совместно сlibcamera-бэкендом Qt; переключение на современный стек (обычно черезraspi-configили явную настройку/boot/config.txt) может требоваться явно, прежде чем камера будет видна черезQMediaDevices. - Недостаточное охлаждение/питание Raspberry Pi при длительной записи видео в высоком разрешении, приводящее к тепловому троттлингу процессора и заметному падению частоты кадров во время длительной работы — для приложений с продолжительным захватом видео в высоком разрешении стоит заранее проверить тепловой режим конкретной модели и корпуса, особенно для компактных моделей вроде Pi Zero 2 W с ограниченным теплоотводом.
- Игнорирование разницы в производительности обработки видео в реальном времени между Raspberry Pi и десктопным компьютером, на котором, возможно, изначально разрабатывалось и тестировалось приложение — алгоритмы обработки изображений (например, для последующей интеграции с OpenCV), достаточно быстрые на мощном десктопе, могут не успевать обрабатывать кадры в реальном времени на значительно менее производительном Raspberry Pi, и производительность стоит явно протестировать на целевом устройстве, а не только на машине разработки.