四小时学习opencv+qt系列(第五天)

四小时学习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 ,这样的话opencv4中也可以使用CV_BGR2RGB了。set可以转换内存中连续存储的图像数据。

//确保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布局如下,做如下的修改,将工具栏和菜单栏都移除了,设置网格布局。

四小时学习opencv+qt系列(第五天)_第1张图片

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));
    }
}

效果图:直接拖拽图片放到界面中就可以显示

四小时学习opencv+qt系列(第五天)_第2张图片

上面讲到的是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复选框。目录结构如下图:

四小时学习opencv+qt系列(第五天)_第3张图片

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添加后提升。接下来运行程序就会出现窗口中一个方块每半秒交换一次颜色(红与白之间)效果动画:

四小时学习opencv+qt系列(第五天)_第4张图片

在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自带的那几个类吧,明天继续,,,对你有帮助的话点个赞吧。

你可能感兴趣的:(opencv,Qt)