MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include <opencv2/videoio.hpp>
using namespace cv;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_actOpen_triggered();//打开摄像头
void on_actClose_triggered();//关闭摄像头
void timeOut();//timer超时
private:
Ui::MainWindow *ui;
VideoCapture cap;
QTimer *timer = new QTimer(this);
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeOut()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actOpen_triggered()
{
cap = VideoCapture();
cap.open(0);
timer->setInterval(40);
timer->start();
ui->actOpen->setEnabled(false);
ui->actClose->setEnabled(true);
}
void MainWindow::on_actClose_triggered()
{
timer->stop();
ui->actOpen->setEnabled(true);
ui->actClose->setEnabled(false);
}
void MainWindow::timeOut()
{
Mat mat;
cap.read(mat);
ui->label->setData(mat);//这个是我重写的一个widget控件
this->update();
}
SDLWidget.h
#ifndef SDLWIDGET_H
#define SDLWIDGET_H
#include <QMutex>
#include <QWidget>
#include <opencv2/core/mat.hpp>
#include <SDL2/SDL.h>
using namespace cv;
class SDLWidget : public QWidget
{
Q_OBJECT
public:
explicit SDLWidget(QWidget *parent = nullptr);
~SDLWidget();
void setData(Mat mat);
signals:
private:
Mat mat;
QMutex mtx;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture = NULL;
// QWidget interface
protected:
void paintEvent(QPaintEvent *event) override;
};
#endif // SDLWIDGET_H
SDLWidget.cpp
#include "SDLWidget.h"
#include <QDebug>
SDLWidget::SDLWidget(QWidget *parent) : QWidget(parent)
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindowFrom((void *)this->winId());
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);//硬件加速
SDL_ShowWindow(window);
}
SDLWidget::~SDLWidget()
{
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
}
void SDLWidget::setData(Mat mat)
{
mtx.lock();
mat.copyTo(this->mat);
mtx.unlock();
if (texture == NULL) {
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR24, SDL_TEXTUREACCESS_STREAMING, mat.cols, mat.rows);
}
}
void SDLWidget::paintEvent(QPaintEvent *event)
{
if (!this->mat.empty()) {
Mat frame;
mtx.lock();
this->mat.copyTo(frame);
mtx.unlock();
qDebug() << "clear \t" << SDL_RenderClear(renderer); // 0 on success, or -1 on error
qDebug() << "color \t" << SDL_SetRenderDrawColor(renderer, 187, 159, 93, 255); //用renderer画背景图 0 on success, or -1 on error
qDebug() << "update \t" << SDL_UpdateTexture(texture, NULL, frame.data, frame.cols * 3); //更新纹理 0 on success, or -1 if the texture is not valid.
qDebug() << "copy \t" << SDL_RenderCopy(renderer, texture, NULL, NULL); // 0 on success, or -1 on error
SDL_RenderPresent(renderer); //渲染
}
QWidget::paintEvent(event);
}
界面
设备没问题,代码应该也没有问题,这段c++代码可以正常播放.
#include <stdio.h>
#include <SDL2/SDL.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char *argv[])
{
bool res = SDL_Init(SDL_INIT_VIDEO); //枚举变量值可以叠加,返回值为0/1;
/** 这两段代码差这句话,Qt直接把他当成控件处理,所以不需要create,C++这块需要create一个window **/
SDL_Window *window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_OPENGL);//
printf("%d\n", SDL_GetWindowID);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); //使用硬件加速
SDL_Texture *texture = nullptr;
VideoCapture cap = VideoCapture();
cap.open(0);
bool isRunning = true;
Mat mat;
int winWidth = 0;
int winHeight = 0;
SDL_GetWindowSize(window, &winWidth, &winHeight);
while (isRunning)
{
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 187, 159, 93, 255); //用renderer画黑图
printf("clear");
isRunning = cap.read(mat);
if (!isRunning)
{
break;
}
texture = texture == nullptr ? SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR24, SDL_TEXTUREACCESS_STREAMING, mat.cols, mat.rows) : texture;
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = 640;
rect.h = 480;
res = SDL_UpdateTexture(texture, NULL, mat.data, mat.cols * 3);
printf("update %d\n", res);
res = SDL_RenderCopy(renderer, texture, NULL, &rect);
printf("copy %d\n", res);
SDL_RenderPresent(renderer); //这个是用来显示画面的
waitKey(40);
}
cap.release();
SDL_Quit();
return 0;
}