qml+opencv(一)

前言

忽然想起opencv,一直想作人臉識別,但是理論基礎太水,只能慢慢來,去年學習了一會,而後公司讓我去搞app和網絡,就一直擱着,如今學習qml,忽然想能不能在qml裏面使用opencv,因此就有了這篇文章。算法

QQuickItem和QObject

在QML中,可視化的基礎組件是Item,不可視化的就是QtObject,它們對應C++中的QQuickItem和QObject類,擴展QML組件一個繼續基於QML中的Item擴張,還有就是繼承QQuickItem,咱們想把opencv加到QML中,那麼只有繼承QQuickItem了。
怎麼使用,那還要看QML新的渲染機制,Qt5的QML渲染基於OpenGL,其場景的渲染在單獨的線程進行,咱們須要須要QQuickItem返回可以描述場景的對象,就是QSGNode。實現QQuick的updatePaintNode函數就OK了,咱們在updatePaintNode,描述怎麼渲染。markdown

類的關係

OpenCVcapture繼承QOjbect,其是圖像捕獲的基類,OpenCVcamera是OpenCVcapture子類,完成從攝像頭捕獲數據。OpenCVaction類封裝了opencv圖像算法操做。OpenCVshowFrame繼承QQuickItem,實現可視化。網絡

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml/qqml.h>
#include "opencvcamera.h"
#include "opencvshowframe.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    qmlRegisterType<OpenCVcamera>("OpenCV", 1, 0, "OpenCVcamera");
    qmlRegisterType<OpenCVshowFrame>("OpenCV", 1, 0, "OpenCVshowFrame");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import OpenCV 1.0

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true

    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: {

                    //messageDialog.show(qsTr("Open OpenCV triggered"));
                    opencvCamera.m_run = true
                }

            }
            MenuItem {
                text: qsTr("&Close")
                onTriggered: {

                    //messageDialog.show(qsTr("Open OpenCV triggered"));
                    opencvCamera.m_run = false
                }

            }
            MenuItem {
                text: qsTr("E&xit")
                onTriggered: Qt.quit();
            }
        }
    }

    OpenCVcamera {
        id:opencvCamera
        m_cameraId: 1
        m_run: false

        //width: 320
        //height: 240
    }

    OpenCVshowFrame {
        anchors.centerIn: parent
        id:opencvShowFrame
        m_capture: opencvCamera
        m_frameRate: 33
        m_run: true
        width: 480
        height: 320
    }


    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")

        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
}

效果
這裏寫圖片描述
我封裝了輪廓掃描的算法操做。app

updatePaintNode

QSGNode* OpenCVshowFrame::updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
{
    QSGSimpleTextureNode *texture = static_cast<QSGSimpleTextureNode*>(old);
    if (texture == NULL) {
        texture = new QSGSimpleTextureNode();
    }
    QImage img;
    IplImage *iplImage = NULL;
    IplImage *out = NULL;
    if (m_capture) {
        iplImage = static_cast<OpenCVcapture*>(m_capture)->getFrame();
    }
    if (iplImage != NULL) {
        out = doActions(iplImage);
        uchar *imgData = (uchar *)out->imageData;
        //qDebug() << out->depth << out->nChannels;
        img = QImage(imgData, out->width, out->height, QImage::Format_RGB888);
    } else {
        img = QImage(boundingRect().size().toSize(), QImage::Format_RGB888);
    }
    QSGTexture *t = window()->createTextureFromImage(img.scaled(boundingRect().size().toSize()));
    if (t) {
        QSGTexture *tt = texture->texture();
        if (tt) {
            tt->deleteLater();
        }
        texture->setRect(boundingRect());
        texture->setTexture(t);
    }
    if (out) {
        cvReleaseImage(&out);
    }
    return texture;
}

使用了QSGSimpleTextureNode,而後咱們將opencv的圖像,做爲一個QSGTexture,而後返回給渲染的線程進行場景的渲染。函數

這裏還要說下,Qt的QImage,不支持單通道的灰度圖,咱們須要轉換成RGB才能正確的顯示。學習

相關文章
相關標籤/搜索