opencv



  • Hallo,

    Ich habe ein schwarz-weiß Bild.
    Ich habe die Aufgabe, die Mitte eines schwarzen Blocks herauszufinden.

    Zu Anfang habe ich mir gedacht, dass ich den Block mit Linien umschließe, damit ich herausfinde, ob die Koordinaten richtig sind.

    Allerdings klappt es nicht und ich finde den Fehler nicht.

    #include <iostream>
    //#include <math.h>
    #include <cv.h>
    #include <highgui.h>
    
    using namespace std;
    using namespace cv;
    
    int main(int argc, char *argv[])
    {
      IplImage* img = 0;
      int height,width,step,channels, row;
      uchar *data;
      int i=0,j,k;
    
      if(argc<2){
        cerr<<"Usage: " << argv[0] << " <image-file-name> " << endl;
        exit(1);
      }
    
      // load an image  
      img=cvLoadImage(argv[1]);
      if(!img){
        cerr << "Could not load image from file: " << argv[1]<<endl;
        exit(2);
      }
    
    cout << " Simple variable value i=" << i << endl;
    
      // get the image data
      height    = img->height;
      width     = img->width;
      step      = img->widthStep;
      channels  = img->nChannels;
      data      = (uchar *)img->imageData;
      cout << "Processing a " << height << "x" << width << " image with " << channels << " colour channels" << endl;
      //cout << "Step is " << step << endl;
    
      // create a window
      cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
      cvMoveWindow("mainWin", 100, 100);
    
      // NB Your code
     for(i=0;i<height;i++)
     {
        for(j=0;j<width;j++)
        {
           for(k=0;k<channels;k++)
           {
             if(data[i*step+j*channels+k] < 60)
             {
                data[i*step+j*channels+k] = 0;
             }
             else
                data[i*step+j*channels+k] = 255;
           }
        }
     }
     int row_begin = 0, row_end = 0;
     int column_begin = 0, column_end = 0;
    
     for(i=0;i<(height);i++)
     {
        for(j=0;j<(width);j++)
        {
           for(k=0;k<channels;k++)
           {
            if((data[i*step+j*channels+k] == 255) && ((data[(++i)*step+j*channels+k] == 0) || (data[i*step+(++j)*channels+k] == 0) || (data[(++i)*step+ (++j)*channels+k] == 0)))
            {
             row_begin = i;
             column_begin = j;
            }
    
            if((data[i*step+j*channels+k] == 0) && ((data[(++i)*step+j*channels+k] == 255) || (data[i*step+(++j)*channels+k] == 255) || (data[(++i)*step+(++j)*channels+k == 255] )))
            {
             row_end = i;
             column_end = j;
            }
           }
        }
     }
    
    cvLine(img, cvPoint(column_begin,0), cvPoint(column_begin,width), cvScalar(255,0,0), 1);
    cvLine(img, cvPoint(0,row_begin), cvPoint(height,row_begin), cvScalar(255,0,0), 1);
    
    cvLine(img, cvPoint(column_end,0), cvPoint(column_end,width), cvScalar(255,255,0), 1);
    cvLine(img, cvPoint(0,row_end), cvPoint(height,row_end), cvScalar(255,255,0), 1);
    
    cout<<"r_b = "<<row_begin<<endl;
    cout<<"c_b = "<<column_begin<<endl;
    cout<<"r_e = "<<row_end<<endl;
    cout<<"c_e = "<<column_end<<endl;
    
      //End Your code
    
      // show the image
      cvShowImage("mainWin", img );
    
      // wait for a key
      cvWaitKey(0);
    
      // release the image
      cvReleaseImage(&img );
      return 0;
    }
    

    Vielleicht könnt ihr mir weiterhelfen



  • chris2728 schrieb:

    Allerdings klappt es nicht und ich finde den Fehler nicht.

    ...

    Vielleicht könnt ihr mir weiterhelfen

    Bei der Problembeschreibung sicher nicht.



  • Ich habe folgendes Bild:
    http://img213.imageshack.us/img213/17/purgid.jpg

    Diese Bild habe ich in ein schwarz-weißes Bild umgewandelt, so dass nur noch die 2 schwarzen Blöcke zu sehen sind.

    Jetzt brauche ich die Mitte des Blockes der oben links ist.
    Der Plan ist Ende_Koord. - Anfangs_Koord. der Zeilen und Spalten.

    Ich habe versucht diesen Block mittels Linien zu umschließen, um zu sehen ob diese Koordinaten stimmen, aber die sind entweder ganz am Anfang (zeile = 0, spalte = 0) oder irgendwo im nirgendwo.



  • Das hier

    if((data[i*step+j*channels+k] == 255) && ((data[(++i)*step+j*channels+k] == 0) || (data[i*step+(++j)*channels+k] == 0) || (data[(++i)*step+ (++j)*channels+k] == 0)))
    

    ist mit Sicherheit undefiniertes Verhalten. Du willst prüfen, ob Pixel 255 und Nachbar-Pixel 0 sind? Dann prüfe Pixel i und Pixel i+1 (nicht ++i, damit inkrementierst du i vor Auswertung des Terms, und das mehrmals in einem Ausdruck ist irgendwie ziemlich böse 😉 ).



  • Was ich damit machen will ist:

    Wenn der jetzige Pixel weiß ist und der Pixel in der nächsten Zeile bzw. Spalte schwarz ist, ist das der Anfang des Blockes



  • chris2728 schrieb:

    Was ich damit machen will ist:

    Wenn der jetzige Pixel weiß ist und der Pixel in der nächsten Zeile bzw. Spalte schwarz ist, ist das der Anfang des Blockes

    Der Ansatz ist ja auch ok. Aber notiere dann für den Nachbarpixel i+1 (bzw. j+1), nicht ++i.



  • Ich habe mal die zwei IF-Anweisungen in vier aufgeteilt

    if((data[i*step+j*channels+k] == 255) && (data[(i++)*step+j*channels+k] == 0))
             row_begin = i;
    
            if((data[i*step+j*channels+k] == 255) && (data[i*step+(j++)*channels+k] == 0))
             column_begin = j;
    
            if((data[i*step+j*channels+k] == 0) && (data[(i++)*step+j*channels+k] == 255))
             row_end = i;
    
            if((data[i*step+j*channels+k] == 0) && (data[i*step+(j++)*channels+k] == 255))
             column_end = j;
    

    Als Ergebnis kommt bei allen 4 Variablen immer 0



  • *push*



  • chris2728 schrieb:

    if((data[i*step+j*channels+k] == 255) && (data[(i++)*step+j*channels+k] == 0))
             row_begin = i;
    

    Du musst dir wirklich mal ansehen, wie das mit den Pre-/Postincrement-Operatoren funktioniert. Das sind Grundlagen, die du beherrschen solltest, bevor du dich an die Bildverarbeitung herantraust. Deine Bedingung kann hier niemals erfüllt werden, da du i erst nach Auswerten des Ausdrucks inkrementierst. Du fragst also ab: "ist Pixel i,j == 255 und ist Pixel i,j == 0". Erst danach erhöhst du i. Logisch, dass der Pixel nicht beide Werte halten kann, oder? 😉



  • Und überhaupt...i ist doch eine Laufvariable einer deiner For-Schleifen...diese überhaupt zu verändern halte ich für fragwürdig ... jede ausgeführte If-Abfrage ändert den Index...



  • So, wie Du Dir das vorstellst wird das mit Deinem Code aber nichts.

    In Zeile 46-60 versuchst Du, das Bild zu binarisieren. Das geht aber nur, wenn alle Kanäle den selben Wert haben. So wie Du das machst, kommen nicht unbedingt Schwarz-Weiss-Werte raus. Beispiel: Dreikanalbild, rgb mit [49, 61, 49]. Da macht Dein Verfahren dann ein komplett grünes Pixel draus. Du musst erst die Kanäle in einen graukanal wandeln - wenn Du noch kein Graustufenbild hast - und dann denn Schwellenwertoperator anwenden.

    Das Ganze würde ich dann in eine separate FUnktion "binarize" auslagern. Eigentlich sollte OpenCV aber so was schon mitbringen.

    Dass die Verwendung des Preinkrement-Operators in den Zeilen 70 und 76 falsch ist haben diverser Vorposter ja schon gesagt.

    Dein Ansatz, so wie er in den Zeilen 61-84 formuliert ist, würde, selbst wenn die Codierungsfehler nicht drin wären, nur das am weitesten rechts unten liegende Rechteck erkennen.

    Statt dessen solltest Du drei Funktionen schreiben. Eine, die die linke obere Ecke eines Rechtecks im Bild sucht, und eine weitere, die, ausgehend von der vorher gefundenen die korrespondierende rechte, untere Ecke sucht. Und die dritte Funktion ruft zuerst die Erste, und dann die zweite Funktion auf. Um alle Rechtecke zu finden, muss Du dann durch das ganze Bild gehen, wobei Du die Suche n+1 an der rechten oberen (!) Ecke, des zuvor gefundenen Rechtecks starten kannst.

    Und: Lass Dich nicht entmutigen! Aller Anfang ist schwer und Du hast Dir ein Problem ausgesucht, bei dem Du viel über Programmierung und Bildverarbeitung lernen kannst.



  • Übrigens ist es bei solchen Geschichten oft hilfreich, sich die Zwischenschritte auch mal selbst anzusehen. Wenn du dein Bild nicht in einem Control anzeigen kannst, weil du gar kein GUI hast, kannst du es ja als Datei abspeichern. Dann wäre dir z.B. aufgefallen, dass dein Binärbild gar keines ist (habe ich gar nicht gesehen, guter Einwand). Ich zeichne auch manchmal gerne mit verschiedenen Farben ins Bild hinein, was der Algorithmus so macht.


Anmelden zum Antworten