Qt截取摄像头并显示截图效果详解

Qt截取摄像头并显示截图效果详解

使用qt和opencv制作一个人脸录入系统时,通过qt截取保存人脸后用户没有得到及时的反馈,既没有截图结束通知,也不知道截得怎么样,所以希望可以实现手机截图产生的那种动画效果。

这种截图效果是新产生了一个动画控件显示,然后消失,所以我们新创建一个截图效果类BlinkFrame,并在主窗口MainWindow中应用该类。

截图特效演示:

在这里插入图片描述

代码参考

先贴出截图特效代码:

头文件:

#include <QPropertyAnimation>
#include <QRect>
#include <QLabel>
#include <QPixmap>
#include <QTimer>
#include <QDesktopWidget>
#include <QApplication>


class BlinkFrame : public QWidget
{
	Q_OBJECT

public:
	explicit BlinkFrame(QWidget *parent = 0);
	~BlinkFrame();
	void setSnapshotPixmap(const QPixmap &pixmap);     //获取要截取的图片
	void show();                                 //显示动画
	void setInitRect(QRect rect);                //获取截图的位置大小信息
    
private:
	QLabel* mBGLabel;     //显示截取的图片
	QRect mRect;          //获取截图的位置大小信息
	QPixmap mFitpixmap;     //获取截取图片
	QPropertyAnimation* mShowAnimal;       //声明一个属性动画对象
};

源文件:

BlinkFrame::BlinkFrame(QWidget *parent) :
    QWidget(parent)
{
	setWindowFlags(Qt::SubWindow | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
	setAttribute(Qt::WA_TranslucentBackground, true);
        
	mBGLabel = new QLabel(this);
	mBGLabel->setStyleSheet("background-color:white");
	mShowAnimal = new QPropertyAnimation(mBGLabel, "geometry");
}


BlinkFrame::~BlinkFrame()
{

}


void BlinkFrame::setInitRect(QRect rect)
{
	mRect = rect;
}


void BlinkFrame::setSnapshotPixmap(const QPixmap &pixmap)
{
	mFitpixmap = pixmap;
}


void BlinkFrame::show()
{
    //设置动画的持续时间为400ms,在创建一个proertyAnimation对象时,默认的动画持续时间为250ms
	mShowAnimal->setDuration(400);
    //设置动画初始值,动画对象初始大小以及位置由mRect对象决定
	mShowAnimal->setStartValue(mRect);
    //设置动画结束值,动画结束时的坐标和大小由QRect对象决定,自行设定动画结束的位置
	mShowAnimal->setEndValue(QRect(mRect.x(), mRect.y() + mRect.height()*0.7, mRect.width()*0.3, mRect.height()*0.3));
       
	connect(mShowAnimal, &QPropertyAnimation::finished, this, [=](){
		mFitpixmap = mFitpixmap.scaled(mBGLabel->width(), mBGLabel->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
		mBGLabel->setPixmap(mFitpixmap);   //在label上显示截取的图像
		mBGLabel->setAlignment(Qt::AlignCenter);       //设置label上内容为居中对齐
		QTimer::singleShot(900, [=](){
			hide();
			this->deleteLater();
		});
	});
    
    //获取桌面控件
	QDesktopWidget* desktop = QApplication::desktop();
	int count = desktop->screenCount();            //返回系统可用桌面的数量
	int tempWidth = 0;
	int tempHeight = 0;
	
	if (count > 0)
    {
        //screenGeometry返回桌面坐标,count-1为桌面index,是从0开始的
        tempWidth += desktop->screenGeometry(count - 1).width();
        tempHeight = desktop->screenGeometry(count - 1).height();
    }
	
    //设置动画初始大小,坐标(0, 0)随意,因为初始坐标已经设定了
	this->setGeometry(0, 0, tempWidth, tempHeight);
    this->setVisible(true);         //显示动画控件
    
	mShowAnimal->start();          //开始动画
}

MainWindow中的应用:

BlinkFrame *blinkLabel = new BlinkFrame();
QRect m_previewRect(100, 0, 800, 800);
blinkLabel->setInitRect(m_previewRect);         //设置初始大小坐标
blinkLabel->setSnapshotPixmap(*current_img);     //传入要截图显示的图片
blinkLabel->show();            //显示动画

部分代码详解:

blinkframe.cpp

构造函数:

  1. void setWindowFlags(Qt::WindowFlags type) //设置截图窗口属性,即窗口类型type,还有属性标志WindowFlags也就是设置窗口的各种属性

    setWindowFlags(Qt::SubWindow | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) //表示该窗口为子窗口,FramelessWindowHint 代表窗口无边框,WindowStaysOnTopHint设置该窗口总是在其它窗口的顶部

    详细可在qt creator参见Qt官方文档,或者参考

  2. void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on = true) //参数二为true则设置窗口控件属性,否则清空该属性

    setAttribute(Qt::WA_TranslucentBackground, true) //WA_TranslucentBackground可设置窗口控件透明,缺少此处时显示动画时主窗口消失

    setWindowFlags与setAttribute

  3. QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = Q_NULLPTR) //创建一个动画对象,作用对象为target

    mShowAnimal = new QPropertyAnimation(mBGLabel, "geometry") //使用QProertyAnimation属性动画库,绑定对象为一个label标签,属性名为"geometry"

show()函数:

  1. void setStartValue(const QVariant &value) //设置动画的初始值

    mShowAnimal->setStartValue(mRect) //动画对象初始大小以及位置由mRect对象决定

  2. void setEndValue(const QVariant &value) //同理为设置动画结束值

    mShowAnimal->setEndValue(QRect) //动画结束时的坐标和大小由QRect对象决定

  3. lambda介绍

    /*下述信号槽连接,发信号对象为QProertyAnimation动画,
      信号finished当动画被停止或者结束时被发送出
      接收对象为this
      槽函数使用的是lambda表达式
    */
    connect(mShowAnimal, &QPropertyAnimation::finished, this, [=](){
            mFitpixmap = mFitpixmap.scaled(mBGLabel->width(), mBGLabel->height(), 				Qt::IgnoreAspectRatio, Qt::FastTransformation);
            mBGLabel->setPixmap(mFitpixmap);
            mBGLabel->setAlignment(Qt::AlignCenter);
            QTimer::singleShot(900, [=](){
                hide();
                this->deleteLater();
            });
        });
        
        
    
    1. QPixmap.scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) //返回用所给的w和h框出来的矩形QPixmap
    2. void QTimer::singleShot(int msec, Functor functor) //在经过msec时间后自动调用函数,函数以指针传入
    3. hide() //默认隐藏了动画,和this->hide()是一样的
    4. this->deleteLater() //在对象进入时间循环后删除对象,释放内存

    MainWindow.cpp

    截取摄像头人脸保存代码:

    void MainWindow::save_image()
    {
        //获取摄像头当前显示的帧
        const QPixmap *current_img = ui->camera_label->pixmap();
        QString id = ui->id_line_edit->text();         //获取界面输入的人名id
        QString dir = face_dir;
        dir = dir + id + ".jpg";       //id名就是保存的图片名
        //string s = dir.toStdString();
        //cout << s << endl;
        current_img->save(dir);           //将当前图片保存在指定路径dir中
    
        //开始显示截图动画特效
        BlinkFrame *blinkLabel = new BlinkFrame();
        QRect m_previewRect(100, 50, 800, 800);
        blinkLabel->setInitRect(m_previewRect);
        //const QPixmap pp = QPixmap::fromImage(img);
        blinkLabel->setSnapshotPixmap(*current_img);
        blinkLabel->show();
    }
    

截图对象BlinkFrame 的内存定义最好使用时再定义,若在构造函数中定义在使用一次后就会被this->deleteLater()函数回收内存,就无法再使用。

关于label上图片的保存方法参考

暂记到此,如有错误,敬请批正。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值