我有两个cv :: Mat实例:m1和m2。它们具有相同的数字类型和大小。 OpenCV中是否有任何函数返回矩阵是否相同(具有所有相同的值)?
答案 0 :(得分:44)
正如Acme所提到的,你可以使用cv::compare
,尽管它并不像你希望的那样干净
在以下示例中,使用!=
operator:
cv::compare
// 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;
据推测,通过比较元素迭代会更快吗?如果您知道类型,则可以使用STL equal函数:
bool eq = std::equal(a.begin<uchar>(), a.end<uchar>(), b.begin<uchar>());
答案 1 :(得分:12)
以下内容也适用于多通道矩阵:
bool isEqual = (sum(img1 != img2) == Scalar(0,0,0,0));
由于sum接受具有1到4个通道的矩阵,并返回Scalar
,其中[0]处的元素是第一个通道的总和的结果,依此类推。
答案 2 :(得分:7)
将cv::compare与cv::countNonZero结合使用。
一个可以帮助您进一步帮助您的问题OpenCV compare two images and get different pixels
答案 3 :(得分:3)
我用这个:
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) );
}
如果您必须多次执行此操作,可以将其设置为一个类,将temp
作为成员,并防止每次都分配图像。详细信息:使temp
变为可变,以便areEqual
可以是const
方法。
请注意cv::countNonZero
only works with cv::Mat
of one channel。它有点矫枉过正,但在这种情况下,可以使用cv::split
将每个频道拆分为单独的图片并对其进行cv::countNonZero
。
答案 4 :(得分:3)
使用单一功能的另一种方法是使用:
bool areIdentical = !cv::norm(img1,img2,NORM_L1);
由于L1范数计算为∑I|img1(I)−img2(I)|
参考:OpenCV norm
答案 5 :(得分:1)
这是我用来比较通用的代码(不依赖于元素的维度或类型)cv::Mat
实例:
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;
}
我不明白,为什么cv::Mat
根据此实现没有运算符==
。
答案 6 :(得分:0)
使用cv::countNonZero
的问题在于此功能仅适用于单通道图像。如果要使用多通道图像,则必须分别照顾每个通道。第一步是将图像分成多个通道。正如Antonio所解释的,您可以为此使用cv::split
函数。拆分后,您可以为每个通道使用cv::countNonZero
,并使用迭代对所有通道的结果求和。 cv::Mat::channels
为您提供了频道数。
这是我用来检查两个矩阵是否相同的代码。
bool isEqual(cv::Mat firstImage, cv::Mat secondImage){
cv::Mat dst;
std::vector<cv::Mat>channels;
int count = 0;
cv::bitwise_xor(firstImage, secondImage, dst);
cv::split(dst, channels);
for (int ch = 0; ch<dst.channels();ch++){
count += cv::countNonZero(channels[ch]);
}
return count == 0 ? true : false;
}
答案 7 :(得分:0)
对于多通道图像,您可以使用cv::Mat::reshape创建单个通道图像,而不会产生任何额外开销。
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)));
}