• 【使用VS开发的第一个QT项目——实现相机功能(包括QT下载、配置、摄像头程序)】


    使用VS开发的第一个QT项目

    一、QT(WIN10)安装

    1.首先下载QT(VS有对应的QT)

    下载链接
    windows程序的后缀是.exe
    Ubuntu程序的后缀是.run

    2.安装QT

    按照安装指示操作、注册QT,然后出现”选择“界面时勾选“MinGW 7.3.0 64-bit”,“MSVC 2017 64-bit”;点击“Developer and Designer Tools”前的尖号,打开其中选项,勾选“MinGW 7.3.0 64-bit”。

    二、将QT加载到VS中

    在VS"工具"→"扩展与更新"→"联机"中搜索“QT”并下载,重启生效
    在这里插入图片描述

    三、QT设置

    1.在VS"Qt Vs Tools"→"QT Versions"中添加"msvc2017_64"qmake的路径

    在这里插入图片描述

    2.在"General"→"QT Designer"中将"False"改为"True"

    在这里插入图片描述

    四、QT程序打包

    1.新建QT Widges项目,Base class也选择"QWidget"类(QMainWindow是一个含有菜单的窗口、QDialog是对话框、QWidget是不确定的窗口)

    在这里插入图片描述

    2.先在VS中使用Release模式发布,在x64中找到生成的exe

    在这里插入图片描述

    3.在空白处"shift"+右键打开Windows PowerShell模式,使用QT自带的搜索程序QT\mingw73_64\bin\windeployqt.exe将exe需要的动态库都拷贝过来

    在这里插入图片描述

    4. 安装包制作,首先下载Inno Setup官方链接

    5.新建脚本模式

    请添加图片描述

    6.修改程序信息

    请添加图片描述

    7.设置打包程序位置

    请添加图片描述

    8.添加原始exe和文件夹路径

    请添加图片描述

    9.下面这个关联格式的不要点

    请添加图片描述

    10.创建快捷方式(无需修改)

    请添加图片描述

    11.设置安装向导(无需修改)

    请添加图片描述

    12.选择安全模式(无需修改)

    请添加图片描述

    13.语言选择(无需修改,没得中文)请添加图片描述

    14.设置安装文件的相关信息(生成的exe位置、名称、图标和安装时的密码)请添加图片描述

    后面的一路ok就好了就可以打开了

    #五、第一个项目(摄像头播放)

    要用到opencv调摄像头,所以把opencv也配置到vs中:
    1.在”VC++目录"→“包含目录”中增加opencv\bulid的include和include中的opencv2路径
    2.在"库目录"中增加opencv\build\x64\vc15\lib路径
    3.在"链接器"→"输入"→"附加依赖项"中增加opencv_worldxxx_lib(如果配置为Debug,选择opencv_worldxxxd.lib
    如果为Release,选择opencv_worldxxx.lib)

    1.原代码(已改过命名方式)

    ui

    /********************************************************************************
    ** Form generated from reading UI file 'QT_learning1.ui'
    **
    ** Created by: Qt User Interface Compiler version 5.14.2
    **
    ** WARNING! All changes made in this file will be lost when recompiling UI file!
    ********************************************************************************/
    
    #ifndef UI_QT_LEARNING1_H
    #define UI_QT_LEARNING1_H
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    QT_BEGIN_NAMESPACE
    
    class Ui_QT_learning1Class
    {
    public:
        QPushButton *Open_Camera;
        QPushButton *Capture;
        QPushButton *Close_Camera;
        QLabel *Video;
        QLabel *Photo;
        QLabel *label;
        QLabel *label_2;
    
        void setupUi(QWidget *QT_learning1Class)
        {
            if (QT_learning1Class->objectName().isEmpty())
                QT_learning1Class->setObjectName(QString::fromUtf8("QT_learning1Class"));
            QT_learning1Class->resize(600, 400);
            Open_Camera = new QPushButton(QT_learning1Class);
            Open_Camera->setObjectName(QString::fromUtf8("Open_Camera"));
            Open_Camera->setGeometry(QRect(100, 330, 93, 28));
            Capture = new QPushButton(QT_learning1Class);
            Capture->setObjectName(QString::fromUtf8("Capture"));
            Capture->setGeometry(QRect(250, 330, 93, 28));
            Close_Camera = new QPushButton(QT_learning1Class);
            Close_Camera->setObjectName(QString::fromUtf8("Close_Camera"));
            Close_Camera->setGeometry(QRect(400, 330, 93, 28));
            Video = new QLabel(QT_learning1Class);
            Video->setObjectName(QString::fromUtf8("Video"));
            Video->setGeometry(QRect(40, 40, 224, 224));
            Photo = new QLabel(QT_learning1Class);
            Photo->setObjectName(QString::fromUtf8("Photo"));
            Photo->setGeometry(QRect(310, 40, 224, 224));
            label = new QLabel(QT_learning1Class);
            label->setObjectName(QString::fromUtf8("label"));
            label->setGeometry(QRect(110, 280, 81, 16));
            label_2 = new QLabel(QT_learning1Class);
            label_2->setObjectName(QString::fromUtf8("label_2"));
            label_2->setGeometry(QRect(410, 280, 72, 15));
    
            retranslateUi(QT_learning1Class);
    
            QMetaObject::connectSlotsByName(QT_learning1Class);
        } // setupUi
    
        void retranslateUi(QWidget *QT_learning1Class)
        {
            QT_learning1Class->setWindowTitle(QCoreApplication::translate("QT_learning1Class", "QT_learning1", nullptr));
            Open_Camera->setText(QCoreApplication::translate("QT_learning1Class", "\346\211\223\345\274\200\346\221\204\345\203\217\345\244\264", nullptr));
            Capture->setText(QCoreApplication::translate("QT_learning1Class", "\346\213\215\347\205\247", nullptr));
            Close_Camera->setText(QCoreApplication::translate("QT_learning1Class", "\345\205\263\351\227\255\346\221\204\345\203\217\345\244\264", nullptr));
            Video->setText(QString());
            Photo->setText(QString());
            label->setText(QCoreApplication::translate("QT_learning1Class", "\346\221\204\345\203\217\345\244\264\351\242\204\350\247\210", nullptr));
            label_2->setText(QCoreApplication::translate("QT_learning1Class", "\347\205\247\347\211\207", nullptr));
        } // retranslateUi
    
    };
    
    namespace Ui {
        class QT_learning1Class: public Ui_QT_learning1Class {};
    } // namespace Ui
    
    QT_END_NAMESPACE
    
    #endif // UI_QT_LEARNING1_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    h文件

    #pragma once
    
    #include 
    #include "ui_QT_learning1.h"
    
    #ifndef QT_LEARNING1_H
    #define QT_LEARNING1_H
    
    #include 
    #include 
    #include 
    #include      // 设置采集数据的间隔时间
    
    
    #include   
    #include   
    
    #include   //包含opencv库头文件
    
    #include 
    #include 
    #include   //opencv申明
    
    #include 
    using namespace cv;
    
    namespace Ui {
    	class QT_learning1;
    }
    
    class QT_learning1 : public QWidget
    {
    	Q_OBJECT
    
    public:
    	explicit QT_learning1(QWidget *parent = 0);
    	~QT_learning1();
    
    private slots:
    	void openCamara();      // 打开摄像头
    	void getFrame();       // 读取当前帧信息
    	void closeCamara();     // 关闭摄像头。
    	void takingPictures();  // 拍照
    
    private:
    	Ui::QT_learning1Class ui;
    	QTimer    *timer;
    	QImage    *imag;
    	CvCapture *cam;// 视频获取结构, 用来作为视频获取函数的一个参数
    	IplImage  *frame;
    	VideoCapture capture1;
    	Mat showimage;
    	QImage Mat2Qimage(Mat cvImg);
    
    	//QT_learning1(QWidget * parent);
    		//申请IplImage类型指针,就是申请内存空间来存放每一帧图像
    };
    
    #endif // QT_LEARNING1_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    cpp文件
    (摄像头找不到得话,将capture1.open(0)中的0改成1或者-1试试)

    #include "QT_learning1.h"
    #include
    #include 
    #include
    #include
    using namespace cv;
    using namespace std;
    
    
    
    
    
    QT_learning1::QT_learning1(QWidget *parent) :
    	QWidget(parent)
    {
    	ui.setupUi(this);
    	connect(ui.Open_Camera, SIGNAL(clicked()), this, SLOT(openCamara()));
    	connect(ui.Capture, SIGNAL(clicked()), this, SLOT(takingPictures()));
    	connect(ui.Close_Camera, SIGNAL(clicked()), this, SLOT(closeCamara()));
    	setWindowTitle(tr("Main Window"));
    
    	timer = new QTimer(this);
    	imag = new QImage();
    	connect(timer, SIGNAL(timeout()), this, SLOT(getFrame()));//超时就读取当前摄像头信息
    }
    QT_learning1::~QT_learning1()
    {
    
    }
    
    void QT_learning1::openCamara()
    {
    	capture1.open(0);                                            //打开摄像头,从摄像头中获取视频
    	timer->start(10);
    
    }
    
    void QT_learning1::getFrame() {
    	capture1 >> showimage;
    	QImage imag = Mat2Qimage(showimage);
    
    	ui.Video->setScaledContents(true);
    	ui.Video->setPixmap(QPixmap::fromImage(imag));
    }
    
    void QT_learning1::closeCamara()
    {
    	timer->stop();
    	ui.Video->clear();
    	capture1.release();
    }
    
    
    
    void QT_learning1::takingPictures()
    {
    	capture1.open(0);
    	capture1 >> showimage;
    	QImage img = Mat2Qimage(showimage);
    	ui.Photo->setScaledContents(true);
    	ui.Photo->setPixmap(QPixmap::fromImage(img));
    
    	string writePath = "./";
    	string name;
    	time_t now = time(0);
    	name = writePath + to_string(now) + ".jpg";
    	imwrite(name, showimage);
    
    }
    
    
    QImage QT_learning1::Mat2Qimage(Mat cvImg)
    {
    	// 8-bits unsigned, NO. OF CHANNELS = 1
    	if (cvImg.type() == CV_8UC1)
    	{
    		QImage image(cvImg.cols, cvImg.rows, QImage::Format_Indexed8);
    		// Set the color table (used to translate colour indexes to qRgb values)
    		image.setColorCount(256);
    		for (int i = 0; i < 256; i++)
    		{
    			image.setColor(i, qRgb(i, i, i));
    		}
    		// Copy input Mat
    		uchar *pSrc = cvImg.data;
    		for (int row = 0; row < cvImg.rows; row++)
    		{
    			uchar *pDest = image.scanLine(row);
    			memcpy(pDest, pSrc, cvImg.cols);
    			pSrc += cvImg.step;
    		}
    		return image;
    	}
    	// 8-bits unsigned, NO. OF CHANNELS = 3
    	else if (cvImg.type() == CV_8UC3)
    	{
    		// Copy input Mat
    		const uchar *pSrc = (const uchar*)cvImg.data;
    		// Create QImage with same dimensions as input Mat
    		QImage image(pSrc, cvImg.cols, cvImg.rows, cvImg.step, QImage::Format_RGB888);
    		return image.rgbSwapped();
    	}
    	else if (cvImg.type() == CV_8UC4)
    	{
    		//		qDebug() << "CV_8UC4";
    				// Copy input Mat
    		const uchar *pSrc = (const uchar*)cvImg.data;
    		// Create QImage with same dimensions as input Mat
    		QImage image(pSrc, cvImg.cols, cvImg.rows, cvImg.step, QImage::Format_ARGB32);
    		return image.copy();
    	}
    	else
    	{
    		//		qDebug() << "ERROR: Mat could not be converted to QImage.";
    		return QImage();
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    main.cpp

    #include "QT_learning1.h"
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    	QT_learning1 w;
        w.show();
        return a.exec();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    效果
    还行,但有两个问题:
    1.拍照得到的照片失真,原因是打开摄像头和拍照重复使用摄像头接口,导致数据传输变慢、冲突
    2.没有多线程,如果再来个功能或者运算量变大就over了
    在这里插入图片描述

    2.把cpp文件替换为下面得即可解决第一个问题

    #include "QT_learning1.h"
    #include
    #include 
    #include 
    #include
    #include
    using namespace cv;
    using namespace std;
    
    
    QT_learning1::QT_learning1(QWidget *parent) :
    	QWidget(parent)
    {
    	ui.setupUi(this);
    	connect(ui.Open_Camera, SIGNAL(clicked()), this, SLOT(openCamara()));
    	connect(ui.Capture, SIGNAL(clicked()), this, SLOT(takingPictures()));
    	connect(ui.Close_Camera, SIGNAL(clicked()), this, SLOT(closeCamara()));
    	setWindowTitle(tr("Main Window"));
    
    	timer = new QTimer(this);
    	imag = new QImage();
    	connect(timer, SIGNAL(timeout()), this, SLOT(getFrame()));//超时就读取当前摄像头信息
    }
    QT_learning1::~QT_learning1()
    {
    
    }
    
    void QT_learning1::openCamara()
    {
    	capture1.open(0);                                            //打开摄像头,从摄像头中获取视频
    	timer->start(10);
    
    }
    
    void QT_learning1::getFrame() {
    	capture1 >> showimage;
    	QImage imag = Mat2Qimage(showimage);
    
    	ui.Video->setScaledContents(true);
    	ui.Video->setPixmap(QPixmap::fromImage(imag));
    }
    
    void QT_learning1::closeCamara()
    {
    	timer->stop();
    	ui.Video->clear();
    	capture1.release();
    }
    
    
    
    void QT_learning1::takingPictures()
    {
    	QImage img = Mat2Qimage(showimage);
    	ui.Photo->setScaledContents(true);
    	ui.Photo->setPixmap(QPixmap::fromImage(img));
    
    	string writePath = "./";
    	string name;
    	time_t now = time(0);
    	name = writePath + to_string(now) + ".jpg";
    	imwrite(name, showimage);
    
    }
    
    
    QImage QT_learning1::Mat2Qimage(Mat cvImg)
    {
    	// 8-bits unsigned, NO. OF CHANNELS = 1
    	if (cvImg.type() == CV_8UC1)
    	{
    		QImage image(cvImg.cols, cvImg.rows, QImage::Format_Indexed8);
    		// Set the color table (used to translate colour indexes to qRgb values)
    		image.setColorCount(256);
    		for (int i = 0; i < 256; i++)
    		{
    			image.setColor(i, qRgb(i, i, i));
    		}
    		// Copy input Mat
    		uchar *pSrc = cvImg.data;
    		for (int row = 0; row < cvImg.rows; row++)
    		{
    			uchar *pDest = image.scanLine(row);
    			memcpy(pDest, pSrc, cvImg.cols);
    			pSrc += cvImg.step;
    		}
    		return image;
    	}
    	// 8-bits unsigned, NO. OF CHANNELS = 3
    	else if (cvImg.type() == CV_8UC3)
    	{
    		// Copy input Mat
    		const uchar *pSrc = (const uchar*)cvImg.data;
    		// Create QImage with same dimensions as input Mat
    		QImage image(pSrc, cvImg.cols, cvImg.rows, cvImg.step, QImage::Format_RGB888);
    		return image.rgbSwapped();
    	}
    	else if (cvImg.type() == CV_8UC4)
    	{
    		//		qDebug() << "CV_8UC4";
    				// Copy input Mat
    		const uchar *pSrc = (const uchar*)cvImg.data;
    		// Create QImage with same dimensions as input Mat
    		QImage image(pSrc, cvImg.cols, cvImg.rows, cvImg.step, QImage::Format_ARGB32);
    		return image.copy();
    	}
    	else
    	{
    		//		qDebug() << "ERROR: Mat could not be converted to QImage.";
    		return QImage();
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114

    请添加图片描述
    这样就ok了

    3.多线程

    C++中可直接使用thread库实现
    而QT提供了两种方式实现多线程:
    1.继承QThread的run函数,是个虚函数,会自动调用的
    2.继承于QObject的类用moveToThread函数转移到一个Thread里
    第一种QThread已经不推荐了,我们使用QObject实现

    1.QObject实现思路

    在这里插入图片描述

    1.创键一个继承于 QObject 的自定义线程类(如:MyThread),用来盛放比较耗时,需要放入子线程的处理函数
    (1)定义一个线程处理函数(如:MyWork),当然也可以定义多个,这时多个处理函数就共用一个子线程
    (2)在处理函数中进行处理,此过程可能时间较长(如:QThread::sleep(1))
    (3)在处理函数中发送处理完成的信号(如:emit signal_back()),当然该信号中可能含有处理的结果信息(如计算结果)

    2、 在主线程(亦称界面线程)中创建一个子线程(QThread* subthread = new QThread(this))

    3、新建一个自定义线程类对象(MyThread* m_MyThread = new MyThread())

    4、将自定义线程类对象移入子线程容器中(m_MyThread->moveToThread(subthread)),其实也可以移入多个自定义线程类到同一个subthread中,这时他们就共享一个子线程了

    5、连接主线程和子线程之间的信号和槽
    (1)主线程——>子线程,主线程的信号和子线程的槽
    connect ( this, &MainWindow::StartThread, m_MyThread, &MyThread::MyWork )
    (2)子线程——>主线程,子线程的信号和主线程的槽
    connect (m_MyThread, &MyThread::signal_back, this, &MainWindow::slot_handle_finish )

    6、子线程使用完毕需要回收销毁,不然该线程会一直占用,而系统可分配的线程数量是有限的

    (1)subthread->qiut(); //该停止函数比较弱,会等到线程处理函数MyWork()的任务执行完之后,才会停止线程

    (2)subthread->wait();

    所有通常会加入一个标志位,来终止任务。
    未完待续。。。

  • 相关阅读:
    专精特新是什么?看完你就懂了
    “看看人家苹果和亚马逊”,嫌薪酬太低,谷歌员工“炮轰”高管
    华为HG532系列路由器命令注入漏洞复现 CVE-2017-17215
    HTML CSS JS 画的效果图
    Java多线程篇(11)——BlockingQueue(优先级阻塞,延迟队列)
    嵌入式物联网在医疗行业中的应用——案例分析
    Vue 和 React 比,React 好在哪里?
    DirectX 3D C++ 圆柱体的渲染(源代码)
    【无标题】
    三年,能否成为一名真正的架构师
  • 原文地址:https://blog.csdn.net/qq_37249793/article/details/130893967