Threads mit QtConcurrent
-
DeckLinkToCv bekommt einen Zeiger als Parameter, das passt nicht. Das Frame muss am Leben erhalten werden. Also evtl. den CComPtr als Kopie übergeben.
Ich würde spontan eher zu einem dedizierten Thread tendieren. Evtl. ein Thread, der einliest, konvertiert, und die Frames in einer Queue ablegt. Und der Hauptthread stellt sie dar oder wie auch immer.Kann es sein, dass du einen ziemlich langsamen Rechner hast? Wundert mich, dass das nicht in Echtzeit geht.
-
Ja, der Rechner ist ein wenig langsamer. Aber selbst wenn er das nicht wäre, würde es doch Sinn machen die Formatwandlung zwecks Perfomance in einem anderen Thread durchzuführen?
Ich meine 25 Bilder die Sekunde nach cv::Mat konvertieren und dann auch noch die Pixelwerte auslesen lassen, dürfte doch für eine ganz gute Auslastung sorgen?
-
@makopo sagte in Threads mit QtConcurrent:
Ich meine 25 Bilder die Sekunde nach cv::Mat konvertieren und dann auch noch die Pixelwerte auslesen lassen, dürfte doch für eine ganz gute Auslastung sorgen?
Glaub ich eher nicht... Ich kann jetzt grad nichts mit Sicherheit behaupten. Ist schon paar Jahre her, dass ich was ähnliches gemacht habe, und ich kann mich auch nicht erinnern, was das jetzt ganz genau war und wie schnell das war. Aber so wie ich mich dran erinnere, war da auch Konvertierung nach OpenCv, dann ein bisschen Verarbeitung und paar einfache Effekte, und Ausgabe. Und das ging in Echtzeit.
Das Einlesen/Konvertieren hatte ich aber über ffmpeg gemacht, mit Hardware-Unterstützung.
-
Okay, bin für jede Mini-Erfahrung dankbar...
Also wenn ich die Pixelwerte für RGB von einer 300 x 200 Pixelgrafik auslesen lassen dauert das über 5 Sekunden bis jeder Pixel auf der Konsole ausgegeben wurde. Für einen 1080p25 Videostream ist das nicht ganz so cool.
Schreit nach einem neuen Rechner, wobei ich meine mal gelesen zu haben das das auch am Compiler liegen könnte.
-
@makopo sagte in Threads mit QtConcurrent:
bis jeder Pixel auf der Konsole ausgegeben wurde.
Das hört sich doch eher nach dem Flaschenhals an. Was machst du da genau?
-
@makopo sagte in Threads mit QtConcurrent:
Okay, bin für jede Mini-Erfahrung dankbar...
Also wenn ich die Pixelwerte für RGB von einer 300 x 200 Pixelgrafik auslesen lassen dauert das über 5 Sekunden bis jeder Pixel auf der Konsole ausgegeben wurde. Für einen 1080p25 Videostream ist das nicht ganz so cool.
Schreit nach einem neuen Rechner, wobei ich meine mal gelesen zu haben das das auch am Compiler liegen könnte.Das hört sich komisch an: Ich habe mal ein bisschen Bildverstehen auf 'ner 800 Mhz CPU gemacht, die in so 'n Fußballroboter eingebaut war. Da musste man ein bisschen aufpassen und hat z.B. nicht jeden Pixel verarbeitet, weil man auch noch andere Sachen machen musste, Aber 300 * 200 * 3 Werte auslesen und ausgeben über 5 Sekunden... Ist das die Ausgabe auf der Konsole? Das dauert schon mal. Wie lange dauert es, wenn du die alle, sagen wir, aufaddierst und nur einen Wert ausgibst? (Ich will die Ausgabe minimieren )
Was für eine CPU hast du denn? Welchen Compiler benutzt du? Und, mit welchen Flags kompilierst du? Wie sieht der Code aus, mit dem du deine Messung gemacht hast?
-
@Mechanics sagte in Threads mit QtConcurrent:
Das hört sich doch eher nach dem Flaschenhals an. Was machst du da genau?
void GraphicScreen::ReadPixelData() { unsigned char r, g, b; cv::Mat frame = cv::imread("C://ImageTest/test.jpg"); for (int x = 0; x < frame.rows; ++x) { cv::Vec3b* pixel = frame.ptr<cv::Vec3b>(x); for (int y = 0; y < frame.cols; ++y) { r = pixel[y][2]; g = pixel[y][1]; b = pixel[y][0]; qDebug() << "R" << r << "G" << g << "B" << b; } } }
Das ist die Funktion mit der ich die Pixel auslese. Vielleicht ist die auch nicht besonders effizient. Und parallel läuft in meinem Programm kein anderer Prozess (also auch nicht das einlesen des Videostreams)
@Schlangenmensch sagte in Threads mit QtConcurrent:
Was für eine CPU hast du denn? Welchen Compiler benutzt du? Und, mit welchen Flags kompilierst du?
CPU: i3 mit 3 GHz (ist mir ein wenig peinlich, aber der Rechner wurde mir gestellt, habe vorher ehrlich gesagt auch nicht darauf geachtet)
Compiler: MSVC2019 C++17
Flags: Bewusst habe ich keine Flags gesetzt. Ich habe über Qt ein makefile erstellt und in VS die Libraries eingebunden. Das war mein Setup. Laufen lassen tue ich das Programm im Debug Mode.Am Anfang des Projekts dachte ich ja auch das sowas theoretisch in Echtzeit funktionieren müsste. Aber dann setzt man die ersten Sachen um und merkt das es doch nicht so funktioniert wie geplant und kommt ins Zweifeln und in Erklärungsnot ^^.
-
@makopo sagte in Threads mit QtConcurrent:
Das ist die Funktion mit der ich die Pixel auslese. Vielleicht ist die auch nicht besonders effizient.
Lass mal das qDebug zum Test weg. Ich vermute, das braucht sehr viel mehr Zeit, als das Auslesen.
-
@makopo sagte in Threads mit QtConcurrent:
Was für eine CPU hast du denn? Welchen Compiler benutzt du? Und, mit welchen Flags kompilierst du?
CPU: i3 mit 3 GHz (ist mir ein wenig peinlich, aber der Rechner wurde mir gestellt, habe vorher ehrlich gesagt auch nicht darauf geachtet)
Compiler: MSVC2019 C++17
Flags: Bewusst habe ich keine Flags gesetzt. Ich habe über Qt ein makefile erstellt und in VS die Libraries eingebunden. Das war mein Setup. Laufen lassen tue ich das Programm im Debug Mode.Die CPU sollte für das bisschen ausreichen.
Visual Studio setzt von sich aus ganz viele verschiedene Compilerflags, je nach verwendeter Konfiguration.Nachdem du QDebug, wie von @Mechanics vorgeschlagen, rausgenommen hast, kannst du die Konfiguration mal auf Release umstellen, kompilieren und ausführen. Das führt dazu, dass Visual Studio die Optimierungsflags setzt und ich meine auch, per Default Debugsymbole ausschaltet.
Ich habe jetzt nicht in die Doku von qDebug geschaut, aber ich würde vermuten, dass das in der Release Konfiguration von QT aus, schon abgeschaltet wird.
Dann ist noch interessant, wie OpenCV und QT kompiliert wurden. Da sollte man dann nämlich auch gegen die "Release" Libs linken.
Generell gilt: Performance im Debug Build zählt nicht
-
@Schlangenmensch sagte in Threads mit QtConcurrent:
Ich habe jetzt nicht in die Doku von qDebug geschaut, aber ich würde vermuten, dass das in der Release Konfiguration von QT aus, schon abgeschaltet wird.
Das sollte auch im Release Build funktionieren.
-
Am Anfang des Projekts dachte ich ja auch das sowas theoretisch in Echtzeit funktionieren müsste
zwei schleifen übern memory um Bildpunkte einzeln auslesen .... glaub nicht.
OpenCV kann Formatkonvertierungen in Echtzeit auch nur mit "Tricks" (simd / multimedia Befehlssätze (AVX) / GPU)Darf ich fragen für was die RGBWerte auslesen willst/musst? "Normal" macht man, wenn es echtzeit sein muss, alles blockweisse .....
Aber wenn die Anforderung heisst, lese die Bildpunkte von einem Image einzeln aus ... wie soll das in Echtzeit gehen?
Das sind bei dir schon mal 300 * 200 * 3 * 30 ? Aufrufe in der sekunde (mit einzelnem Farbkanal) .... wenn nur einen Aufruf pro pixel hasst ... und den rest wegoptimieren könntest.
-
@RHBaum sagte in Threads mit QtConcurrent:
Das sind bei dir schon mal 300 * 200 * 3 * 30 ? Aufrufe in der sekunde (mit einzelnem Farbkanal)
Ja und? Das sind nur 5.4 Mio Aufrufe. Bei mehreren Ghz Takt und 10-30 GB/s Ram Bandbreite.
-
Ich denke mal das das Problem war das
qDebug()
zeilenweise in der Schleife aufgerufen wurde. Stattdessen habe ich versucht, die Pixelwerte für jeden Kanal jeweils in einem Vector zu speichern. Diese Funktion rufe ich dann in der FunktionDrawGraph
auf, die mir aus den Werten einen Graph zeichnen soll.
Draw Graph
wird dann über das Anklicken eines Button aufgerufen und der Graph wird sofort gezeichnet.
Mit einem einzelnen Bild funktioniert es sehr schnell. Wie es mit 25 Bildern die Sekunde im HD Format aussieht kann ich noch nicht sagen, da ich mit der Formatkonvertierung noch nicht weitergegekommen bin.void GraphicScreen::ReadPixelData() { uint redPx, greenPx, bluePx; uint redSum, greenSum, blueSum; //hier wird ein in cv::Mat RGB konvertiertes Format übergeben cv::Mat frame = cv::imread("C://ImageTest/test.jpg"); if (frame.empty()) qDebug() << "No image found in ReadPixelData()."; for (int r = 0; r < frame.rows; ++r) { cv::Vec3b* pixel = frame.ptr<cv::Vec3b>(r); //Vec3b defines a vector with 3 byte entries for (int c = 0; c < frame.cols; ++c) { redPx = pixel[c][2]; greenPx = pixel[c][1]; bluePx = pixel[c][0]; //push single channel pixel into a vector m_redValues.push_back(redPx); m_greenValues.push_back(greenPx); m_blueValues.push_back(bluePx); } } }
cv::Mat GraphicScreen::DrawGraph(int w, int h) { ReadPixelData(); cv::Mat data(m_redValues); qDebug() << "Red:" << m_redValues; cv::Ptr<cv::plot::Plot2d> plot = cv::plot::Plot2d::create(data); cv::Mat image; plot->setPlotBackgroundColor(cv::Scalar(30, 30, 30)); plot->setPlotAxisColor(cv::Scalar(30, 30, 30)); plot->setPlotGridColor(cv::Scalar(30, 30, 30)); plot->setPlotLineColor(cv::Scalar(0, 0, 255)); plot->setShowText(false); plot->render(image); return image; }
So etwas in der Art programmiere ich übrigens (nur ohne Manipulationsmöglichkeit) : Link
-
-
ich hoffe du hasst die vectoren vorher reserved
-
Du bekommst als Ergebniss deiner ReadPixelData funktion genau was ?
So wie ich es sehe das bild in die RGB Komponenten gesplittet .... dein m_redValues, m_greenValues, m_blueValues
(schau dir mal cv::split an)
was ich noch ned ganz verstehe ist cv::plot::Plot2d::create(data);
data ist in deinem Fall der RotKanal vom Bild ....wenn den so plotten willst, wird deine X zu column + row * column vom bild, und Y wird der Farbwert da ....
Glaub nicht das es das ist was du haben willst
-
-
Hi,
@RHBaum sagte in Threads mit QtConcurrent:
ich hoffe du hasst die vectoren vorher reserved
Das habe ich noch nicht gemacht. Würde ich aber einbauen wenn das ganze Gerüst erstmal steht.
@RHBaum sagte in Threads mit QtConcurrent:
Du bekommst als Ergebniss deiner ReadPixelData funktion genau was ?
Über
ReadPixel
greife ich auf einzelnen Vektoren zu.m_redValues
speichert ja die Pixelwerte für Rot und den Vektor übergebe ich dann an die Plot2D Funktion. Ich habe aber schon gemerkt das Plot2D ungeeignet ist, da man damit nicht drei Graphen in einem Koordinatensystem zeichnen kann.
Probiere das Extrahieren nun mit dercv::split
und das zeichnen mitcv:line
.
-
@makopo sagte in Threads mit QtConcurrent:
Das habe ich noch nicht gemacht.
Ich hoffe mit der Zeit wird das auch bei Dir zum reflex Vector wird groß, du weisst die größe -> reserven
Probiere das Extrahieren nun mit der cv::split
Der Unterschied zu deiner Methode: cv::split liefert eine Matrix2D statt einem reinem array (vector)
da ist der unterschied, die matrix kennt ihre X dimensionen, der vector kennt keine (hat nur 1) ... Aber die Daten selber sollten gleich sein.
Vorteil der Matrix , du kannst SIe in OpenCV direkt anzeigen, dann siehst dein Bild als Farbkanal ....Bin nicht sicher ob die cv Matrix2D einen linearen zugriff hat (hab lange nix mehr mit openCV gemacht), wenn nicht muesstes deinen Index in zeile,spalte umrechenen, sollte kein Problem sein, da die Dimensionen ja kennst (damit wie aufn vector zugreifen kannst).
Ich verstehe immer noch nicht, was du fürn diagram zeichnen willst ....
Die y Achse soll dein red farbwert sein ... (und grü und blau) aber was soll die X Achse sein ....Wenn das einm klassisches Farb Histogramm werden soll, dann ist deine X Achse der Helligkeitswert (von 0 - 1) und nix was von der Pixelpostion (row/column) abhängig ist
Da wirst noch bissi rechnen dürfen ....Ciao ...
-
@RHBaum sagte in Threads mit QtConcurrent:
Ich verstehe immer noch nicht, was du fürn diagram zeichnen willst ....
Die y Achse soll dein red farbwert sein ... (und grü und blau) aber was soll die X Achse sein ....Ich bin in der Testphase. Wichtig ist für mich erstmal das ich Werte/Grafiken einlesen und in der GUI darstellen kann. Das der Graph dann erstmal keinen Sinn macht, ist mir relativ egal. Für mich war es als Anfänger, ohne Skript und Vorgabe, erstmal ein Erfolgserlebnis die Pixelwerte als Graph in der GUI ausgeben zu können.
Ein Histogramm benötige ich allerdings auch, aber hier gibt es für OpenCv ja aber eine relativ gutes Tutorial.
Wenn ich nach dieser Definition gehe, dann wäre die x-Achse die Zeit und die y-Achse der Wertebereich von 0 - 255. Und genau das möchte ich später auch abbilden.
-
@makopo sagte in Threads mit QtConcurrent:
Ich verstehe dein Ansinnen das Lernen mit was konkretem praktischen Verbinden zu wollen.Aber ich bin immer noch der Meinung, das man zum Lernen von Grundlagen (Sprache, allgemeine Algorithmic, Abstraktion) nicht gleich mit Rendern/ComputerVision anfangen sollte.
Hier macht man eben vieles anders / Speziell um spezielle Hardware auszunutzen. Das wiederum bedeuted, das man mehr in asynchronen Mustern "denken" muss.
Auch wenn Dein Beispiel hier schon fast das "Hallo World" in der Bildverarbeitung ist, fällts halt doch schwer die Grundlagen dahinter zu erklären.Was Du konkret willst, ist mit den richtigen Biblios nen 3 Zeiler quasi ... und im produktiven Umfeld sollte man das auch nutzen. Aber Lernen würdest dabei halt auch sehr wenig ....
Grundlagen der BildVerarbeitung / Computervision Theorie hingegen solltes sprachneutral lernen und um das praktisch anzuwenden / testen gibts einfachere Sprachen ...
-
Was das Erlernen der Grundlagen angeht gebe ich dir absolut recht. Das merke ich schon an Themen wie dem Threading.
Es handelt es sich hierbei jedoch um ein praktisches Projekt fürs Studium, das ich mir zwar selbst ausgesucht habe (wegen Herausforderung und so), bei dem ich aber keinerlei fachliche Hilfestellung und mit Ausnahme von C++ als Programmiersprache keinerlei Vorgaben durch irgendwen erhalten habe (wahrscheinlich weil es zu speziell ist). Mit Ausnahme dieses Internetz von dem immer alle reden...Und so habe ich mir meine Frameworks zusammengestellt, einen Haufen selbst recherchierter Unterlagen vor mir liegen und versuche das irgendwie zu wuppen. Wobei andere sicherlich auch so mit dem programmieren angefangen haben, könnte ich mir vorstellen.
Vielleicht das nur zur Erklärung (sry fürs Offtopic)...
-
ok, dann ist die Problemstellung auch eine andere ... also Praktikablität ist zweitrangig.
Dann aber trotzdem generell, die Vektoren bräuchtest du nur, wenn du die werte in der binären Form vorliegen haben muesstest, zum beispiel wenn du eine lib damit befeuerst (darstellen etc willst).
Was du aber eher brauchst sind "Akkumulatoren" . (Summe, Mittelwert, Abstand zu einem Bestimmten Punkt ...)
Also ich würd mal damit anfangen, versuchen den Durchschnittlichen Rot/Grün/Blau Wert für ein ganzes Bild (Frame) zu berechnen.
Dann kannst du Dich mal mit der Helligkeit (Grauwert) beschäftigen .... weil für Bildverarbeitung ist der Farbwert im Verhältis zur Heligkeit oft wichtiger ist als der absolute Farbwert.Das Ganze dann ohne kopieren der einzelnen Farbkanäle usw. am besten nur mit dem Bild + speicher für laufvariable und speicher für Ergebnisse. (fast nichts ist schlimmer für die Performance, als wenn man zur laufzeit des Algos dynamisch speicher allokieren muss).
dann das ganze schon als STL Algo (std::for_each), damit es generischer und unabhängiger von den libs wird ...
Dann koennte man mal die ergebnisse Plotten mit Durchschnittlicher Farbwert pro zeit, was bei fixen frameraten nimmer so schwer ist.
Als Nächstes koennte man überlegen, ob es lohnt die Akku funktion zu parallelisieren...
Wobei andere sicherlich auch so mit dem programmieren angefangen haben, könnte ich mir vorstellen
Ja, aber gleich mit sowas ?
Ich hab angefangen mit Basic (bin also kein guter C++ Entwickler ) auf nem Z80 Clone.
Meine ersten Programme waren eher für Lagerhaltung ....