2012-03-28 8 views

Odpowiedz

41

Jak wspomniano przez Acme, można użyć cv::compare choć nie jest tak czysty, jak można mieć nadzieję.
W poniższym przykładzie cv::compare nazywa przy użyciu != operator:

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

Prawdopodobnie byłoby szybciej po prostu iterację porównując elementy chociaż? Jeśli znasz typ można użyć funkcji STL equal:

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

'bool eq = cv :: countNonZero (a! = B) == 0;'. Myślę, że jest to rozsądnie czyste. Najbardziej irytujące jest to, że musisz odwrócić operator porównania w porównaniu do tego, co naprawdę chcesz wiedzieć ('! =' Zamiast '== '), ponieważ nie ma funkcji' countZero() '. – nobar

+3

Cv :: Mat może, ale nie musi ciągły, nie jestem pewien, czy bajty dopełnienia każdego wiersza mają tę samą wartość. – StereoMatching

+3

Tak, ale wierzę, że iteratory Mat zajmują się tym za Ciebie? http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-begin –

1

Jak wspomniano przez Acme i Tim, można użyć cv::compare. Jest to kod używam porównać mój 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; 
} 

Ważne jest, aby wyróżniać się, że funkcja cv::countNonZero only works with cv::Mat of one channel, więc jeśli trzeba porównać dwa cv::Mat zdjęć musisz najpierw przekonwertować swojej cv::Mat w ten sposób:

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

gdzie InputMat1 i InputMat2cv::Mat chcesz porównać. Po tym można wywołać funkcję:

bool equal = matsEqual(gray1, gray2); 

Wziąłem ten kod z tej strony: OpenCV: compare whether two Mat is identical

Mam nadzieję, że to pomoże.

+2

Konwersja obrazów na skalę szarości powoduje utratę informacji i potencjalnie może spowodować, że identyczne obrazy dwukolorowe będą początkowo inne. – Antonio

1

Jest to kod używam porównać rodzajowe (nie w zależności od wymiarów i rodzaju elementów) cv::Mat przypadki:

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

Nie rozumiem, dlaczego cv::Mat nie ma operatora == według tego realizacja.

1

Używam tego:

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

Jeśli trzeba zrobić tę operację wiele razy, można zrobić to w klasie, mają temp jako członka i zapobiec obraz ma zostać przydzielona za każdym razem. Szczegóły: zmień wartość temp, aby areEqual mogła być metodą const.

Pamiętaj jednak, że cv::countNonZero only works with cv::Mat of one channel. To przesada, ale w takim przypadku można użyć cv::split, aby podzielić każdy kanał na osobne obrazy i wykonać na nich cv::countNonZero.

8

następuje będzie działać również matryc wielokanałowych:

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

Ponieważ sum przyjmuje matryce z 1 do 4 kanałów i zwraca Scalar, w którym element w [0] jest wynikiem sumy dla pierwszego kanału i tak dalej.

0

Innym sposobem, za pomocą pojedynczej funkcji byłoby użyć:

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

Ponieważ norma L1 jest obliczane jako ∑I|img1(I)−img2(I)|

referencyjny: OpenCV norm

Powiązane problemy