如何在OpenCV中检查两个矩阵是否相同
how to check whether two matrices are identical in OpenCV
我有两个cv::Mat:m1和m2的实例。它们具有相同的数字类型和大小。OpenCV中是否有任何函数可以返回矩阵是否相同(具有所有相同的值)?
正如Acme所提到的,您可以使用cv::compare
,尽管它并不像您希望的那样干净
在以下示例中,使用!=
运算符调用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) == Scalar(0,0,0,0);
如果你知道类型,你可以使用STL相等函数。Mat迭代器处理数据不连续的情况,并且可以为多通道矩阵使用向量类型。
bool eq = std::equal(a.begin<uchar>(), a.end<uchar>(), b.begin<uchar>());
编辑:已更新以处理多通道案例
以下内容也适用于多通道矩阵:
bool isEqual = (sum(img1 != img2) == Scalar(0,0,0,0));
由于sum接受具有1到4个通道的矩阵,并返回Scalar
,其中[0]处的元素是第一个通道的和的结果,依此类推
使用单个函数的另一种方法是使用:
bool areIdentical = !cv::norm(img1,img2,NORM_L1);
由于L1范数计算为∑I|img1(I)−img2(I)|
参考:OpenCV规范
这是我用来比较通用(不取决于元素的维度或类型)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
根据这个实现没有运算符==
。
将cv::compare与cv::countNonZero结合使用。
一个SO问题可能有助于您进一步OpenCV比较两个图像并获得不同的像素
正如Acme和Tim所提到的,您可以使用cv::compare
。这是我用来比较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;
}
需要注意的是,函数cv::countNonZero
仅适用于一个通道的cv::Mat
,因此,如果您需要比较两个cv::Mat
图像,您需要首先以这种方式转换cv::Mat
:
Mat gray1, gray2;
cvtColor(InputMat1, gray1, CV_BGR2GRAY);
cvtColor(InputMat2, gray2, CV_BGR2GRAY);
其中InputMat1
和InputMat2
是要比较的cv::Mat
。之后,您可以调用函数:
bool equal = matsEqual(gray1, gray2);
我拿了这个网站的代码:OpenCV:比较两个Mat是否相同
我希望这对你有帮助。
我使用这个:
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
仅与一个信道的cv::Mat
一起工作。这太夸张了,但在这种情况下,可以使用cv::split
将每个通道分割成单独的图像,并对其执行cv::countNonZero
。
对于多通道图像,您可以使用cv::Mat::整形来创建单个通道图像,而无需任何额外开销。
安东尼奥的答案更新为
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)));
}
使用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;
}
bool matIsEqual(const cv::Mat &m1, const cv::Mat &m2)
{
if(m1.type() != m2.type())
return false;
if(m1.size() != m2.size())
return false;
return std::equal(m1.begin<uchar>(), m1.end<uchar>(), m2.begin<uchar>());
}
- 如何检查两个 std::向量在小于 O(n) 的时间复杂度内是否相等
- 是否可以在 OpenGL 中的同一调用中呈现两个具有不同索引起点的不同缓冲区?
- 检查两个节点在子节点上是否具有相同状态的更优雅的方法
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 使用XOR查找O(n)-解决方案中的两个字符串是否为变位符
- 给定一个大小为 N 的数组 S,检查是否可以将序列拆分为两个序列
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 如何更好地检查两个 char 变量是否在一组值中?
- 是否有一种标准方法来计算两个 asctime() 值之间的天数
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- 检查两个模板参数是否相同
- 是否可以在 for 循环中添加两个浮点数?
- 是否允许三元运算符在C++中计算两个操作数?
- 使用 SET(C++) 检查两个给定字符串是否是字谜时出现运行时错误
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 检查两个向量是否并行的最有效方法
- 检查两个图是否为补码的功能
- gtest:检查字符串是否等于两个字符串之一
- 如何在c/c++中检查两个任意内存范围是否重叠
- 图问题:找出两个节点是否在每个节点的O(1)时间和O(2)存储中共享同一分支