#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"