QVideoFrame转为opencv可处理的cv::Mat格式

#include <QApplication>
#include <QCamera>
#include <QCameraInfo>
#include <QVideoProbe>
#include <QVideoFrame>
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
#include <opencv2/opencv.hpp>

class CameraWidget : public QWidget {
    Q_OBJECT

public:
    CameraWidget(QWidget *parent = nullptr) : QWidget(parent) {
        // 初始化布局
        QVBoxLayout *layout = new QVBoxLayout(this);
        viewfinder = new QLabel(this);
        viewfinder->setAlignment(Qt::AlignCenter);
        layout->addWidget(viewfinder);
        setLayout(layout);

        // 初始化相机
        QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
        if (cameras.isEmpty()) {
            viewfinder->setText("No camera found!");
            return;
        }

        camera = new QCamera(cameras.first(), this);
        camera->setCaptureMode(QCamera::CaptureVideo);

        // 初始化视频探针
        videoProbe = new QVideoProbe(this);
        if (videoProbe->setSource(camera)) {
            connect(videoProbe, &QVideoProbe::videoFrameProbed, this, &CameraWidget::processFrame);
        }

        // 启动相机
        camera->start();
    }

private slots:
    void processFrame(const QVideoFrame &frame) {
        QVideoFrame cloneFrame(frame);
        if (cloneFrame.map(QAbstractVideoBuffer::ReadOnly)) {
            // 将 QVideoFrame 转换为 cv::Mat
            cv::Mat cvImage = convertQVideoFrameToMat(cloneFrame);

            if (!cvImage.empty()) {
                // 对图像进行处理(例如转换为灰度图像)
                cv::Mat grayImage;
                cv::cvtColor(cvImage, grayImage, cv::COLOR_BGR2GRAY);

                // 将处理后的图像显示在 QLabel 中
                QImage qImage(grayImage.data, grayImage.cols, grayImage.rows, grayImage.step, QImage::Format_Grayscale8);
                viewfinder->setPixmap(QPixmap::fromImage(qImage));
            }

            cloneFrame.unmap();
        }
    }

private:
    // 将 QVideoFrame 转换为 cv::Mat
    cv::Mat convertQVideoFrameToMat(const QVideoFrame &frame) {
        // 获取图像尺寸和格式
        int width = frame.width();
        int height = frame.height();
        QVideoFrame::PixelFormat pixelFormat = frame.pixelFormat();

        // 根据像素格式确定 OpenCV 图像格式
        int cvType = CV_8UC3; // 默认格式为 3 通道 8 位图像
        if (pixelFormat == QVideoFrame::Format_ARGB32 || pixelFormat == QVideoFrame::Format_RGB32) {
            cvType = CV_8UC4; // 4 通道 8 位图像
        } else if (pixelFormat == QVideoFrame::Format_RGB24) {
            cvType = CV_8UC3; // 3 通道 8 位图像
        } else if (pixelFormat == QVideoFrame::Format_YUV420P || pixelFormat == QVideoFrame::Format_NV12) {
            // 对于 YUV 格式,需要额外处理
            cv::Mat yuvImage(height + height / 2, width, CV_8UC1, frame.bits());
            cv::Mat rgbImage;
            cv::cvtColor(yuvImage, rgbImage, cv::COLOR_YUV2BGR_I420);
            return rgbImage;
        } else {
            qWarning() << "Unsupported pixel format:" << pixelFormat;
            return cv::Mat();
        }

        // 创建 cv::Mat
        cv::Mat cvImage(height, width, cvType, frame.bits(), frame.bytesPerLine());

        // 如果格式是 ARGB32 或 RGB32,需要调整通道顺序
        if (pixelFormat == QVideoFrame::Format_ARGB32 || pixelFormat == QVideoFrame::Format_RGB32) {
            cv::cvtColor(cvImage, cvImage, cv::COLOR_BGRA2BGR);
        }

        return cvImage;
    }

private:
    QCamera *camera;
    QVideoProbe *videoProbe;
    QLabel *viewfinder;
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    CameraWidget widget;
    widget.resize(800, 600);
    widget.show();

    return app.exec();
}

#include "main.moc"
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值