2010-12-28 2 views
4

Pour une raison quelconque, le code ci-dessous ne fonctionne pas. J'ai deux images 640 * 480 qui sont très similaires mais pas les mêmes (au moins quelques centaines/milliers de pixels devraient être différents).OpenCV compare deux images et obtient des pixels différents

Voici comment je les compare et en comptant différents pixels:

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++; 
     } 
    } 
} 
} 

Maintenant, à la fin je reçois le numéro 3626 qui semble bien. Mais, j'ai essayé d'ouvrir l'une des images dans MS Paint et de tracer des lignes rouges épaisses partout, ce qui devrait augmenter considérablement le nombre de pixels différents. J'ai encore le même numéro: 3626.

Évidemment, je fais quelque chose de mal ici.

Je compare ces images dans une boucle.

Cette ligne est avant que la boucle:

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

ensuite dans la boucle je charger des images comme celle-ci:

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

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

lastFIplImageHeader->imageData = fIplImageHeader->imageData; 

Ainsi lastFIplImageHeader stocke l'image de l'itération précédente et fIplImageHeader stocke la Image actuelle.

Répondre

5

Il me semble que vous ne comptez pas des pixels différents, pas même des pixels.
Vous comptez combien de fois un canal de couleur d'un pixel dans la première image correspond au canal du pixel correspondant dans l'autre image.

Vous avez probablement voulu dire faire quelque chose le long des lignes de:

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

Cela représentera toutefois pas le canal alpha (le cas échéant) et échouera sur les images en niveaux de gris que vous pouvez lire en dehors des limites de la tableau de données.

EDIT: Tant que vous ne libérez pas l'ancienne image, cela devrait aller. Cependant, il pourrait être préférable de faire quelque chose comme:

//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); 

Sinon, au lieu de copier, vous pouvez simplement tenir un pointeur sur l'ancienne image et l'utiliser, aussi longtemps que vous ne relâchez pas.

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

EDIT2: Si la différence est tout ce que vous voulez, vous pouvez jeter un oeil à cvSub (avec les images chargées en niveaux de gris), suivi par cvCountNonZero

+0

Vous avez probablement raison. Mais j'ai toujours le même numéro tout le temps: 3626.Je pense qu'il y a un problème avec la façon dont je stocke l'image précédente dans lastFIplImageHeader. –

+0

J'ai édité ma réponse. – Darcara

+0

Je vais essayer le soir et vous faire savoir comment ça s'est passé. Je n'ai pas beaucoup de temps en ce moment (je suis au travail). –

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); 
} 

Pourriez avoir besoin de quelques ajustements, mais c'est à propos de comment vous le faites. En outre, vous ne devriez pas jouer avec cv * si vous utilisez vraiment C++. Utilisez la nouvelle interface C++ et ne vous souciez pas de libérer des images. lire des images, se souvenir de la précédente devient aussi simple que

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