I have two instances of cv::Mat : m1 and m2. They are of the same numeric type and sizes. Is there any function in OpenCV that returns whether the matrices are identical (ha
I use this:
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) );
}
If you have to do this operation many times, you can make this into a class, have temp
as member and prevent the image to be allocated every time. Detail: Make temp
mutable so that areEqual
can be a const
method.
Note though that cv::countNonZero only works with cv::Mat of one channel. It's overkill, but in that case one could use cv::split to split each channel into separate images and do cv::countNonZero
on them.
As mentioned by Acme, you can use cv::compare although it is not as clean as you might hope.
In the following example, cv::compare
is called by using the != 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;
Presumably it would be quicker to just iterate through comparing the elements though? If you know the type you could use the STL equal function:
bool eq = std::equal(a.begin<uchar>(), a.end<uchar>(), b.begin<uchar>());
For multichannel images, you could use cv::Mat::reshape to create a single channel image without any extra overhead.
An update of Antonio's answer would be
bool areEqual(const cv::Mat& a, const cv::Mat& b)
{
cv::Mat temp;
cv::bitwise_xor(a,b,temp);
return !(cv::countNonZero(temp.reshape(1)));
}
Use cv::compare combined with cv::countNonZero.
An SO question that might help you further OpenCV compare two images and get different pixels
As mentioned by Acme and Tim, you can use cv::compare
. This is the code I use to compare my 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;
}
It is important to stand out that the function cv::countNonZero only works with cv::Mat of one channel, so if you need to compare two cv::Mat
images, you need first to convert your cv::Mat
in this way:
Mat gray1, gray2;
cvtColor(InputMat1, gray1, CV_BGR2GRAY);
cvtColor(InputMat2, gray2, CV_BGR2GRAY);
where InputMat1
and InputMat2
are the cv::Mat
you want to compare.
After that you can call the function:
bool equal = matsEqual(gray1, gray2);
I took this code of this site: OpenCV: compare whether two Mat is identical
I hope this help you.
The following will work also for multi-channel matrices:
bool isEqual = (sum(img1 != img2) == Scalar(0,0,0,0));
Since sum accepts matrices with 1 to 4 channels, and returns a Scalar
, where the element at [0] is the result of the sum for first channel, and so on.