1. 程式人生 > >人臉識別系統開發(3) -- C++與QML混合程式設計

人臉識別系統開發(3) -- C++與QML混合程式設計

版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。
本文連結:https://blog.csdn.net/china_jeffery/article/details/78954822
使用Qt Quick技術可以快速的構建流暢的介面,而且具有動畫等各種絢麗的效果。但它也有很多侷限性,比如在網路訪問、硬體操作、檔案處理等方面,所以在很多時候我們需要混合使用C++和QML,比如使用QML構建介面,使用C++來實現非介面的業務邏輯等。這樣也就涉及到了QML和C++之間的互動了。其實,QML的很多基本型別本來也是通過C++來實現的,比如Item對應QQuickItem類,Image對應QQuickImage類等。

前面人臉識別系統開發(2) – QML基礎語法中提到的:

import HFR.IDCard 1.0     // C++中IDCardReader類註冊為QML物件
import HFR.VideoItem 1.0  // C++中VideoItem類註冊為QML物件
1
2
就是典型的QML訪問C++的例子,通過將C++類註冊為QML物件,來讓QML訪問。

C++呼叫QML的例子如:

QMetaObject::invokeMethod(g_Root, "showMsg",
    Q_ARG(QVariant, QObject::tr("人臉檢測模組載入失敗")));
1
2
一、在QML中使用C++類和物件
Qt提供了2種在QML中訪問C++物件的方式:
1. 在C++中實現一個類,註冊該類為QML環境的一個型別,然後在QML中使用該型別建立一個物件(即宣告一個控制元件)。
2. 在C++中構造一個物件,將這個物件設定為QML的上下文屬性,是QML環境中直接使用該屬性。

1.1 定義一個可以匯出的C++類
以OpenCVCamera類為例,該類位於HFR\OpenCVCamera.h檔案:

// OpenCVCamera摘要
//
class OpenCVCamera : public QObject { // 直接或間接從QObject繼承
    Q_OBJECT // 使用Q_OBJECT巨集

    // 使用Q_PROPERTY巨集來定義可以被QML環境訪問的屬性
    // 詳細語法見:http://doc.qt.io/qt-5/qobject.html#Q_PROPERTY
    //
    Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
public:
    explicit OpenCVCamera(QObject *parent = 0);
    virtual ~OpenCVCamera();

    bool enabled() const;
    virtual void setEnabled(bool b);
    bool readMat(cv::Mat &frame);
public slots:
    // 使用Q_INVOKABLE巨集來修飾類的成員函式,讓QML中可以呼叫該方法
    //
    Q_INVOKABLE void grapImage(bool bFace, int iNum);
    Q_INVOKABLE void recognize(QString name,
        QString sex, 
        QString nation, 
        QString birthday, 
        QString photoPath, 
        QString address,
        QString cardNumber);
private slots:
    void grapFaceFrameTimeProc();
    void recognizeResultNotify(bool bPass);
signals:
    void enabledChanged(bool bEnable);

    void beginGrapFaceImage();
    void endGrapFaceImage();

    void newGrapImage(const GrapImageData& data);

    void beginRecognize();
    void endRecognize(bool result, double confidence);

    void noVideoInputSignal();
    void recognizeFinish(const HFResult &result);
};
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
還可以使用Q_ENUMS將列舉型別註冊到QML中。

1.2 將C++類註冊為QML可用型別
qmlRegisterType<OpenCVCamera>("HFR.OpenCV", 1, 0, "OpenCVCamera");
1
1.3 在QML中使用匯入的型別
import HFR.IDCard 1.0 

IDCardReader {
    id: idCardReader;
}
1
2
3
4
5
1.4 將C++物件設定為QML上下文
在C++中構造一個物件,將這個物件設定為QML的上下文屬性,是QML環境中直接使用該屬性。
如將pCamera,pCameraPreview物件設定為QML環境上下文,在QML中就可以直接訪問和使用:

OpenCVCamera *pCamera = new OpenCVCamera();
QObject::connect(pCamera, SIGNAL(newGrapImage(const GrapImageData&)), pGrapImageModel, SLOT(addGrapImage(const GrapImageData&)));

OpenCVCameraPreview* pCameraPreview = new OpenCVCameraPreview();

engine.rootContext()->setContextProperty("camera", pCamera);
engine.rootContext()->setContextProperty("cameraPreview", pCameraPreview);
1
2
3
4
5
6
7
QML中使用:

camera.recognize(idCardReader.name,
                 idCardReader.sex,
                 idCardReader.nation,
                 idCardReader.birthday,
                 idCardReader.photoPath,
                 idCardReader.address,
                 idCardReader.cardNumber
                 );
1
2
3
4
5
6
7
8
cameraPreview.enabled = false;
1
二、在C++中使用QML物件
在C++中使用QML物件的步驟如下:
1. 使用objectName查詢到QML物件。

QObject *root = NULL;
QList<QObject*> rootObjects = engine.rootObjects();
for (int i = 0; i < rootObjects.size(); i++) {
    if (rootObjects.at(i)->objectName() == "root") {
        root = rootObjects.at(i);
        break;
    }
}
1
2
3
4
5
6
7
8
使用QMetaObject::invokeMethod來呼叫QML函式。
if (g_Root) {
    QMetaObject::invokeMethod(g_Root, "showMsg",
        Q_ARG(QVariant, QObject::tr("人臉檢測模組載入失敗")));
}
1
2
3
4
關於“C++與QML的混合程式設計”可以參考:
1. Qt官方文件:Integrating QML and C++
2. http://blog.csdn.net/foruok/article/details/32698603

人臉識別系統專案地址:https://gitee.com/china_jeffery/HFR_OpenSource


————————————————
版權宣告:本文為CSDN博主「china_jeffery」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/china_jeffery/art