【OpenCV】关于Mat_类的一个问题

发布时间 2023-03-28 17:08:53作者: DoubleLi

* 未经许可,谢绝转载!请尊重原创! 【OpenCV】关于Mat_类的一个问题 *
对于Mat_类,就从文档里面复制点内容做个简单的介绍吧。
The class Mat_<Tp> is a “thin” template wrapper on top of the Mat class. It does not have any extra data fields.While Mat is sufficient in most cases, Mat can be more convenient if you use a lot of element access operations and if you know matrix type at the compilation time.
这个类其实就是Mat的一个子类,平时我自己主要用来操作当数据已知且量较小时的输入,见下面的例子。
这次在看以前写的代码的时候,不经意间发现了下面代码中要展示的问题,这也是本文要说的。

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    // 方式一
    Mat matrix1 = (Mat_<int>(2, 3) << 0, 1, 2,
                                      3, 4, 5);
    cout << matrix1 << endl << endl;

    // 方式二
    Mat matrix2 = *(Mat_<int>(2, 3) << 0, 1, 2,
                                       3, 4, 5);
    cout << matrix2 << endl;

    return 0;
}

在我的代码中几乎都是用的第一种方式,除了有一行代码用的是第二种方式。其实我也没弄明白当时咋个就加了个*。
上面的两种方式产生的结果完全相同。大家可以自己试一下结果。
为什么会产生上面的问题?根本原因就是操作符重载了。下面直接从源码中给出解释。

// 下面的代码源自OpenCV2.4.9
// 上面例子中的操作基本都是由MatCommaInitializer_类来完成的
template<typename _Tp> class MatCommaInitializer_
{
public:
    //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat
    MatCommaInitializer_(Mat_<_Tp>* _m);
    //! the operator that takes the next value and put it to the matrix
    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);
    //! another form of conversion operator
    Mat_<_Tp> operator *() const;
    operator Mat_<_Tp>() const;
protected:
    MatIterator_<_Tp> it;
};

// 对应例子中的方式一
template<typename _Tp> inline MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const
{
    CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() );
    return Mat_<_Tp>(*this->it.m);
}

// 对应例子中的方式二
template<typename _Tp> inline Mat_<_Tp> MatCommaInitializer_<_Tp>::operator *() const
{
    CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() );
    return Mat_<_Tp>(*this->it.m);
}

从上面的代码可以看出,这两种重载其实做了完全一模一样的事情。
相信绝大部分人在用到Mat_这个类的时候都会使用第一种方式,既然偶然的机会让我碰到了这个问题,还是在此做个记录,希望可以帮到大家。
对上第二种方式,在OpenCV3.0.0中已经不复存在了,还是看源码吧。

// 下面的代码源自OpenCV3.0.0
// MatCommaInitializer_
template<typename _Tp> class MatCommaInitializer_
{
public:
    //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat
    MatCommaInitializer_(Mat_<_Tp>* _m);
    //! the operator that takes the next value and put it to the matrix
    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);
    //! another form of conversion operator
    operator Mat_<_Tp>() const;
protected:
    MatIterator_<_Tp> it;
};

// 对应例子中的第一种方式,第二种方式已经被删除
template<typename _Tp> inline
MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const
{
    CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() );
    return Mat_<_Tp>(*this->it.m);
}

从上面OpenCV3.0.0中的源码可以看出,对*的重载已经被删除了。
* 未经许可,谢绝转载!请尊重原创! 【OpenCV】关于Mat_类的一个问题 *