四小时学习opencv+qt系列(第五天)
上一篇博客我们学习的是opencv中的图像和视频处理,接下来是学习直接利用qt中的类进行图像和视频处理。
一、Qt中的图像和视频处理
1.QImage
//创建一个320*240像素(宽*高)的标准RGB图像
QImage image(320,240,QImage::Format_RGB888);
//利用QSize传递参数
QImage image(QSize(320,240),QImage::Format_RGB888);
下面的例子是opencv读入图片再转化为QImage,由于opencv默认读入图片是BGR的所以需要转化为RGB
#include
#include
using namespace cv;
Mat mat=imread("../1.jpg");
cvtColor(mat,mat,CV_BGR2RGB);
QImage image(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_RGB888);
imshow("output",mat);
代码及问题分析:上面这种写法我是在using namespace cv的前提下的,由于我使用的opencv是4.2,所以新版本的cvtColor(mat,mat,CV_BGR2RGB);应该写作cvtColor(mat,mat,COLOR_BGR2RGB);还有一种解决方案,就是添加头文件
#include
//确保QImage是标准的三通道RGB图像
QImage image("../1.jpg");
image = image.convertToFormat(QImage::Format_RGB888);//转换图像格式
//bytesPerLine()与step相似,表示图像中每条扫描线的字节数基本上与width相同
Mat mat=Mat(image.height(),image.width(),CV_8UC3,image.bits(),image.bytesPerLine());
imshow("output1",mat);
2.QPixmap类
新建项目ImageViewer,基类选择MainWindow;
ui布局如下,做如下的修改,将工具栏和菜单栏都移除了,设置网格布局。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
//要重写的三个事件
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void resizeEvent(QResizeEvent *event);
private:
Ui::MainWindow *ui;
QPixmap pixmap;//私有的pixmap
};
#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);
setAcceptDrops(true);//有这个才能接受拖拽事件
}
MainWindow::~MainWindow()
{
delete ui;
}
// 拖拽处理函数
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
QStringList acceptedFileTypes;
acceptedFileTypes.append("jpg");
acceptedFileTypes.append("png");
acceptedFileTypes.append("bmp");
if (event->mimeData()->hasUrls() &&
event->mimeData()->urls().count() == 1)
{
QFileInfo file(event->mimeData()->urls().at(0).toLocalFile());
if(acceptedFileTypes.contains(file.suffix().toLower()))
{
event->acceptProposedAction();
}
}
}
// 拖拽释放处理函数
void MainWindow::dropEvent(QDropEvent *event)
{
QFileInfo file(event->mimeData()->urls().at(0).toLocalFile());
if(pixmap.load(file.absoluteFilePath()))
{
ui->label->setPixmap(pixmap.scaled(ui->label->size(),
Qt::KeepAspectRatio,
Qt::SmoothTransformation));
}
else
{
QMessageBox::critical(this,
tr("Error"),
tr("The image file cannot be read!"));
}
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
if(!pixmap.isNull())
{
ui->label->setPixmap(pixmap.scaled(ui->label->width()-5,
ui->label->height()-5,
Qt::KeepAspectRatio,
Qt::SmoothTransformation));
}
}
效果图:直接拖拽图片放到界面中就可以显示
上面讲到的是Mat——>QImage,下面是如何QImage——>QPixmap
#include
using namespace cv;
Mat mat=imread("../1.jpg");
QImage image(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(image.rgbSwapped()));
3.QImageReader和QImageWriter类,进行图像的读写,支持QImage和QPixmap相同类型的文件。
4.QPainter类
新建一个自定义控件,用QPainter创建他的可视化对象。
新建一个Painter_Testd的应用程序,基类还是选择QMainWindow,再在这个工程里新建一个c++class,基类为QWidget,类名为QBlinkingWidget,只勾选Include QWidget复选框。目录结构如下图:
qblinkingwidget.h
#ifndef QBLINKINGWIDGET_H
#define QBLINKINGWIDGET_H
#include
#include
#include
#include
class QBlinkingWidget : public QWidget
{
Q_OBJECT
public:
explicit QBlinkingWidget(QWidget *parent = nullptr);
//画图事件
protected:
void paintEvent(QPaintEvent *event);
signals:
private slots:
void onBlink();//onBlink槽函数
private:
QTimer blinkTimer;//定时器blinkTimer
bool blink;//bool变量blink
};
#endif // QBLINKINGWIDGET_H
qblinkingwidget.cpp
#include "qblinkingwidget.h"
QBlinkingWidget::QBlinkingWidget(QWidget *parent) : QWidget(parent)
{
//一开始讲blink置为false
//500ms触发一次onBlink槽函数
blink = false;
connect(&blinkTimer,SIGNAL(timeout()),this,SLOT(onBlink()));
blinkTimer.start(500);
}
void QBlinkingWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
if(blink)
painter.fillRect(this->rect(),QBrush(Qt::red));
else
painter.fillRect(this->rect(),QBrush(Qt::white));
}
void QBlinkingWidget::onBlink()
{
blink = !blink;//取反
this->update();//刷新绘图事件
}
在mainwindow.ui中拖动出一个QWidget控件,右键提升为类,类名为QBlinkingWidget添加后提升。接下来运行程序就会出现窗口中一个方块每半秒交换一次颜色(红与白之间)效果动画:
在QImage上完成绘制操作,只需要保证QImage传递给QPainter或使用begin函数来构造QPainter。
QImage image(320,240,QImage::Format_RGB888);
QPainter painter;
painter.begin(&image);
painter.fillRect(image.rect(),Qt::blue);
painter.drawLine(0,0,this->width()-1,this->height()-1);
painter.end();
5.Qt中的视频处理
//因为用到了类都存在Qt的多媒体类中,所以在.pro文件中
QT+=multimedia
//Qt的相关类
QCamera:用于访问平台上的可用相机
QCameraInfo:用于获取平台上的可用相机的有关信息
QMediaPlayer:用于播放视频和其他类型的大众媒体
QMediaRecorder:这个类在录制视频或是其他媒体类型时有用
QVideoFrame:可以访问相机抓取的单个视频帧
QVideoProbe:可以监控来自相机或视频的帧
QVideoWidget:可用于显示从相机或者视频源的帧
最后我尝试不用Qt给的这几个多媒体的类,直接用画图事件加上自己写的一个类来制作一个视频播放软件,参照上面那个例子,在自己写的类中引入opencv将图像读取进来,进行转换之后用QPainter来画,发现不行可能是需要继承Qt自带的那几个类吧,明天继续,,,对你有帮助的话点个赞吧。