OpenCV Mat元素类型及其大小

liz*_*isk 34 opencv

我对OpenCV Mat元素类型感到困惑.这是来自文档:

There is a limited fixed set of primitive data types the library can operate on.
That is, array elements should have one of the following types:

8-bit unsigned integer (uchar) 
8-bit signed integer (schar)
16-bit unsigned integer (ushort)
16-bit signed integer (short)
32-bit signed integer (int)
32-bit floating-point number (float)
64-bit floating-point number (double)
...

For these basic types, the following enumeration is applied:
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };
Run Code Online (Sandbox Code Playgroud)

众所周知,C++标准没有以字节为单位定义基本类型的大小,那么他们如何使用这些假设呢?我应该期待什么类型,比方说CV_32S,是int32_t还是int?

Ant*_*nio 5

Miki的答案开始,
在OpenCV 3中,定义已经转移到modules/core/include/opencv2/core/traits.hpp,在那里你可以找到:

/** @brief A helper class for cv::DataType

The class is specialized for each fundamental numerical data type supported by OpenCV. It provides
DataDepth<T>::value constant.
*/
template<typename _Tp> class DataDepth
{
public:
    enum
    {
        value = DataType<_Tp>::depth,
        fmt   = DataType<_Tp>::fmt
    };
};



template<int _depth> class TypeDepth
{
    enum { depth = CV_USRTYPE1 };
    typedef void value_type;
};

template<> class TypeDepth<CV_8U>
{
    enum { depth = CV_8U };
    typedef uchar value_type;
};

template<> class TypeDepth<CV_8S>
{
    enum { depth = CV_8S };
    typedef schar value_type;
};

template<> class TypeDepth<CV_16U>
{
    enum { depth = CV_16U };
    typedef ushort value_type;
};

template<> class TypeDepth<CV_16S>
{
    enum { depth = CV_16S };
    typedef short value_type;
};

template<> class TypeDepth<CV_32S>
{
    enum { depth = CV_32S };
    typedef int value_type;
};

template<> class TypeDepth<CV_32F>
{
    enum { depth = CV_32F };
    typedef float value_type;
};

template<> class TypeDepth<CV_64F>
{
    enum { depth = CV_64F };
    typedef double value_type;
};
Run Code Online (Sandbox Code Playgroud)

大多数情况下/编译器中,您应该使用C++精确数据类型.在C++中明确定义的单字节数据类型(CV_8U- > uint8_tCV_8U- > int8_t)不会出现问题.同样为浮子(32位)和双(64位).但是,对于其他数据类型来说,确实使用正确的数据类型(例如在使用方法时),您应该使用例如:at<>

typedef TypeDepth<CV_WHATEVER_YOU_USED_TO_CREATE_YOUR_MAT>::value_type access_type;
myMat.at<access_type>(y,x) = 0;
Run Code Online (Sandbox Code Playgroud)

作为旁注,我很惊讶他们决定采用这种模棱两可的方法,而不是简单地使用确切的数据类型.

因此,关于你的最后一个问题:

我应该期待什么类型,比方说,CV_32S

我相信OpenCV 3中最准确的答案是:

TypeDepth<CV_32S>::value_type
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢。.在大多数情况下,OpenCV不遵循C ++。尽管它是一个很棒的计算机视觉库,但我讨厌用C ++处理它。它总是使我的代码刹车,并使我编写自己感到可耻的代码。 (2认同)

Boy*_*nov -3

简而言之,您提供的表格是正确的。如果要直接访问像素,请将其类型转换为右侧的说明符,例如 CV_32S 是有符号的 32 位。S 始终表示有符号整数(signed char、signed Short、signed int) F 始终表示浮点数(float、double) U 始终表示无符号整数。

该枚举仅在创建或转换 Mat 时使用。这是一种告诉 mat 所需类型的方式,据我了解,它是未使用模板时的 C 前身。

我专门使用 C 功能,为了创建图像,传递以下内容将是错误的:

cvCreateImage(mySize,char, nChannels);
Run Code Online (Sandbox Code Playgroud)

相反,我通过以下内容:

cvCreateImage(mySize, IPL_DEPTH_8U, nChannels);
Run Code Online (Sandbox Code Playgroud)

这里,IPL_DEPTH_8U 是函数使用的标志。该函数本身有一个检查标志的 switch 类型语句。标志的实际值通常是没有意义的,因为它通常由条件语句而不是代数语句控制。