Schwerpunkte

HMI / GUI-Frameworks

OpenCV und Qt Quick - ein Einstieg

21. Januar 2019, 13:31 Uhr   |  Berthold Krevert und Torsten Rahn, Software-Entwickler bei basysKom


Fortsetzung des Artikels von Teil 3 .

OpenCV unter Qt Quick

Es ist natürlich auch möglich, neben den von Qt Quick bereitgestellten Elementen wie Rechtecke und Bilder, eigene Elemente zu erstellen – entweder als Komposition zahlreicher Qt-Quick-Elemente oder als Implementierung in C++. Ein Beispiel zeigt das Listing 3.

Listing 3
Item {
    id: root
    width: 300
    height: 300

    CVMat {
        id: inputImage
        source: "foo.jpg"
        anchors.left: parent.left
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        width: parent.width / 2
    }

    CVContour {
        id: resultImage
        input: inputImage
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        width: parent.width / 2
        height: parent.height / 2
    }
}
 

Hier stehen zwei QML-Elemente, die nicht zur Ausstattung des Qt-Quick Frameworks gehören: Das CVMat-Element lädt ein Bild in eine cv::Mat und zeigt es auf der linken Seite des Fensters. Der Quellcode enthält hier exemplarisch die Bilddatei foo.jpg. Das selbsterstellte CVContour-Element soll unter der Haube die Konturen dieses Bildes bestimmen. Zur Entwicklung solcher QML-Elemente auf C++-Seite dient in der Regel die Klasse QQuickItem als Basisklasse: hier wird die Methode QQuickItem::updatePaintNode() (Listing 4) überschrieben.

Listing 4

QSGNode * AbstractMat::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
      QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
      if (!node) {
          node = new QSGSimpleTextureNode();
          QImage img((uchar*) m_cvImage.data, m_cvImage.cols, m_cvImage.rows, m_cvImage.step, QImage::Format_RGB888);
          img = img.rgbSwapped().copy();
          QSGTexture *texture = window()->createTextureFromImage(img);
          node->setTexture(texture);
      }
      node->setRect(boundingRect());
      return node;
}
 

Hier wird ein einfacher Texturknoten für den SceneGraph erzeugt. Dieser Texturknoten erhält den Bildinhalt, über den erläuterten Mechanismus via QImage, aus der cv::Mat als Textur. Es ist auch möglich, dem SceneGraph eigene Knoten hinzuzufügen. So ist ein CVMatNode denkbar, der die Bilddaten einmalig über Grafik-APIs wie OpenGLs glTexImage2D in den Grafikspeicher lädt. Beim Zeichnen muss die Textur nur noch aktiviert werden. Das erspart den Umweg über QImage.

Bei der Implementierung einer neuen QQuickItem-basierten Klasse sollte übrigens im Konstruktor das Flag ItemHasContents gesetzt werden – andernfalls werden die instanzierten Objekte nicht gezeichnet und bleiben unsichtbar. Basierend auf diesem Grundschema kann ein großer Teil der OpenCV-Funktionalität dem Qt-Quick-Framework zugänglich gemacht werden.

OpenCV erkennt HMI-Elemente
© basysKom

Bild 2: OpenCV erkennt Objekte


Referenz [1] stellt ein vollständiges Code-Beispiel zu diesem Artikel zum Herunterladen und Experimentieren (neben OpenCV wird eine Qt-5.10-Installation benötigt). Das Code-Beispiel macht deutlich, wie auf einem Bild einzelne Gegenstände - in diesem Fall Zahnräder - gefunden werden (Bild 2). Dazu wird in der CVContours-Klasse auf OpenCV-Seite die findContours()-Methode verwendet. Vorbereitend muss dazu vorher das Bild über die threshold()-Funktion in ein Schwarzweiß-Bild konvertiert werden (Listing 5).


Listing 5


    Mat gray;
    cvtColor(*mat, gray, COLOR_BGR2GRAY);
    Mat bw;
    threshold(gray, bw, 50, 255, THRESH_BINARY | THRESH_OTSU);
    vector<vector<Point>> contours;

    findContours(bw, contours, RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
 

Anschließend wäre es möglich, die so gefundenen Konturen über die OpenCV-eigene Methode drawContours() zu zeichnen. In unserem Code-Beispiel sammeln wir stattdessen die Polygonzüge in Qt-eigenen Datenstrukturen und exportieren diese als Property nach QML. Basierend darauf werden die Polygone mit dem neuesten Bordmittel von Qt gezeichnet: seit Qt 5.10 gibt es für Qt Quick die Shape-API, über die man nun auch mit QML sehr flexibel polygon- und kurvenbasierte Formen darstellen kann. In unserem Beispiel verwenden wir Shapes, um die Umrisse der detektierten Objekte zu zeichnen und das reguläre QML-Rectangle-Element, um deren Bounding-Boxen darzustellen. Damit können nicht nur QML-basierte Animationen verwendet, sondern auch   QML-basierte Nutzerinteraktionen via Touch integriert werden. Ergebnis ist eine praktisch nahtlose Integration von OpenCVs analytischen Fähigkeiten mit den QML-basierten Bedienelementen.

Seite 4 von 5

1. OpenCV und Qt Quick - ein Einstieg
2. Austausch zwischen den internen Bildformaten
3. Einführung in Qt Quick und QML
4. OpenCV unter Qt Quick
5. Experimentieren mit LiveCV

Auf Facebook teilenAuf Twitter teilenAuf Linkedin teilenVia Mail teilen

Das könnte Sie auch interessieren

KI-Prozessoren mit „Synapsen“ aus Nanodrähten
Zehn Prognosen zur wirtschaftlichen Entwicklung
»Viele Jobs werden vor künstlicher Intelligenz sicher sein«
Professionelle Displays, Kapazitätsausbau und Preisdruck
Kompaktere und günstigere Gassensoren
Augen und Intelligenz für Roboter

Verwandte Artikel

WEKA FACHMEDIEN GmbH