目录
cv::CV_Assert() & cv::CV_DbgAsser()
cv::CV_Error() & cv::CV_Error_()
工具函数
OpenCV提供一些专用功能,可用于更有效地处理计算机视觉应用中普遍出现的数学和其他问题。它们被称为工具函数。工具函数包含数学操作、测试、错误生产、内存与线程处理、优化及其他的工具。
工具函数和系统函数:
函数名称 | 描述 |
---|---|
cv::alignPtr() | 对齐指针到给定字节数 |
cv::alignSize() | 将缓冲区大小与给定的字节数对齐 |
cv::allocate() | 分配一个C风格的数组对象 |
cv::cubeRoot() | 计算一个数的立方根 |
cv::CV_Assert() | 如果给出的条件不为真,则抛出异常 |
cv::deallocate() | 释放一个C风格的数组对象 |
cv::error() | 指示错误并抛出异常 |
cv::fastAtan2() | 向量的二维角度的计算 |
cv::fastFree() | 释放一个内存缓冲区 |
cv::fastMalloc() | 分配一个对齐的内存缓冲区 |
cv::format() | 以sprintf类型格式创建一个STL字符串 |
cv::getCPUTickCount() | 从内部CPU计时器获得tick计数 |
cv::getNumThreads() | 获得当前OpenCV使用的线程数 |
cv::getOptimalDFTSize() | 计算要传递给cv::DFT()的数组的最适宜大小 |
cv::getThreadNum() | 获得当前线程的索引 |
cv::getTickCount() | 获得系统的tick计数 |
cv::getTickFrequency() | 获得每秒的tick数 |
cv::setNumThreads() | 设定OpenCV使用的线程数 |
cv::setUseOptimized() | 开启或关闭优化代码(SSE2等) |
cv::useOptimized() | 指示代码优化的启用 |
CV_Error() | 构造cv:Exception(从固定的字符串)并抛出异常的一个宏 |
CV_Error_() | 构造cv:Exception(从格式化的字符串)并抛出异常的一个宏 |
cvIsInf() | 判断一个浮点数x是否无穷 |
cvIsNaN() | 判断一个浮点数x是否不是一个数 |
cvRound() | 判断一个浮点数x到最近的整数 |
cvCeil() | 近似一个浮点数x到不小于x的最近的整数(向上取整) |
cvFloor() | 近似一个浮点数x到不大于x的最近的整数(向下取整) |
cv::alignPtr()
template<typename _Tp >
static _Tp* cv::alignPtr(
_Tp *ptr,
int n = (int)sizeof(_Tp)
)
参数:
ptr 需要对齐的指针
n 必须是2的幂的对齐大小。
函数返回值为对齐后的指针地址
将指针与指定的字节数对齐。该函数返回与输入指针相同类型的对齐指针:
(_Tp*)(((size_t)ptr + n-1) & -n)
在某些架构上,只有能被指定数(如4,16)整除的内存地址才能够被访问,否则程序会crash,或者出现错误的结果,或者数据的访问变慢。
opencv2.0以上版本很多指针都是被对齐过的,使指针地址能够被16整除。opencv中的内存一般是通过malloc分配,不能保证都是都能被16整除,此时需要截断,CV2.0在 malloc 是多申请一个指针的空间,这个指针指向 malloc 得到的真实内存地址,只在 free 时使用它。
对于指向任意地址的一个指针,OpenCV中可以使用cv::alignPtr()函数将其位移到后面最近的一个能整除n的地址,其中n必须是一个2的幂。
关于 &-n:n是2的幂,其二进制也就只有一个1,比如n默认为16的时候为00010000,取负数得到111110000,效果是对于2k ,得到一个低k为0,其他位为1的数,拿这个数(-n)和别的数做与操作,等于把别的数的低k位截没了。这样得到的数必然是2k 的倍数(低k位为0的数必然是2k 的倍数)。这一效果仅对n=2^k成立。
cv::alignSize()
static size_t cv::alignSize(
size_t sz,
int n = sizeof(T)
);
参数:
sz:要对齐的缓冲区大小。
n:必须是2的幂的对齐大小
将缓冲区的大小与指定的字节数对齐。
该函数返回大于或等于sz且可被n整除的最小数:(计算此缓冲区应该的大小,以便包含大小为n个整数的对象)
(s + n – 1) & -n
cv::allocate()
template<class T>
T* cv::allocate(
size_t sz; //数组大小,n * sizeof(T)
);
该函数与数组形式的new相似,都分配了含n个T类型对象的C风格数组,为每个对象调用默认构造函数并返回指向数组中第一个对象的指针。
示例: void cv::AutoBuffer<_Tp, fixed_size>::allocate(size_t size);
分配大小为 size 的新缓冲区。如果size 足够小,则使用栈分配的缓冲区。
template<typename _Tp, size_t fixed_size=4096/sizeof(_Tp)+8>
class CV_EXPORTS AutoBuffer
{
public:
typedef _Tp value_type;
enum { buffer_padding = (int)((16 + sizeof(_Tp) - 1)/sizeof(_Tp)) };
//! the default contructor
AutoBuffer();
//! constructor taking the real buffer size
AutoBuffer(size_t _size);
//! destructor. calls deallocate()
~AutoBuffer();
//! allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used
void allocate(size_t _size);
//! deallocates the buffer if it was dynamically allocated
void deallocate();
//! returns pointer to the real buffer, stack-allocated or head-allocated
operator _Tp* ();
//! returns read-only pointer to the real buffer, stack-allocated or head-allocated
operator const _Tp* () const;
protected:
//! pointer to the real buffer, can point to buf if the buffer is small enough
_Tp* ptr;
//! size of the real buffer
size_t size;
//! pre-allocated buffer
_Tp buf[fixed_size+buffer_padding];
};
cv::AutoBuffer<int> b;
b[0] = 1;
cout << b.size() << endl;
cv::deallocate()
template<T>
void cv::deallocate(
T* ptr, //需要释放的buffer指针
size_t sz //buffer的大小,n * sizeof(T)
);
cv::deallocate()函数与数组形式的delete相似,都释放含有n个T类型对象的C风格数组,为每个对象调用析构函数。
cv::deallocate()用于释放由cv::allocate()分配的对象,元素n必须与分配的n一致。
cv::fastAtan2()
float cv::fastAtan2(
float y, //向量的y坐标
float x //向量的x坐标
);
以度为单位计算二维向量的角度,函数fastAtan2 计算输入2D矢量的全范围角度,角度从0-360°不等,精度约为0.3°。
cv::cubeRoot()
float cv::cubeRoot(
float x
);
double cv::cubeRoot(
double x
);
这个函数计算变量x的立方根,负数值的x也能正确处理,返回负值。
cv::CV_Assert() & cv::CV_DbgAsser()
#define CV_Assert(expr)
do {
if(!!(expr)) ;
else
cv::error( cv::Error::StsAssert, #expr, CV_Func, __FILE__, __LINE__ );
} while(0)
CV_Assert()是一个宏,它会测试传递给它的表达式,如果表达式为false,它将抛出异常。
CV_DbgAsser()只可用于Debug模式。
cv::error()
void cv::error(
const cv::Exception &ex
);
这个函数大多数是由CV_ERROR() 和CV_ERROR_()调用的,这些宏带着在异常中展示的信息,为你打包好,然后传递最终的异常结果给cv::error();
cv::CV_Error() & cv::CV_Error_()
//example
CV_Error(ecode, estring);
CV_Error_(ecode, fmt, ...);
cv::CV_Error() 宏允许传递一个错误代码ecode和一个固定C风格的字符串estring,然后将其打包进cv::Exception,进而传递给cv::error()进行处理。
如果需要在运行过程中构建消息,那么使用宏CV_Error_,允许传递一个错误码ecode,和一个sprintf()风格的字符串后面紧跟着各种变量参数,就是sprintf()所需要的。
cv::fastFree()
void cv::fastFree(
void *ptr
);
释放由cv::fastMalloc() 分配的内存。
cv::fastMalloc()
void* cv::fastMalloc(
size_t size //需要分配的buffer大小
);
cv::fastMalloc()工作机制与 malloc()类似,但它会进行内存对齐。这意味着如果传递的缓存区大小超过16比特,返回的缓冲区会被对齐到16比特的边界。
cv::format()
string cv::format(
const char* fmt, //格式化字符串
... //vargs, 类似sprintf()
);
这个函数本质上与标准库中的sprintf()相同,它不需要从访问者获得一个字符缓存区,而是构建一个STL字符并返回它。它对Exception()构造函数格式化错误信息很有用。
cv::getCPUTickCount()
int64 cv::getCPUTickCount(void);
这个函数返回CPU的ticks数量,包括但不限于x86架构。
这个函数对于初始化随机数生成器这样的任务很适用。
cv::getNumThreads()
int cv::getNumThreads(void);
返回当前OpenCV适用的线程数。
cv::getOptimalDFTSize()
int cv::getOptimalDFTSize(int n);
cv::getOptimalDFTSize()的一般输入为图片的实际大小,并返回应给传递给cv::dft()的数组大小。
cv::getThreadNum()
int cv::getThreadNum(void);
如果OpenCV库编译时,添加了OpenMP支持,则返回当前执行的线程的索引(从零开始)。
cv::getTickCount()
long int cv::getTickCount(void);
该函数返回了与一些体系结构相关的时间的tick计数。
每个tick时间可以用cv::getTickFrequency()计算。
该函数比cv::getCPUTickCount()应用更广,它不会受线程跑在那个核或CPU降频等底层问题的影响。
cv::getTickFrequency()
double cv::getTickFrequency(void); //返回每秒的滴答数。
该函数返回每秒的滴答数。
为了计算某些事件发生的时间,只需要在函数调用前后调用cv::getTickCount(),两个时间相减并除以cv::getTickFrequency()的返回值即可。
double t = (double)getTickCount();
// do something ...
t = ((double)getTickCount() - t)/getTickFrequency();
cv::setNumThreads()
void cv::setNumThreads(int nthreads); //设置OpenCV可以使用线程的数目
当OpenCV编译时加入了OpenMP的支持,这个函数可以设定OpenMP区域使用的线程数。
如果nthreads为0,则线程数量被重新定为默认值。
cv::setUseOptimized()
void cv::setUseOptimized(bool on_off);
默认情况下,优化例程是启用的,除非你在安装时禁用它。可以使用cv::setUseOptimized()在任何时候开启和关闭这些优化。
对优化用法的全局标志的测试是在opencv库函数中相对较高的级别上完成的。这表示在任何其他的例程(或函数)运行的时候,都不应该调用cv::setUseOptimized()。
cv::useOptimized()
bool cv::useOptimized(void);
返回值:
true:优化在当前是开启的
false:优化是关闭的
在任何时候,都可以使用cv::useOptimized()来检查优化的全局标记的状态。
cvIsInf()
int cvIsInf(double x);
如果x是 正负无穷, 则cvIsInf()返回值是1, 否则返回0.
cvIsNaN()
int cvIsNaN(double x);
如果x不是一个数,cvIsNaN()返回1,否则返回0.
cvRound()
int cvRound(double x);
给定一个浮点数x,cvRound()计算与x最近的整数。如果输入值超出32位整型表示的范围,结果就是undefined(未定义)
cvCeil()
int cvCeil(
float x
);
给定一个浮点数x, cvCeil()计算不小于x的最小整数(向上取整)。如果输入超出了32位整数的表示范围,则结果返回未定义(undefined)。
cvFloor()
int cvFloor(
float x
);
给定一个浮点数x, cvCeil()计算不大于x的最小整数(向下取整)。如果输入超出了32位整数的表示范围,则结果返回未定义(undefined)。
练习
-
找到并打开cxtyes.h,通读并找到很多转换帮助函数。
a. 选择一个负的浮点数
b. 计算它的绝对值,近似,向上取整,向下取整
c. 产生一些随机数
d. 生成一个浮点数的cv::Point2f, 把它转换成整型的cv::Point,把cv::Point 转换成cv::Point2f.
int main()
{
srand(time(NULL));
float a = -3.14;
cout << "绝对值:" << cv::abs(a) << ". 近似:" << cvRound(a) << ". 向上取整:" << cvCeil(a) << ". 向下取整:"
<< cvFloor(a) << endl;
//cv::RNG rng(rand());
//int x1 = (int)rng % 1000;
//cout << x1 << endl;
//cv::Point2f p1(rng.uniform(0.0, 1000.0), rng.uniform(0.0, 1000.0));
//cout << p1 << endl;
//cv::Point p2 = (cv::Point)p1;
//cout << p2 << endl;
CvPoint point1 = cvPoint(50, 50);
cout << "(" << point.x << ", " << point.y << ")" <<endl;
CvPoint2D32f pointf1 = cvPointTo32f(point1);
cout << "(" << pointf1.x << ", " << pointf1.y << ")" <<endl;
CvPoint2D32f pointf2 = cvPoint2D32f(50.9876, 50.3565);
cout << "(" << pointf2.x << ", " << pointf2.y << ")" <<endl;
CvPoint point2 = cvPointFrom32f(pointf2);
cout << "(" << point2.x << ", " << point2.y << ")" <<endl;
return EXIT_SUCCESS;
}
2. 紧凑型矩阵和向量类
a.用cv::Mat33f 和 cv::Vec3f 对象,对应生成一个3 * 3 的矩阵和3行的向量
b.可以直接把他们两个相乘吗?如果不行,为什么?
int main()
{
cv::RNG rng(0);
cv::Matx33f m33(rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0),
rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0),
rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0));
cv::Vec3f v3(rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0), rng.uniform(0.0, 100.0));
cout << m33 << endl;
cout << v3 << endl;
cout << m33 * v3 << endl;
return EXIT_SUCCESS;
}