2013-05-07 16 views
6

Ich bin mit dem in OpenCV 1.1 verwendeten IPL-Bildformat gut vertraut. Allerdings verwende ich die neueste Version 2.4 und möchte auf die C++ - Schnittstelle von OpenCV wechseln. Hier ist die Methode, mit der ich die Pixel in einem Bild zuzugreifen:Von IPLImage zu Mat

int step = img->widthStep; 
int height = img->height; 
int width = img->width; 
unsigned char* data = (unsigned char*) img->imageData; 

for (int i=0; i<height; i++) 
{ 
    for (int j=0; j<step; j+=3)   // 3 is the number of channels. 
    { 
     if (data[i*step + j] > 200)  // For blue 
      data[i*step + j] = 255; 

     if (data[i*step + j + 1] > 200) // For green 
      data[i*step + j + 1] = 255; 

     if (data[i*step + j + 2] > 200) // For red 
      data[i*step + j + 2] = 255; 
    } 
} 

Ich brauche Hilfe für die Umwandlung genau diesen Codeblockes mit der Mattenstruktur. Ich finde hier und da einige Funktionen, aber es wird sehr hilfreich sein, wenn ich die genaue Umsetzung der obigen paar Zeilen als Ganzes bekomme.

Antwort

8
// Mat mat; // a bgr, CV_8UC3 mat 

for (int i=0; i<mat.rows; i++) 
{ 
    // get a new pointer per row. this replaces fumbling with widthstep, etc. 
    // also a pointer to a Vec3b pixel, so no need for channel offset, either 
    Vec3b *pix = mat.ptr<Vec3b>(i); 
    for (int j=0; j<mat.cols; j++) 
    { 
     Vec3b & p = pix[j]; 
     if (p[0] > 200) p[0] = 255; 
     if (p[1] > 200) p[1] = 255; 
     if (p[2] > 200) p[2] = 255; 
    } 
} 
3

Zuerst können Sie die gleiche Operation auf IPLImage ausführen und den integrierten Konstruktor von Mat verwenden, um es zu konvertieren.

Zweitens scheint Ihr Code übermäßig kompliziert zu sein, da Sie die gleiche Operation für alle 3 Dimensionen durchführen. Hier finden Sie aufgeräumter (in Mat-Notation):

unsigned char* data = (unsigned char*) img.data; 

for (int i = 0; i < image.cols * image.rows * image.channels(); ++i) { 
    if (*data > 200) *data = 255; 
    ++data; 
} 

Wenn Sie die THRES für die Kanäle wollen anders sein, dann gilt:

unsigned char* data = (unsigned char*) img.data; 
assert(image.channels() == 3); 

for (int i = 0; i < image.cols * image.rows; ++i) { 
    if (*data > 200) *data = 255; 
    ++data; 
    if (*data > 201) *data = 255; 
    ++data; 
    if (*data > 202) *data = 255; 
    ++data; 
} 
+0

tun alles in IPL-Bild und dann die Umwandlung zurück - wird diese schnell genug sein? Ich möchte nicht, dass dieser Prozess etwas zusätzliche Verarbeitungszeit benötigt. Und zu diesem über Komplikation Sache - das ist nur ein Beispiel-Code, nehme an, dass ich verschiedene Schwellenwerte für rot, grün und blau geben muss. Wird Ihre Methode dann funktionieren? – Soumyajit

+1

Wenn Sie zwischen Mat und IplImage konvertieren, haben Sie die Möglichkeit, die Daten zu kopieren oder nicht. Wenn Sie nicht kopieren, ist der Overhead wirklich klein. Selbst wenn Sie kopieren, bezweifle ich, dass der Aufwand signifikant ist, da Ihre gesamte Verarbeitung länger als 1 Sekunde dauert. Hinzugefügt für verschiedene Schwellenwerte. – guinny

+0

Ihr Code funktioniert nicht, wenn die Matrix einen Schritt hat. Dies ist z.B. für Matrix-Header, die als ROI einer anderen Matrix erstellt werden. Verwenden Sie Iteratoren oder Zeilenzeigerzugriff, um solche Fehler zu vermeiden! – ypnos