Qt+Opencv打开视频并播放,图像自适应缩放

1 篇文章 0 订阅

Qt图片自适应控件大小

Qt5.12.0 + opencv344

目的

主要是想让打开的视频可以自适应窗口大小,放大或者缩小窗口时视频图片也可以跟着放大缩小。

最初的使用方法

  1. 使用QLabel
  2. QLbale置于QWidget中
  3. 对QWidget使用 栅格布局

部分代码如下:

    //方法一
    //直接显示
    QImage image = MatToQImage2(mat);    
    QPixmap pixmap = QPixmap::fromImage(image);   
    ui->label_image->setPixmap(pixmap);
    
    //方法二
    //按比例缩放   
    QImage image=MatToQImage2(mat);    
    QPixmap pixmap = QPixmap::fromImage(image);        
    int width = ui->label_image->width();    
    int height = ui->label_image->height();    
    QPixmap fitpixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); //按比例缩放    
    ui->label_image->setPixmap(fitpixmap); 

显示效果

在这里插入图片描述

存在问题

  • 方法一:图片大小不会随着窗口的放大而放大
  • 方法二:随着窗口的放大,图片可以很好的自适应放大,显示比例也正常,但放大后不能再调整缩小窗口,相应的图片大小也无法缩小

修改1

方法二中,若对Qwidget设置最小值,如10,则可以任意调整大小???

实测可以,原理暂时不清楚

修改2

参考资料

作者:x264ge
来源:CSDN
原文:https://blog.csdn.net/yh_1988/article/details/6752733

    ui->label->setScaledContents(true);//为设置QLabel自动缩放,既:显示图像大小自动调整为Qlabel大小。
    
    //方法三,完全按QWidget缩放,不能保持原比例    
    QImage image=MatToQImage2(mat);    
    QPixmap pixmap = QPixmap::fromImage(image);    
    ui->label_image->resize(ui->widget_show->size());    
    ui->label_image->setPixmap(pixmap);

存在问题

方法三图片完全按照Qwidget大小缩放,不能保持原视频比例

最终方法

采用方法二,可以使视频按照比例的放大缩小,若想实现不按比例缩放,只需添加ui->label->setScaledContents(true);

完整代码

ui

在这里插入图片描述
在这里插入图片描述

playvideo.cpp

#include "playvideo.h"
#include "ui_playvideo.h"

playvideo::playvideo(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::playvideo)
{
    ui->setupUi(this);
    timer=new QTimer(this);
    ui-> label_image->setScaledContents(true);//可以使图片完全按QWidget缩放,而不保持原视频比列
    connect(timer,SIGNAL(timeout()),this,SLOT(ReadFrame()));
}

playvideo::~playvideo()
{
    delete ui;
}

void playvideo::on_pushButton_open_clicked()
{
    videofileName = QFileDialog::getOpenFileName(
                    this, "open video",
                    ".",
                    "video (*.avi *.mp4 *.flv));;All files (*.*)");
    sfileName = videofileName.toStdString();
    video.open(sfileName);

    if(!video.isOpened()){
        QMessageBox::information(this,tr("提示"),tr("视频没有打开"));
    }
    else {

        int videoW = int( video.get(CV_CAP_PROP_FRAME_WIDTH) );
        int videoH = int( video.get(CV_CAP_PROP_FRAME_HEIGHT) );
        fps = int( video.get(CV_CAP_PROP_FPS) );
        //ui->widget_info->setVisible(true);
        //ui->widget_show->setVisible(true);
        ui->textBrowser_info->setText(QString("视频信息:%1").arg(videofileName));
        ui->textBrowser_info->append(QString("视频尺寸:%2×%3").arg(videoW).arg(videoH));
        ui->textBrowser_info->append(QString("视频帧率:%4").arg(fps));
        Mat frame_start;
        video >> frame_start;
        ShowImage(frame_start);
    }
}

void playvideo::ShowImage(cv::Mat& mat)
{
    //方法二,按比例缩放
    QImage image=MatToQImage2(mat);
    QPixmap pixmap = QPixmap::fromImage(image);
    int width = ui->label_image->width();
    int height = ui->label_image->height();
    QPixmap fitpixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    //按比例缩放
    ui->label_image->setPixmap(fitpixmap);
}

void playvideo::on_pushButton_play_clicked()
{
    timer->start(1000/fps);
}

void playvideo::on_pushButton_pause_clicked()
{
    timer->stop();
}

void playvideo::ReadFrame()
{

    Mat frame_now;
    video >> frame_now;//读帧进frame
    if (frame_now.empty())
    {
        QMessageBox::information(this, tr("warning"), tr("the video is end!"));
        timer->stop();

    }
    else {
        ShowImage(frame_now);
    }
}


//图像格式转换
QImage playvideo::MatToQImage2(const cv::Mat &mat)
{
    QImage img;
    int chana = mat.channels();
    //依据通道数不同,改变不同的装换方式
    if(3 == chana ){
		//调整通道次序
		cv::cvtColor(mat,mat,CV_BGR2RGB);
		img = QImage(static_cast<uchar *>(mat.data),mat.cols,mat.rows,QImage::Format_RGB888);
	}
	else if(4 == chana )
	{
		//argb
		img = QImage(static_cast<uchar *>(mat.data),mat.cols,mat.rows,QImage::Format_ARGB32);
	}
	else {
    //单通道,灰度图
    img = QImage( mat.cols, mat.rows , QImage::Format_Indexed8);
    uchar * matdata = mat.data;
		for(int row = 0 ; row <mat.rows ; ++row )
		{
			uchar* rowdata = img.scanLine( row );
			memcpy(rowdata,matdata ,mat.cols);
		m	atdata+=mat.cols;
		}
    }
    return img;
}


playvideo.h

#ifndef playvideo_H
#define playvideo_H

#include <QWidget>
#include <QTimer>
#include <QFileDialog>
#include <QPushButton>
#include <QImage>
#include <QString>
#include <QMessageBox>
#include <QDebug>

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;



namespace Ui {
class playvideo;
}

class playvideo : public QWidget
{
    Q_OBJECT

public:
    explicit playvideo(QWidget *parent = nullptr);
    ~playvideo();

    QImage  MatToQImage2(const cv::Mat& mat);

    void ShowImage(cv::Mat& mat);

private slots:
    void on_pushButton_open_clicked();

    void on_pushButton_play_clicked();

    void ReadFrame();

    void on_pushButton_pause_clicked();

private:
    Ui::playvideo *ui;

    VideoCapture video;
    QTimer *timer;

    int fps;
    QString videofileName;
    std::string sfileName;
};

#endif // playvideo_H

完整工程

点击下载

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值