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
构造函数:
-
void setWindowFlags(Qt::WindowFlags type) //设置截图窗口属性,即窗口类型type,还有属性标志WindowFlags也就是设置窗口的各种属性
setWindowFlags(Qt::SubWindow | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) //表示该窗口为子窗口,FramelessWindowHint 代表窗口无边框,WindowStaysOnTopHint设置该窗口总是在其它窗口的顶部
详细可在qt creator参见Qt官方文档,或者参考
-
void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on = true) //参数二为true则设置窗口控件属性,否则清空该属性
setAttribute(Qt::WA_TranslucentBackground, true) //WA_TranslucentBackground可设置窗口控件透明,缺少此处时显示动画时主窗口消失
-
QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = Q_NULLPTR) //创建一个动画对象,作用对象为target
mShowAnimal = new QPropertyAnimation(mBGLabel, "geometry") //使用QProertyAnimation属性动画库,绑定对象为一个label标签,属性名为"geometry"
show()函数:
-
void setStartValue(const QVariant &value) //设置动画的初始值
mShowAnimal->setStartValue(mRect) //动画对象初始大小以及位置由mRect对象决定
-
void setEndValue(const QVariant &value) //同理为设置动画结束值
mShowAnimal->setEndValue(QRect) //动画结束时的坐标和大小由QRect对象决定
-
/*下述信号槽连接,发信号对象为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(); }); });
QPixmap.scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) //返回用所给的w和h框出来的矩形QPixmap
void QTimer::singleShot(int msec, Functor functor) //在经过msec时间后自动调用函数,函数以指针传入
hide() //默认隐藏了动画,和this->hide()是一样的
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()
函数回收内存,就无法再使用。
暂记到此,如有错误,敬请批正。