C++ 如何在 OpenCV 中检查两个矩阵是否相同
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9905093/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to check whether two matrices are identical in OpenCV
提问by kirkor
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 (have all the same values)?
我有两个 cv::Mat 实例:m1 和 m2。它们具有相同的数字类型和大小。OpenCV 中是否有任何函数返回矩阵是否相同(具有所有相同的值)?
回答by Tim MB
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:
正如 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) == 0;
Presumably it would be quicker to just iterate through comparing the elements though? If you know the type you could use the STL equalfunction:
据推测,通过比较元素进行迭代会更快吗?如果您知道类型,则可以使用 STL equal函数:
bool eq = std::equal(a.begin<uchar>(), a.end<uchar>(), b.begin<uchar>());
回答by Miki
The following will work also for multi-channel matrices:
以下内容也适用于多通道矩阵:
bool isEqual = (sum(img1 != img2) == Scalar(0,0,0,0));
Since sumaccepts 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.
由于sum接受具有 1 到 4 个通道的矩阵,并返回 a Scalar
,其中 [0] 处的元素是第一个通道的总和的结果,依此类推。
回答by Sadique
Use cv::comparecombined with cv::countNonZero.
将cv::compare与cv::countNonZero结合使用。
An SO question that might help you further OpenCV compare two images and get different pixels
一个可以帮助您进一步OpenCV 比较两个图像并获得不同像素的 SO 问题
回答by Angie Quijano
As mentioned by Acme and Tim, you can use cv::compare
. This is the code I use to compare my cv::Mat
:
正如 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;
}
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:
重要的是要指出该功能cv::countNonZero
仅适用于cv::Mat
一个 channel,因此如果您需要比较两个cv::Mat
图像,您首先需要以cv::Mat
这种方式转换您的:
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:
您要比较的位置InputMat1
和InputMat2
位置cv::Mat
。之后,您可以调用该函数:
bool equal = matsEqual(gray1, gray2);
I took this code of this site: OpenCV: compare whether two Mat is identical
我拿了这个网站的代码:OpenCV:比较两个Mat是否相同
I hope this help you.
我希望这对你有帮助。
回答by fmigneault
Another way using a single function would be to use:
使用单个函数的另一种方法是使用:
bool areIdentical = !cv::norm(img1,img2,NORM_L1);
Since L1 norm is calculated as ∑I|img1(I)?img2(I)|
由于 L1 范数计算为 ∑I|img1(I)?img2(I)|
reference: OpenCV norm
参考:OpenCV 规范
回答by Antonio
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.
如果你要多次执行这个操作,你可以把它做成一个类,temp
作为成员,防止每次都分配图像。细节:使temp
可变的,以便areEqual
可以是一种const
方法。
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.
请注意,这cv::countNonZero
仅适用于cv::Mat
一个频道。这是矫枉过正,但在那种情况下,可以使用cv::split
将每个通道拆分为单独的图像并cv::countNonZero
对其进行处理。
回答by user5309470
This is the code I use to compare generic (not depending on dimensions or type of elements) cv::Mat
instances:
这是我用来比较通用(不取决于元素的尺寸或类型)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;
}
I don't understand, why cv::Mat
does not have an operator ==
according to this implementation.
我不明白,为什么cv::Mat
没有==
根据这个实现的运营商。