我对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?
从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_t
和CV_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)
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 类型语句。标志的实际值通常是没有意义的,因为它通常由条件语句而不是代数语句控制。