如何检查OpenCV中两个矩阵是否相同

kir*_*kor 29 c++ opencv

我有两个cv :: Mat实例:m1和m2.它们具有相同的数字类型和大小.OpenCV中是否有任何函数返回矩阵是否相同(具有相同的值)?

Tim*_* MB 46

正如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;
Run Code Online (Sandbox Code Playgroud)

据推测,通过比较元素迭代会更快吗?如果您知道类型,则可以使用STL 功能:

bool eq = std::equal(a.begin<uchar>(), a.end<uchar>(), b.begin<uchar>());
Run Code Online (Sandbox Code Playgroud)

  • `bool eq = cv :: countNonZero(a!= b)== 0;`.我认为这是相当干净的.最令人讨厌的是你必须将比较运算符与你实际想知道的相比(`!=`而不是`==`),因为没有`countZero()`函数. (7认同)
  • cv :: Mat可能连续也可能不连续,我不确定每行的字节填充是否具有相同的值. (3认同)
  • 是的,但我相信Mat迭代器会为您解决这个问题?http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-begin (3认同)

Mik*_*iki 14

以下内容也适用于多通道矩阵:

bool isEqual = (sum(img1 != img2) == Scalar(0,0,0,0));
Run Code Online (Sandbox Code Playgroud)

由于sum接受具有1到4个通道的矩阵,并返回a Scalar,其中[0]处的元素是第一个通道的和的结果,依此类推.


fmi*_*ult 10

使用单个函数的另一种方法是使用:

bool areIdentical = !cv::norm(img1,img2,NORM_L1);
Run Code Online (Sandbox Code Playgroud)

由于 L1 范数计算为 ?I|img1(I)?img2(I)|

参考:OpenCV 规范


小智 8

这是我用来比较通用(不取决于元素的尺寸或类型)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;
}
Run Code Online (Sandbox Code Playgroud)

我不明白,为什么cv::Mat没有==根据这个实现的运营商。


Sad*_*que 7

使用cv :: comparecv :: countNonZero结合使用.

一个可能有助于您进一步OpenCV的SO问题比较两个图像并获得不同的像素


Ang*_*ano 5

如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;
}
Run Code Online (Sandbox Code Playgroud)

重要的是要突出该功能cv::countNonZero仅适用于cv::Mat一个通道,因此,如果需要比较两个cv::Mat图像,则需要首先以cv::Mat这种方式进行转换:

Mat gray1, gray2;
cvtColor(InputMat1, gray1, CV_BGR2GRAY);
cvtColor(InputMat2, gray2, CV_BGR2GRAY);
Run Code Online (Sandbox Code Playgroud)

其中InputMat1InputMat2cv::Mat要比较。之后,您可以调用该函数:

bool equal = matsEqual(gray1, gray2);
Run Code Online (Sandbox Code Playgroud)

我使用了此网站的以下代码:OpenCV:比较两个Mat是否相同

希望对您有所帮助。

  • 通过将图像转换为灰度图像,您会丢失信息,并且有可能使相同的2色图像本来就不同。 (2认同)