cv::DataType<>为OpenCV中用于提取数据类型的模板,主要是利用C++ traits技术,实现算法与数据类型 的分离,增加算法兼容性,<learning OpenCV3>中对DataType的介绍如下:

When OpenCV library functions need to communicate the concept of a particular data type, they do so by creating an object of type cv::DataType<>. cv::DataType<> itself is a template, and so the actual objects passed around are specializations of this template. This is an example of what in C++ are generally called traits.This allows the cv::DataType<> object to contain both runtime information about the type, as well as typedef statements in its own definition that allow it to refer to the same type at compile time.

cv::DataType<>作为数据类型提取模板,可以按照实际需要用于传递特定数据类型,在图像处理过程中,所涉及到的数据类型各种各样,使用traits可以完美使算法能够适应各种数据类型。

Traits

traints技术又被称为特性萃取技术,能够让同一接口适应多种不同的数据类型。在传统的处理过程中,如有不同的数据类型如int, float用到同一种算法时,需要写多个不同的分支,每个分支都需要处理不同类型的数据,这样处理在架构和业务处理上显然非常繁琐,还要提供不同的接口适应不同的数据类型。但幸运的是出现了traints技术,在STL中就是使用该技术将实现算法和容器进行分离。算法本身并不知道传进来的数据类型是什么,traints相当于在接口和实现之间加了一层封装,来隐藏一些细节并选择一个合适的算法。

下面使用一个简单的例子来说明下基本能说明下traints的好处

分别有一个整型数组类cIntArray和浮点数组类cFloatArray,每个类都有一个方法求其数组的和,并且可以根据不同的数据类型选择到具体的类的求和方法,主要思路是首先分别实现cIntArray和cFloatArray类数组求和,然后中间封装一层根据不同的数据类型选择到相应的求和方法,其主要实现如下:

class cIntArray
{int a[10];
public:cIntArray(){for (int i = 0; i < 10; i++){a[i] = i + 1;}}int GetSum(int times){int sum = 0;for (int i = 0; i < 10; i++){sum += a[i];}return  sum*times;}
};class cFloatArray
{float f[10];
public:cFloatArray(){for (int i = 1; i <= 10; i++){f[i - 1] = 1.0f / i;}}float GetSum(float times){float sum = 0.0f;for (int i = 0; i < 10; i++){sum += f[i];}return sum * times;}
};template <class T> class cApply
{
public:float GetSum(T &t, float inpara){return t.GetSum(inpara);}
};

cIntArray和cFloatArray分别为整型和浮点型的数组实现,在cApply中根据C++中的template参数推导机制根据T的类类型来调用相应不同的类的实现,应用层调用其接口方法如下:

#include <stdio.h>using namespace std;
void main()
{cIntArray intary;cFloatArray fltary;cApply<cIntArray> c1;cApply<cFloatArray> c2;cout << "3 times of sum of int array is: " << c1.GetSum(intary, 3) << endl;cout << "3.2 times of sum of float array is: " << c2.GetSum(fltary, 3.2f) << endl;
}

运行结果:

3 times of sum of int array is: 165
       3.2 times of sum of float array is: 9.3727

上述例子还不能明显说明traits的好处,因为traits是一个模板类技术,将上述cIntArray和cFloatArray两个类修改名字,全部修改为cApply,相当于套用cApply类,cApply类进一步修改将class T修改为按照数据类型参数推断,则上述例子进一步修改为如下:

template<typename _Tp> class cApply
{public:_Tp value[10];cApply(){}
};template<> class cApply<int>
{
public:int value[10];cApply(){}};template<> class cApply<float>
{
public:float value[10];cApply(){}
};

上述例子修改为如上所述,其中所有的数组名字修改为value, 在cApply模板中value的数据类型与_Tp相关,对例子进行了初步抽象,一个cApply模块初步模型基本完成, cApply称为实例化模板, template<> class cApply<int>和template<> class cApply<float>称之为具体实例化,在实际调用过程中具体实例化要高于模板,意思就是说如果在创建过程中,其如果有其具体实例化,则先调用其实例化,如果没有则调用模块,下面对例子进行一个改造说明问题:

using namespace std;template<typename _Tp> class cApply
{
public:_Tp value[10];cApply(){cout << "call not find, cann temple" << endl;}
};template<> class cApply<int>
{
public:int value[10];cApply(){for (int i = 0; i < 10; i++){value[i] = i + 1;}cout << "call int  first" << endl;}};template<> class cApply<float>
{
public:float value[10];cApply(){for (int i = 1; i <= 10; i++){value[i - 1] = 1.0f / i;}cout << "call float first" << endl;}
};void main()
{cApply<int> c1;cApply<float> c2;cApply<double> c3;
}

本节例子中 int 和float 具体的cApply实例化进行了实现,而double没有具体的实例化,double将会调用模板的构造函数,运行结果如下:

例子经过上述改造已经基本上对traits进行了了解,但是GetSum返回值问题还未解决,template机制只是解决了输入参数数据类型的问题,很多时候其函数的返回值与输入的数据类型有关比如本用例中的GetSum函数,其返回值与输入的类型有关,《STL源码剖析》解决了函数的返回值随着入参数据类型的不同的问题,在类中添加声明内嵌入型来解决,利用typename来定义函数返回值,cApply模板类可以演进成如下:

template<typename _Tp> class cApply
{
public:typedef _Tp value_type;_Tp value[10];cApply(){cout << "call not find, cann temple" << endl;}typename cApply<_Tp>::value_type GetSum(_Tp times){}
};

int 和 float具体实例化类修改为如下:

template<typename _Tp> class cApply
{
public:typedef _Tp value_type;_Tp value[10];cApply(){}typename cApply<_Tp>::value_type GetSum(_Tp times){return 0;}
};template<> class cApply<int>
{
public:int value[10];cApply(){for (int i = 0; i < 10; i++){value[i] = i + 1;}}int GetSum(int times){int sum = 0;for (int i = 0; i < 10; i++){sum += value[i];}return  sum*times;}};template<> class cApply<float>
{
public:float value[10];cApply(){for (int i = 1; i <= 10; i++){value[i - 1] = 1.0f / i;}}float GetSum(float times){float sum = 0;for (int i = 0; i < 10; i++){sum += value[i];}return  sum*times;}
};

测试用例如下:

void main()
{cApply<int> c1;cApply<float> c2;cApply<double> c3;cout << "3 times of sum of int array is: " << c1.GetSum(3) << endl;cout << "3.2 times of sum of float array is: " << c2.GetSum(3.2f) << endl;cout << "3.2 times of sum of double array is: " << c3.GetSum(3.2f) << endl;
}

预测结果c1和c2的值应该和之前一样, c3 sum结果值应该为0,因为用的是模板中的sum,其直接返回的为0,实际运行结果:

上述整个用例的演进过程,基本上说明了traits的技术用例。通过traits技术,可以将所有的数据类型统一封装晨成一个接口,以来显示模板的特殊化,来实现不同数据类型的特殊处理。上述例子还缺少对原生指针的类型的提取,如果需要对原生指针类型进行提取,就需要用到traits中的偏特化技术。

DataType

DataType安全依靠Traits技术,OpenCV将库中的所有的数据类型都采用DataType类模板,比如Mat, vec,float等。DataType的模板定义在modules\core\include\opencv2\core\traits.hpp文件中,其定义如下:

template<typename _Tp> class DataType
{
public:
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATEDtypedef _Tp         value_type;typedef value_type  work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 1,depth        = -1,channels     = 1,fmt          = 0,type = CV_MAKETYPE(depth, channels)};
#endif
};

其中channels为数据元素的多少,depth为opencv定义的数据对应的深度,用如下几个宏表示:

#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_16F  7

fmt为一个字符的数据类型代表,其中float用f代表, int用i代表,short用s代表等等。

下面一段话对上述几个参数解释的比较好,以DataType<float>为例:

The first variable, generic_type, is set to 0, as it is zero for all types defined in core.hpp.The depth variable is the data type identifier used by OpenCV.For example, cv::DataDepth<.float>::value resolves to the constant CV_32F.The entry channel is 1 because float is just a single number;we will see an alternative to this in the next example.The variable fmt gives a single-character representation.of the format.In this case, cv::DataDepth<float>::fmt resolves to f.The last entry is type, which is a representation similar to depth, but includes the number of channels(in this case,one).CV_MAKETYPE(CV_32F,1) resolves to CV_32FC1.

该该文件中还定义了一般数据类型的实例化,比如bool, uchar,等等

template<> class DataType<bool>
{
public:typedef bool        value_type;typedef int         work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 0,depth        = CV_8U,channels     = 1,fmt          = (int)'u',type         = CV_MAKETYPE(depth, channels)};
};template<> class DataType<uchar>
{
public:typedef uchar       value_type;typedef int         work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 0,depth        = CV_8U,channels     = 1,fmt          = (int)'u',type         = CV_MAKETYPE(depth, channels)};
};template<> class DataType<schar>
{
public:typedef schar       value_type;typedef int         work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 0,depth        = CV_8S,channels     = 1,fmt          = (int)'c',type         = CV_MAKETYPE(depth, channels)};
};template<> class DataType<char>
{
public:typedef schar       value_type;typedef int         work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 0,depth        = CV_8S,channels     = 1,fmt          = (int)'c',type         = CV_MAKETYPE(depth, channels)};
};template<> class DataType<ushort>
{
public:typedef ushort      value_type;typedef int         work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 0,depth        = CV_16U,channels     = 1,fmt          = (int)'w',type         = CV_MAKETYPE(depth, channels)};
};template<> class DataType<short>
{
public:typedef short       value_type;typedef int         work_type;typedef value_type  channel_type;typedef value_type  vec_type;enum { generic_type = 0,depth        = CV_16S,channels     = 1,fmt          = (int)'s',type         = CV_MAKETYPE(depth, channels)};
};...

OpenCV的基本的数据类型Mat , Vec, Size ,Matx也都实现了其具体实例化,比如:

/*!traits
*/
template<typename _Tp, int m, int n> class DataType< Matx<_Tp, m, n> >
{
public:typedef Matx<_Tp, m, n>                               value_type;typedef Matx<typename DataType<_Tp>::work_type, m, n> work_type;typedef _Tp                                           channel_type;typedef value_type                                    vec_type;enum { generic_type = 0,channels     = m * n,fmt          = traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED,depth        = DataType<channel_type>::depth,type         = CV_MAKETYPE(depth, channels)
#endif};
};

下面为实例化的DataType的基本用法

#include <stdio.h>
#include "opencv2/opencv.hpp"using namespace cv;
using namespace std;void main()
{cout << "value type: " << DataType<Matx44f>::channels << endl;cout << "fmt: " << DataType<Matx44f>::fmt << endl;cout << "type: " << DataType<int>::fmt << endl;cout << "value type: " << DataType<Matx66d>::channels << endl;cout << "fmt: " << DataType<Matx66d>::fmt << endl;//cout << "type: " << DataType<Matx66d>::type << endl;printf("type: %c\n", DataType<float>::fmt);printf("type: %c\n", DataType<Matx66d>::fmt);string s1(1, DataType<float>::fmt);}

运行结果:

OpenCV辅助对象(help objects)(5)_DataType相关推荐

  1. OpenCV辅助对象(help objects)(3)——Ptr

    OpenCV中的Ptr(智能指针)经过多次版本修改之后,在OpenCV4.0版本之后编译器需要指出C++11的编译器才能编译.Ptr类也完全进行了修改,将Ptr修改为了使用C++11中的shared_ ...

  2. OpenCV辅助对象(help objects)(6)_InputArray和OutputArray

    opencv中的cv:DataType<>解决了算法与数据类型分类的问题,使算法能够适应多种类型的数据,以及能够方便提取出数据类型.但是OpenCV的基本数据类型有多多,Mat matx, ...

  3. OpenCV辅助对象(help objects)(4)_Exception

    OpenCV源码中一般程序如果遇到一些异常(比如空指针等之类的)需要跑出异常一般使用Exception类.Exception是OpenCV在C++std::exception异常中进行了再次封装. E ...

  4. OpenCV辅助对象(help objects)(2)_Range

    Range在opencv中经常被用来表示一段连续的整数数字序列,整体数据结构比较简单,有两个元素start 和 end,分别为序列的开始和结束,取值范围为一个半开半闭空间: [start, end), ...

  5. OpenCV辅助对象(help objects)(1)_TermCriteria

    OpenCV除了基本数据结构(Basic data types)之外还有很多的辅助结构才能使opencv使用越来越完善,下面来分析第一个辅助结构TermCriteria,该结构是OpenCV3中经过整 ...

  6. OpenCV的数据类型——辅助对象

    在上一篇文章中,主要介绍了OpenCV的基础数据类型.接下来在本篇文章中将主要对OpenCV的辅助对象进行介绍. cv::TermCriteria类 在很多算法中都存在着循环嵌套,只有满足终止条件时才 ...

  7. OpenCV 实时对象跟踪(质心跟踪)

    本文章先介绍对象跟踪过程,考虑对象跟踪的特点决定使用:质心跟踪算法,然后会一步一步说明质心跟踪算法的实现:最后是如何用python代码实现. 实验效果如下: 对象跟踪过程 进行一组初始的对象检测(如: ...

  8. OpenCV运行对象检测深度学习网络的实例(附完整代码)

    OpenCV运行对象检测深度学习网络的实例 OpenCV运行对象检测深度学习网络的实例 OpenCV运行对象检测深度学习网络的实例 #include <fstream> #include ...

  9. OpenCV收集对象及其分割蒙版的数据集的实例(附完整代码)

    OpenCV收集对象及其分割蒙版的数据集的实例 OpenCV收集对象及其分割蒙版的数据集的实例 OpenCV收集对象及其分割蒙版的数据集的实例 #include "opencv2/core. ...

最新文章

  1. php怎么输出3个函数和,PHP利用var_dump,var_export,print_r三个函数的区别示例
  2. MyBatis超详细介绍——SQL语句构建器类
  3. 风起云涌时,亦是光芒四射时 | LiveVideoStackCon 2020线上峰会日程全公开
  4. Java 11就在这里,您准备好进行切换了吗?
  5. SQL Server - 高可用与灾难恢复(HADR)技术 -- AlwaysOn可用性组(理论篇)
  6. hdu 3068 最长回文 (Manacher算法求最长回文串)
  7. 如何在Linux中查看所有正在运行的进程 1
  8. kubernetes v1.8.8中 RBAC DENY 解决办法
  9. FFmpeg实现多段小视频合成
  10. 「罗马人的故事I 罗马不是一天建成的」读后感
  11. iMX8MM u-boot2021.04移植
  12. kdj买卖指标公式源码_通达信kdj买卖指标公式
  13. Ubuntu如何更新显卡驱动
  14. 走出国门,在安防赛道海外本地化部署已成必然
  15. No qualifying bean of type ‘service‘ available:单元测试报错
  16. 开关造成的毛刺_令人困扰的DAC输出毛刺消灭记
  17. C语言程序设计学习笔记:P3-判断
  18. 原生 js、javaScript 处理十位数(带有小数点的浮点数时间戳)、十三位数、时间戳, 将时间戳转换成 年、月、日、时、分、秒、毫秒、正常的日期格式
  19. 有没有什么大学生搜题比较好用的网站或APP
  20. 软件测试主管应具备的素质,软件测试人员应具备的素质

热门文章

  1. 怎样正确查看Linux的内存占用情况
  2. Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
  3. hadoop--Map Join
  4. linux系统监控和进程管理
  5. 【7集iCore3基础视频】7-2 iCore3原理图介绍
  6. 高性能JavaScript-JS脚本加载与执行对性能的影响
  7. toolstripmanager --工具栏或菜单的合并
  8. 移动开发框架剖析(二) Hammer专业的手势控制
  9. 减肥日程表(WPS文档反馈群253147947)
  10. 怎样在ArcIMS 上实现专题图