2012-03-29 16 views
7

Looping Haben Sie das Buch ‚Learning OpenCV‘ von O'Reilly nicht lange her, und seitdem habe ich viel zu tun alle Beispielcode Umwandlung folgte ich sehe, dass es von OpenCV zu JavaCV, in der Regel durch eine kleine meiner eigenen Modifikation auch. Die ganze Zeit versuche ich, den reinen OpenCV-Code (C-Sprache) so weit wie möglich zu behalten und Java zu vermeiden. Zum Beispiel habe ich alle Schnittstellenelemente direkt über das OpenCV-highgui-Paket in JavaCV und nicht über Java Swing implementiert. Auf diese Weise hoffe ich, um sowohl die OpenCV-Bibliothek und einige C in relativ kurzer Zeit, sowie zur Einführung einer Bibliothek von nützlichen Funktionen erfahren, dass ich in der Lage zu C leicht zu konvertieren, wenn ich entscheiden, später zu reinen OpenCV zu wechseln.Konvertieren von OpenCV Matrix JavaCV

Wie auch immer, habe ich wenig Kenntnisse von C und manchmal in Schwierigkeiten geraten, wenn sie mit Zeigern zu tun. Das Buch empfiehlt den folgenden Code als ein optimales Mittel, durch die durch eine 3-Kanal-Matrix iterieren:

float sum(const CvMat* mat) { 
    float s = 0.0f; 
    for(int row=0; row<mat->rows; row++) { 
     const float* ptr = (const float*)(mat->data.ptr + row * mat->step); 
     for(col=0; col<mat->cols; col++) { 
      s += *ptr++; 
     } 
    } 
    return(s); 
} 

Hier ist die enthaltene Erklärung für diesen Code:

Wenn der Zeiger in die Matrix Rechen Beachten Sie, dass die Matrixelementdaten eine Union sind. Wenn Sie diesen Zeiger de-referenzieren, müssen Sie daher das korrekte -Element der Union angeben, um den richtigen Zeigertyp zu erhalten. Um den Zeiger zu deaktivieren, müssen Sie das Schrittelement der Matrix verwenden. Wie zuvor erwähnt, ist das Element des Schritts in Bytes. Um sicherzugehen, ist es am besten, die Zeigerarithmetik in Bytes und> in den entsprechenden Typ umzusetzen, in diesem Fall float. Obwohl die CVMat-Struktur das Konzept der Höhe und Breite für die Kompatibilität mit der älteren IplImage-Struktur hat, verwenden wir stattdessen die aktuelleren Zeilen und Spalten. Beachten Sie schließlich, dass wir ptr für> jede Zeile neu berechnen, anstatt einfach am Anfang zu beginnen und dann diesen Zeiger um bei jedem Lesen zu erhöhen. Th ist vielleicht übertrieben erscheinen, sondern weil die CvMat Datenzeiger konnten nur Punkt zu einem ROI innerhalb eines größeren Arrays, gibt es keine Garantie, dass die Daten sein> zusammenhängende über die Reihen.

Allerdings habe ich Probleme, es in JavaCV zu konvertieren. Das ptr-Feld (Zeiger) scheint ein Float zu sein, was mich verwirrt. Ich gehe davon aus, dass es sich nicht um einen "Zeiger" handelt, sondern um einen Wert, dem der Wert jedes Pixels hinzugefügt wird. Oder ist es tatsächlich ein Zeiger, der den s-Wert für alle Spalten innerhalb einer gegebenen Zeile die Gesamtsumme findet?

Wie auch immer, würde ich dankbar, wenn jemand für mich etwas JavaCV Code für eine equivelent Schleife schreiben ist. Ich weiß, dass es bei einem CvMat andere Möglichkeiten gibt, auf jedes Pixel zuzugreifen, aber bei AFAIK sind sie alle weniger effizient oder ungenau.

+0

Soweit ich aus dem Beispiel sehen kann, wird die Matrix als 2-dimensionale, Graustufen, Float-Datentyp adressiert. Alle Pixelwerte werden zu s summiert, was zur kumulativen Helligkeit wird. Die PTR ist tatsächlich ein Zeiger, der an einem beliebigen Punkt in dem Array weist und 'PTR [x] gleich' '(const float *) (MAT-> data.ptr + Zeile * MAT-> Schritt) [x]; '. ptr wird für ein gegebenes Pixel initialisiert und inkrementiert, so dass '[x]' nicht notwendig ist und einfach mit '*', gleich '[0] ', dereferenziert wird. –

+0

@zom Wie wird der Zeiger inkrementiert? Von dem, was ich von dem Code verstehe, ist der Zeiger den Wert des Pixels zugewiesen? Oder ist ihm die Position des Pixels zugewiesen? Wenn der frühere Fall, dann wenn die Operation "ptr ++" auftritt, würde nicht der zugewiesene Pixelwert zunehmen, anstatt den Zeiger dazu zu bringen, auf das nächste Pixel zu zeigen? Und wenn der spätere Fall ist, wann und wo ist der tatsächliche Wert des Pixels, das "s" zugeordnet ist? So viele Fragen. –

+0

lesen Sie zuerst: http://c-faq.com/ptrs/index.html –

Antwort

6

Das spezielle Beispiel würden Sie auf Java optimal umgesetzt als

werden liefern
float sum(CvMat mat) { 
    final int rows = mat.rows(); 
    final int cols = mat.cols(); 
    final int step = mat.step()/4; 
    FloatBuffer buf = mat.getFloatBuffer(); 
    float s = 0.0f; 
    for (int row = 0; row < rows; row++) { 
     buf.position(row * step); 
     for (int col = 0; col< cols; col++) { 
      s += buf.get(); 
     } 
    } 
    return s; 
} 
+0

Danke Sam, nette Antwort vom Entwickler von JavaCV selbst! Ich habe das schon gelöst, aber –

+0

Ok, großartig! aber du solltest die Antwort trotzdem akzeptieren, wenn sie die Frage beantwortet, die du ursprünglich gepostet hast, dass ... –

0

Hier ist eine Variante I durch Versuch bekam schließlich zu & Fehler; für das Durchlaufen einer 3-Kanal-Matrix und das Anwenden eines sehr einfachen Filters (ich glaube, Samuels Beispiel deckt bereits die Summierung von Graustufenwerten gut ab).

static IplImage setSaturate_sv(IplImage imgIn) { 
    IplImage imgOut = cvCloneImage(imgIn); 
    ByteBuffer pointer = imgOut.getByteBuffer(); 

    int height = imgIn.height(); 
    int width = imgIn.width(); 
    int widthStep = imgIn.widthStep(); 
    int nChannels = imgIn.nChannels(); 
    int rowIndex; 

    for (int row = 0; row < height; row++) { 
     rowIndex = row * widthStep; 
     for (int col = 0; col < width; col++) { 
      pointer.put((rowIndex + (col * nChannels) + 1), (byte)255); 
      pointer.put((rowIndex + (col * nChannels) + 2), (byte)255); 
      pointer.put((rowIndex + (col * nChannels) + 3), /* leave alone */); 
     } 
    } 
    return imgOut; 
}