2010-12-28 20 views
4

Aus irgendeinem Grund funktioniert der folgende Code nicht. Ich habe zwei 640 * 480 Bilder, die sehr ähnlich, aber nicht gleich sind (mindestens einige hundert/tausend Pixel sollten unterschiedlich sein).OpenCV zwei Bilder vergleichen und verschiedene Pixel erhalten

Dies ist, wie ich sie am Vergleichs- und verschiedene Pixel zu zählen:

unsigned char* row; 
unsigned char* row2; 
int count = 0; 

// this happens in a loop 
// fIplImageHeader is current image 
// lastFIplImageHeader is image from previous iteration 
if (NULL != lastFIplImageHeader->imageData) { 
for(int y = 0; y < fIplImageHeader->height; y++) 
{ 
    row = &CV_IMAGE_ELEM(fIplImageHeader, unsigned char, y, 0); 
    row2 = &CV_IMAGE_ELEM(lastFIplImageHeader, unsigned char, y, 0); 
    for(int x = 0; x < fIplImageHeader->width*fIplImageHeader->nChannels; x += fIplImageHeader->nChannels) 
    { 
     if(row[x] != row2[x] || row[x+1] != row2[x+1] || row[x+2] != row2[x+2]) 
      count++; 
     } 
    } 
} 
} 

Jetzt am Ende ich Nummer 3626, die in Ordnung scheinen würden.

Aber ich habe versucht, eines der Bilder in MS Paint zu öffnen und dicke rote Linien darauf zu zeichnen, was die Anzahl der verschiedenen Pixel wesentlich erhöhen sollte. Ich habe wieder die gleiche Nummer: 3626.

Offensichtlich mache ich hier etwas falsch.

Ich vergleiche diese Bilder in einer Schleife.

Diese Linie ist vor der Schleife:

IplImage* lastFIplImageHeader = cvCreateImageHeader(cvSize(640, 480), 8, 3); 

dann innerhalb der Schleife geladen werden I-Bilder wie folgt aus:

IplImage* fIplImageHeader = cvLoadImage(filePath.c_str()); 

// here I compare the pixels (the first code snippet) 

lastFIplImageHeader->imageData = fIplImageHeader->imageData; 

So lastFIplImageHeader wird das Bild von der vorherigen Iteration speichert und fIplImageHeader speichert die aktuelles Bild.

Antwort

5

Es scheint mir, Sie zählen nicht verschiedene Pixel, überhaupt nicht Pixel.
Sie zählen, wie oft ein Farbkanal eines Pixels im ersten Bild mit dem Kanal des entsprechenden Pixels im anderen Bild übereinstimmt.

Sie wahrscheinlich bedeutete etwas entlang der Linien von dem zu tun:

... 
//in the inner for loop 
if(row[x] != row2[x] || row[x+1] != row2[x+1] || row[x+2] != row2[x+2]) 
    count++; 
... 

Dies wird Konto jedoch nicht für den Alphakanal (falls vorhanden) und wird auf Graustufenbilder nicht, wie Sie von Grenzen der ausgelesene könnte Datenfeld.

EDIT: Solange Sie das alte Bild nicht freigeben, sollte es in Ordnung sein. Allerdings könnte es besser sein, etwas zu tun:

//make sure size and channels are correct. 
//If unsure, load the image first and then create with the parameters taken from the loaded image. 
cvCreateImage(cvSize(640, 480), 8, 3); 

//use cvCopy to copy the contents and proceed as normal 
cvCopy(fIplImageHeader , lastFIplImageHeader); 

Alternativ kann anstelle des Kopierens, Sie könnten nur einen Zeiger auf das alte Bild halten und verwenden, solange Sie es nicht loslassen.

lastFIplImageHeader = fIplImageHeader; 
fIplImageHeader = cvLoadImage(filePath.c_str()); 

EDIT2: Wenn der Unterschied alles, was Sie wollen, ist, Sie einen Blick auf cvSub (mit beiden Bilder als Graustufen geladen), gefolgt von cvCountNonZero

+0

Sie haben wahrscheinlich Recht. Aber ich bekomme immer die gleiche Nummer: 3626.Ich denke, es gibt ein Problem mit dem Speichern des vorherigen Bildes in lastFIplImageHeader. –

+0

Ich habe meine Antwort bearbeitet. – Darcara

+0

Ich werde es am Abend versuchen und Sie wissen lassen, wie es gelaufen ist. Ich habe momentan nicht viel Zeit (ich bin in der Arbeit). –

8
int count_diff_pixels(cv::Mat in1, cv::Mat in2) { 
    cv::Mat diff; 
    cv::compare(in1, in2, diff, cv::CMP_NE); 
    return cv::countNonZero(diff); 
} 

Könnte einige Optimierungen benötigen, haben könnte aber das ist, wie du es machst. Außerdem solltest du nicht mit cv * herumspielen, wenn du wirklich C++ benutzt. Verwenden Sie die neue C++ - Schnittstelle, und machen Sie sich keine Sorgen über das Freigeben von Bildern. Bilder zu lesen, erinnert sich an die vorherige wird so einfach wie

cv::Mat prev; 
while (...) { 
    cv::Mat current = cv::imread(fn); // or whereever your image comes from 
    // ... do something ... 
    prev = current; 
} // automatic memory management! 
Verwandte Themen