2017-09-21 1 views
1

Mein Titel möglicherweise nicht klar genug, aber bitte schauen Sie sich genau auf die folgende Beschreibung. Vielen Dank im Voraus.Opencv obatin bestimmten Pixel RGB-Wert basierend auf Maske

Ich habe ein RGB-Bild und ein binäres Maskenbild:

Mat img = imread("test.jpg") 
Mat mask = Mat::zeros(img.rows, img.cols, CV_8U); 

einige diejenigen, auf die Maske Geben Sie nehmen die Anzahl der Einsen ist N. Nun ist die Nicht-Null-Koordinaten bekannt sind, auf der Grundlage dieser Koordinaten, wir kann sicherlich das entsprechende Pixel-RGB-Wert des Ursprungs image.I erhalten wissen, dass dies durch den folgenden Code erreicht werden kann:

Mat colors = Mat::zeros(N, 3, CV_8U); 
int counter = 0; 
for (int i = 0; i < mask.rows; i++) 
{ 
    for (int j = 0; j < mask.cols; j++) 
    { 
     if (mask.at<uchar>(i, j) == 1) 
     { 
      colors.at<uchar>(counter, 0) = img.at<Vec3b>(i, j)[0]; 
      colors.at<uchar>(counter, 1) = img.at<Vec3b>(i, j)[1]; 
      colors.at<uchar>(counter, 2) = img.at<Vec3b>(i, j)[2]; 
      counter++; 
     } 
    } 
} 

Und die coords wird wie folgt sein: enter image description here

Allerdings kostet diese zwei Schicht von for-Schleife zu viel Zeit. Ich habe mich gefragt, ob es eine schnellere Methode gibt, Farben zu verwenden, ich hoffe, ihr versteht, was ich vermitteln wollte.

PS: Wenn ich Python verwenden kann, kann dies nur einen Satz in getan werden:

colors = img[mask == 1] 
+0

Warum heißt das Ziel 'Mat'' coords', wenn Sie keine Koordinaten darin speichern, sondern Pixelwerte aus dem Eingangsbild? | Auch dieser Python-Code ist falsch, numpy Arrays sind nicht aufrufbar. Meintest du "img [mask == 1]"? Darüber hinaus erzeugt es auch keine Koordinatenliste. –

+0

Vielen Dank für Ihre Art erinnern :) – Terry

Antwort

1

Wenn Sie mit der Verwendung anderer Open-Source-Bibliothek unter Verwendung von C++ flexibel sind, Armadillo versuchen. Sie können damit alle Operationen der linearen Algebra durchführen und den obigen Code auf eine Zeile reduzieren (ähnlich wie bei Ihrem Python-Code-Snippet).

Oder

findNonZero() Funktion Versuchen und alle Koordinaten in Bild enthält nicht-Null-Werte finden. Überprüfen Sie Folgendes: https://stackoverflow.com/a/19244484/7514664

+0

findNonZero (Maske, nicht-Null-Koordinaten); int Zähler = 0; for (int i = 0; i (Zähler, 0) = img.at (nonzeroCoordinates.at (i) .x, nonzeroCoordinates.at (i) .y) [0]; \t coords.at (Zähler, 1) = img.unter (nicht-nullCoordinates.at (i) .x, nicht-null-Koordinaten (i) .y) [1]; \t (Zähler, 2) = img.at (ungleich Null Koordinaten (i) .x, nicht null Koordinaten (i) .y) [2]; \t Zähler ++; } – Terry

+0

Ich bin mir nicht sicher, ob die obige Methode mein Programm beschleunigen kann ... – Terry

+0

Versuchen Sie dann Armadillo Library zu benutzen. Ich habe Armadillo für solche Operationen benutzt und es ist vergleichsweise schnell im Vergleich zu OpenCV. – Jazz

1

Die Methode .at() ist die langsamste Möglichkeit, auf Werte in C++ zuzugreifen. Am schnellsten ist die Verwendung von Zeigern, aber die beste Vorgehensweise ist ein Iterator. Siehe OpenCV tutorial on scanning images.

Nur eine Anmerkung, obwohl Pythons Syntax für so etwas gut ist, muss es am Ende des Tages immer noch alle Elemente durchlaufen - und da es vorher einiges an Overhead hat, ist es facto langsamer als C++ Schleifen mit Zeigern. Sie müssen unbedingt alle Elemente durchlaufen, unabhängig von Ihrer Bibliothek. Sie müssen für jedes Element Vergleiche mit der Maske anstellen.

+0

Nun Ich denke, ich habe es nicht klar gemacht ... Was ist, wenn die Maskenmatrix spärlich ist? Sie werden viel Zeit damit verbringen, die Matrix zu durchlaufen. Einige exitende Funktionen können ihren modifizierten Algorithmus haben, um mit dieser Situation umzugehen, was ich versuche zu finden. – Terry

+0

Sparse-Matrizen werden unterschiedlich gespeichert, die Nicht-Null-Elemente werden mit ihrem Index gespeichert, sodass Sie einfach mit ihnen indizieren können. Wenn Sie eine spärliche Matrix für die Indexierung benötigen, erstellen Sie eine und verwenden Sie sie für die Indizierung. Allgemeine Masken werden jedoch nicht als dünn besetzte Matrizen gespeichert. Wenn Sie * eine * dünne Matrix von Ihrer Maske erstellen wollen, müssen Sie die Maske immer gleich durchlaufen, nur um sie zu erstellen. –

+0

Keine Sorge, wie man eine Maske erstellt, angenommen, es existiert bereits ... – Terry

0

Compile mit Optimierung aktiviert ist, versuchen diese Version Profilierungs und uns sagen, ob es schneller ist:

vector<Vec3b> colors; 
if (img.isContinuous() && mask.isContinuous()) { 
    auto pimg = img.ptr<Vec3b>(); 
    for (auto pmask = mask.datastart; pmask < mask.dataend; ++pmask, ++pimg) { 
     if (*pmask) 
      colors.emplace_back(*pimg); 
    } 
} 
else { 
    for (int r = 0; r < img.rows; ++r) { 
     auto prowimg = img.ptr<Vec3b>(r); 
     auto prowmask = img.ptr(r); 
     for (int c = 0; c < img.cols; ++c) { 
      if (prowmask[c]) 
       colors.emplace_back(prowimg[c]); 
     } 
    } 
} 

Wenn Sie die Größe der Farben weiß, vorher für den Raum reservieren.

+0

Ich habe Ihre Version versucht, aber wenn ich eine for-Schleife verwenden, um Farben nachzuschlagen, die für (int i = 0; i Terry

+0

Wie haben Sie es überprüft? Ich habe es versucht und es hat die gleichen Ergebnisse wie Ihr Code. Hier finden Sie eine Reihe von Tests: https://ideone.com/1nJuBV –

Verwandte Themen