2012-03-28 17 views

Antwort

41

Wie von Acme erwähnt, können Sie cv::compare verwenden, obwohl es nicht so sauber ist, wie Sie hoffen könnten.
Im folgende Beispiel wird cv::compare unter Verwendung des != operator genannt:

// Get a matrix with non-zero values at points where the 
// two matrices have different values 
cv::Mat diff = a != b; 
// Equal if no elements disagree 
bool eq = cv::countNonZero(diff) == 0; 

Vermutlich wäre es schneller, wenn die Elemente im Vergleich zu nur durchlaufen? Wenn Sie den Typ wissen, könnten Sie die STL equal Funktion:

bool eq = std::equal(a.begin<uchar>(), a.end<uchar>(), b.begin<uchar>()); 
+5

'bool eq = cv :: countNonZero (a! = B) == 0;'. Ich denke, das ist einigermaßen sauber. Am ärgerlichsten ist, dass Sie den Vergleichsoperator mit dem vergleichen müssen, was Sie eigentlich wissen wollen ('! =' Anstelle von '=='), da es keine 'countZero()' -Funktion gibt. – nobar

+3

Die cv :: Mat kann oder kann nicht kontinuierlich, ich bin nicht sicher, dass die Bytes Auffüllen von jeder Zeile den gleichen Wert hat. – StereoMatching

+3

Ja, aber ich glaube, dass die Mat-Iteratoren sich darum kümmern? http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-begin –

1

Wie von Acme und Tim erwähnt, können Sie cv::compare verwenden. Dies ist der Code, den ich vergleichen verwenden, um meine cv::Mat:

bool matIsEqual(const cv::Mat mat1, const cv::Mat mat2){ 
    // treat two empty mat as identical as well 
    if (mat1.empty() && mat2.empty()) { 
     return true; 
    } 
    // if dimensionality of two mat is not identical, these two mat is not identical 
    if (mat1.cols != mat2.cols || mat1.rows != mat2.rows || mat1.dims != mat2.dims) { 
     return false; 
    } 
    cv::Mat diff; 
    cv::compare(mat1, mat2, diff, cv::CMP_NE); 
    int nz = cv::countNonZero(diff); 
    return nz==0; 
} 

Es ist wichtig, dass die Funktion stehen cv::countNonZero only works with cv::Mat of one channel, also wenn Sie benötigen zwei cv::Mat Bilder vergleichen zu können, müssen Sie zuerst Ihre cv::Mat auf diese Weise konvertieren:

Mat gray1, gray2; 
cvtColor(InputMat1, gray1, CV_BGR2GRAY); 
cvtColor(InputMat2, gray2, CV_BGR2GRAY); 

wo InputMat1 und InputMat2 sind die cv::Mat Sie vergleichen möchten. Danach können Sie die Funktion aufrufen kann:

bool equal = matsEqual(gray1, gray2); 

ich diesen Code dieser Seite nahm: OpenCV: compare whether two Mat is identical

hoffe, dass ich diese Hilfe Sie.

+2

Durch die Umwandlung der Bilder in Graustufen verlieren Sie Informationen und möglicherweise machen Sie identische 2-farbige Bilder ursprünglich unterschiedlich. – Antonio

1

Dies ist der Code, den ich Generika vergleichen verwenden (nicht auf Abmessungen oder Typ von Elementen abhängig) cv::Mat Instanzen:

bool matIsEqual(const cv::Mat Mat1, const cv::Mat Mat2) 
{ 
    if(Mat1.dims == Mat2.dims && 
    Mat1.size == Mat2.size && 
    Mat1.elemSize() == Mat2.elemSize()) 
    { 
    if(Mat1.isContinuous() && Mat2.isContinuous()) 
    { 
     return 0==memcmp(Mat1.ptr(), Mat2.ptr(), Mat1.total()*Mat1.elemSize()); 
    } 
    else 
    { 
     const cv::Mat* arrays[] = {&Mat1, &Mat2, 0}; 
     uchar* ptrs[2]; 
     cv::NAryMatIterator it(arrays, ptrs, 2); 
     for(unsigned int p = 0; p < it.nplanes; p++, ++it) 
     if(0!=memcmp(it.ptrs[0], it.ptrs[1], it.size*Mat1.elemSize())) 
      return false; 

     return true; 
    } 
    } 

    return false; 
} 

Ich verstehe nicht, warum cv::Mat kein Betreiber dieses == nach hat Implementierung.

1

Ich benutze diese:

bool areEqual(const cv::Mat& a, const cv::Mat& b) { 
    cv::Mat temp; 
    cv::bitwise_xor(a,b,temp); //It vectorizes well with SSE/NEON 
    return !(cv::countNonZero(temp)); 
} 

Wenn Sie diesen Vorgang mehrmals zu tun haben, können Sie diese in eine Klasse machen, müssen temp als Mitglied und verhindern, dass das Bild jedes Mal zugeordnet werden. Detail: Machen Sie temp veränderbar, so dass areEqual eine const Methode sein kann.

Beachten Sie jedoch, dass cv::countNonZero only works with cv::Mat of one channel. Es ist Overkill, aber in diesem Fall könnte man cv::split verwenden, um jeden Kanal in separate Bilder zu teilen und cv::countNonZero auf ihnen zu tun.

8

Die folgende auch für Mehrkanal-Matrizen arbeiten:

bool isEqual = (sum(img1 != img2) == Scalar(0,0,0,0)); 

Da sum Matrizen mit 1 bis 4 Kanälen annehmen, und gibt ein Scalar, wo das Element auf [0] das Ergebnis der Summe ist, für den ersten Kanal und so weiter.

0

Eine weitere Möglichkeit, eine einzelne Funktion zu verwenden, wäre mit:

bool areIdentical = !cv::norm(img1,img2,NORM_L1); 

Da L1-Norm wird als ∑I|img1(I)−img2(I)| berechnet

Referenz: OpenCV norm

Verwandte Themen