你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

学习OpenCV(3)了解OpenCV的数据类型-2

2021/12/22 9:35:31

目录

辅助对象

cv::TermCriteria类

cv::Range 类

cv::Ptr 模板和垃圾回收

cv::Exception类和异常处理

cv::DataType<>模板

cv::InputArray类 和 cv::OutputArray类


辅助对象

cv::TermCriteria类

很多算法需要一个终止条件以确定何时退出,终止条件的形式要么是达到允许的有限迭代次数(COUNT或MAX_ITER),要么是某种形式的误差参数(EPS, epsilon)。

cv::TermCriteria对象把一个或两个终止条件封装,以方便传进OpenCV算法函数里。

它有三个成员变量:type, maxCount 以及 epsilon,都可以直接设置。

cv::TermCriteria::COUNT和cv::TermCriteria::MAX_ITER是一样的,可以替换使用。

使用cv::TermCriteria::COUNT:算法在maxCount次迭代之后终止。

使用cv::TermCriteria::EPS:与算法收敛相关的某些度量讲到epsilon以下后终止。

type参数必须进行设置以使用maxCount或者epsilon。

//构造函数
cv::TermCriteria(int type, int maxCount, double epsilon);


cv::TermCriteria tc;
tc.type = cv::TermCriteria::COUNT | cv::TermCriteria::EPS;
tc.maxCount = 1000;
tc.epsilon = 10;

cv::TermCriteria t(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 1000, 1.0);

cv::Range 类

cv::Range类用于确定一个连续的整数序列。cv::Range对象有两个元素start 和 end.

//构造函数
cv::Range(int start, int end);

//范围包含start,不包含end。 [)

成员函数:

使用size()函数可以得到一个range类的元素数量。

使用empty()测试range是否含有元素。

使用cv::Range::all() 获得对象可用范围, 表示所有的行或者所有的列

	cv::Range r(1, 10);
	cout << r.size() << endl; // ----> 9
	cout << r.empty() << endl; // ----> 0

cv::Ptr 模板和垃圾回收

智能指针(smart pointer)是C++中一个非常实用的类型。

为想要封装的对象定义一个指针模板的实例

cv::Ptr<cv::Matx33f> p(new cv::Matx33f);
cv::Ptr<cv::Matx33f> p = makePtr<cv::Matx33f>();

这个模板类的构造函数就拥有指向对应对象的指针。得到一个指针指针p, 这是一个类似指针的对象,你可以随意传递,并且像标准指针一样使用它。

int main()
{
	cv::Ptr<cv::Matx33f> p(new cv::Matx33f);
	*p = cv::Matx33f(1, 2, 3, 4, 5, 6, 7, 8, 9);
	cout << (*p)(2, 2) << endl;
	
	return EXIT_SUCCESS;
}

cv::Ptr()<> 模板类支持多个接口中的与智能指针的引用技术功能相关的附加函数。

特别的,函数addref()和release()增加和减少指针内部的引用计数。

empty()函数确定一个智能指针是否指向一个已经被释放的对象。第二种应用,确定智能指针对象内部对象指针是否出于其他原因而为NULL。

注意:成员函数 delete_obj(), 这是一个引用计数为零时自动调用的函数。默认情况下它什么也不做。

OpenCV3.4.16版本:cv::Ptr<T> 没有delete_obj() 和 addref()成员函数

取代delete_obj()的是void cv::DefaultDeleter()

However, if the pointer must be deleted in a different way, you must specify a custom deleter upon Ptr construction. A deleter is simply a callable object that accepts the pointer as its sole argument. For example, if you want to wrap FILE, you may do so as follows:

然而,如果必须以不同的方式删除指针,则必须在Ptr构造时指定自定义删除器。删除器只接受指针作为唯一参数的可调用对象。例如,如果你想构造FILE,你可以这样做:

Ptr<FILE> f(fopen("myfile.txt", "w"), fclose);
if(!f) throw ...;
fprintf(f, ....);
...
// the file will be closed automatically by f's destructor.

Alternatively, if you want all pointers of a particular type to be deleted the same way, you can specialize DefaultDeleter<T>::operator() for that type, like this:

或者,如果你希望以相同的方式删除特定类型的所有指针,你可以为此指定DefaultDeleter<T>::operator() ,如下所示:

namespace cv {
template<> void DefaultDeleter<FILE>::operator ()(FILE * obj) const
{
    fclose(obj);
}
}

cv::Exception类和异常处理

OpenCV使用异常来处理错误。OpenCV定义了自己的异常类型cv::Exception,它继承自STL的异常类std::exception.

cv::Exception 类型有成员code,err,func, file 和 line, 分别由一个数字的错误码代表,对应表示产生异常的错误的字符串、错误发生的函数名、错误发生的文件和错误出现在文件中的行数。

有几个内置宏用于自己生成异常:

CV_Error(errorcode, description); //会生成并抛出一个有固定文字描述的异常。
CV_Error_(errorcode, printf_fmt_str, [printf-args]);
//以同样的方式工作,但允许使用类似printf格式的字符串和参数代替固定的描述。

CV_Assert(condition);
CV_DbgAssert(condition);
//测试程序中设置的条件(condition),如果条件不符合,则抛出异常。

在较新的OpenCV中,这些宏只能用于Debug模式。

cv::DataType<>模板

注:这个模板已弃用,被单一目的的特征取代 traits::Type 和 traits::Depth

当OpenCV库函数需要传递特定数据类型的概念时,会创建一个cv::DataType<>类型的对象。

这允许cv::DataType<>对象同时包含该类型的运行信息,也包含 允许它在编译的时候指向相同类型的它自己定义时的 typedef声明

原始 OpenCV 数据类型是 unsigned char、bool、signed char、unsigned short、signed short、int、float、double 或这些类型之一的值的元组之一,其中元组中的所有值都具有相同的类型.

列表中的任何原始类型都可以通过 CV_<bit-depth>{U|S|F}C(<number_of_channels>) 形式的标识符定义,例如:uchar CV_8UC1,3 元素浮点元组 CV_32FC3,等等。

能够存储这种原始数据类型的单个实例的通用 OpenCV 结构是Vec。这种类型的多个实例可以存储在 std::vector、Mat、Mat_、SparseMat、SparseMat_或任何其他能够存储Vec实例的容器中。

该数据类型类基本上是用来提供这样的基本数据类型的描述不添加到相应的类的任何字段或方法(和它实际上是不可能的任何添加到原始C / C ++的数据类型)。这种技术在 C++ 中称为类特征。使用的不是DataType本身,而是它的专用版本,例如:

template<> class DataType<uchar>
{
    typedef uchar value_type;
    typedef int work_type;
    typedef uchar channel_type;
    enum { channel_type = CV_8U, channels = 1, fmt='u', type = CV_8U };
};

template<typename _Tp> DataType<std::complex<_Tp> >
{
    typedef std::complex<_Tp> value_type;
    typedef std::complex<_Tp> work_type;
    typedef _Tp channel_type;
    // DataDepth is another helper trait class
    enum { 
        depth = DataDepth<_Tp>::value, 
        //depth是Opencv使用的数据类型标识符,例如cv::DataDepth<float>::value 会被解析为CV_32F.
        
        channels=2, 
        //complex包含两个数据,所以channels是2,若是float则是1,rect有四个数据,则是4
        
        fmt=(channels-1)*256+DataDepth<_Tp>::fmt,
        
        type=CV_MAKETYPE(depth, channels) 
    };
};

#define CV_MAKETYPE(depth, cn)

关于CV_MAKETYPE及其他相关基本类型:

opencv中的CV_MAKETYPE及其他相关基本类型定义(2)_A1367297309的专栏-CSDN博客

此类的主要目的是将编译时类型信息转换为与 OpenCV 兼容的数据类型标识符

// 分配一个 30x40 的浮点矩阵
Mat A(30, 40, DataType<float>::type);
Mat B = Mat_<std::complex<double> >(3, 3);

// 下面的语句将打印 6, 2 ,即 depth == CV_64F, channels == 2
cout << B.depth() << ", " << B.channels() << endl;

因此,这些特征用于告诉 OpenCV 您正在使用哪种数据类型,即使这种类型不是 OpenCV 原生的。例如,上面的矩阵 B 初始化被编译,因为 OpenCV 定义了适当的专用模板类 DataType <complex<_Tp> > 。这种机制对于通用算法实现也很有用(并以这种方式在 OpenCV 中使用)

cv::InputArray类 和 cv::OutputArray类

许多OpenCV的函数都把数组作为变量并把数组作为返回值。

但是OpenCV支持各式各样的数组,为了防止接口复杂,OpenCV定义了cv::InputArray类 和 cv::OutputArray类,它们支持任何数组类型。而且存在cv::InputOutputArray,指定用于就地计算的数据。

cv::InputArray类 和 cv::OutputArray类的区别:前者为常量(只读),后者为可变量。

与cv::InputArray相关的是返回cv::InputArray的特殊函数 cv::noArray(). 一些函数有可选的输出函数,当不需要时,可以传递cv::noArray().