这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 09树莓派5Qt调用CSI摄像头

共4条 1/1 1 跳转至

09树莓派5Qt调用CSI摄像头

菜鸟
2025-06-29 00:43:09     打赏

09  树莓派5  Qt调用CSI摄像头

    该安装的在前几节都已经安装好了,这一节就直接从代码开始。

核心代码

// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QPushButton>
#include <QProcess>
#include <QTimer>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void toggleC
    
    
    
    
    
    mera();
    void readCameraOutput();
    void updateFrame();

private:
    QProcess *cameraProcess = nullptr;
    QLabel *cameraView = nullptr;
    QPushButton *cameraButton;
    QTimer *frameTimer;
    QByteArray frameData;
    bool cameraRunning = false;
    bool frameStarted = false;
    int frameCount = 0;
};

#endif // MAINWINDOW_H

// mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QDebug>
#include <QTime>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 设置窗口属性
    setWindowTitle("树莓派CSI摄像头");
    setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
    resize(800, 600);
    
    // 创建中央部件和布局
    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
    
    // 创建摄像头视图区域
    QGroupBox *viewGroup = new QGroupBox("摄像头预览", centralWidget);
    QVBoxLayout *viewLayout = new QVBoxLayout(viewGroup);
    
    cameraView = new QLabel(viewGroup);
    cameraView->setAlignment(Qt::AlignCenter);
    cameraView->setMinimumSize(640, 480);
    cameraView->setStyleSheet("background-color: black;");
    viewLayout->addWidget(cameraView);
    
    // 创建控制区域
    QGroupBox *controlGroup = new QGroupBox("控制面板", centralWidget);
    QHBoxLayout *controlLayout = new QHBoxLayout(controlGroup);
    
    cameraButton = new QPushButton("启动摄像头", controlGroup);
    cameraButton->setFixedSize(150, 40);
    cameraButton->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; }");
    connect(cameraButton, &QPushButton::clicked, this, &MainWindow::toggleCamera);
    
    controlLayout->addWidget(cameraButton);
    
    // 添加到主布局
    mainLayout->addWidget(viewGroup, 4);
    mainLayout->addWidget(controlGroup, 1);
    
    setCentralWidget(centralWidget);
    
    // 创建帧定时器
    frameTimer = new QTimer(this);
    frameTimer->setInterval(33); // 约30fps
    connect(frameTimer, &QTimer::timeout, this, &MainWindow::updateFrame);
}

MainWindow::~MainWindow()
{
    if (cameraProcess) {
        cameraProcess->terminate();
        cameraProcess->waitForFinished();
        delete cameraProcess;
    }
}

void MainWindow::toggleCamera()
{
    if (!cameraRunning) {
        // 启动libcamera-vid进程
        cameraProcess = new QProcess(this);
        connect(cameraProcess, &QProcess::readyReadStandardOutput, 
                this, &MainWindow::readCameraOutput);
        
        // 准备命令行参数
        QStringList arguments;
        arguments << "--inline"          // 输出原始数据
                  << "--width" << "640" 
                  << "--height" << "480"
                  << "--nopreview"      // 禁用内部预览
                  << "--codec" << "mjpeg" // 使用MJPEG格式
                  << "--timeout" << "0"  // 无限运行
                  << "--framerate" << "30" // 设置帧率
                  << "--denoise" << "cdn_off" // 禁用降噪以提高性能
                  << "-o" << "-";        // 输出到stdout
        
        // 启动摄像头进程
        cameraProcess->start("libcamera-vid", arguments);
        
        if (cameraProcess->waitForStarted(3000)) {
            cameraButton->setText("停止摄像头");
            cameraButton->setStyleSheet("QPushButton { background-color: #F44336; color: white; font-weight: bold; }");
            cameraRunning = true;
            frameTimer->start();
            frameCount = 0;
            qDebug() << "摄像头已启动";
        } else {
            qDebug() << "无法启动摄像头进程:" << cameraProcess->errorString();
            delete cameraProcess;
            cameraProcess = nullptr;
        }
    } else {
        // 停止摄像头
        frameTimer->stop();
        
        if (cameraProcess) {
            cameraProcess->terminate();
            if (!cameraProcess->waitForFinished(1000)) {
                cameraProcess->kill();
            }
            delete cameraProcess;
            cameraProcess = nullptr;
        }
        
        cameraButton->setText("启动摄像头");
        cameraButton->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; }");
        cameraRunning = false;
        
        // 清空视图
        cameraView->clear();
        cameraView->setStyleSheet("background-color: black;");
        
        qDebug() << "摄像头已停止";
    }
}

void MainWindow::readCameraOutput()
{
    // 读取所有可用数据
    QByteArray newData = cameraProcess->readAllStandardOutput();
    frameData.append(newData);
}

void MainWindow::updateFrame()
{
    // 如果没有足够数据,直接返回
    if (frameData.size() < 100) return;
    
    // 寻找JPEG开始标记 (0xFF 0xD8)
    int startIndex = frameData.indexOf("\xFF\xD8");
    if (startIndex < 0) {
        // 没有找到JPEG开始标记,清空缓冲区
        frameData.clear();
        return;
    }
    
    // 寻找JPEG结束标记 (0xFF 0xD9)
    int endIndex = frameData.indexOf("\xFF\xD9", startIndex);
    if (endIndex < 0) {
        // 没有完整帧,保留可能包含开始标记的数据
        if (startIndex > 0) {
            frameData = frameData.mid(startIndex);
        }
        return;
    }
    
    // 计算帧长度(包含结束标记)
    int frameLength = endIndex - startIndex + 2;
    
    // 提取完整帧数据
    QByteArray jpegData = frameData.mid(startIndex, frameLength);
    
    // 移除已处理的数据
    frameData = frameData.mid(startIndex + frameLength);
    
    // 更新帧计数器
    frameCount++;
    
    // 显示帧率(每30帧更新一次)
    if (frameCount % 30 == 0) {
        setWindowTitle(QString("树莓派CSI摄像头 - %1 FPS").arg(frameCount / 3));
        frameCount = 0;
    }
    
    // 创建图像并显示
    QPixmap pixmap;
    if (pixmap.loadFromData(jpegData, "JPEG")) {
        // 缩放图像以适应视图
        QPixmap scaledPixmap = pixmap.scaled(cameraView->width(), 
                                             cameraView->height(), 
                                             Qt::KeepAspectRatio, 
                                             Qt::SmoothTransformation);
        cameraView->setPixmap(scaledPixmap);
    }
}

// main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    // 设置应用样式
    QApplication::setStyle("Fusion");
    
    // 创建主窗口
    MainWindow w;
    w.show();
    
    return a.exec();
}

主要流程:

deepseek_mermaid_20250628_cd30d4.png

成果演示:

output.gif




专家
2025-06-29 13:17:02     打赏
2楼

感谢分享


专家
2025-06-29 13:18:01     打赏
3楼

感谢分享


专家
2025-06-29 13:19:33     打赏
4楼

感谢分享


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]