1.10--OpenCV Introduction
一、OpenCv Introduction
OpenCV 使用BSD协议
官方地址:http://opencv.org/
官方下载地址:http://docs.opencv.org/
OpenCV有自己的模块结构,这意味着包含多个共享或静态库,以下是可以获取的模块
Corefunctionality:组合的模块,定义了的基本数据结构,包括多维数矩阵和被所有其他模块使用的基本使用的功能。
mageprocessing:一个图像处理模块包括线性和非线性的图像过滤,图像几何变换(调整、仿射和,透视弯曲,一般的基础变换)
video:视频分析模块,包括运动估计、背景减法,和对象跟踪算法。
· calib3d -基本的多视图几何算法 ,单体和立体相机标定,物体定位,立体通信算法,三维建筑元素
features2d :显著特征探测器,描述符合描述匹配器
objdetect:检测的对象和预定义的类的实例(forexample, faces, eyes, mugs, people, cars, and so on).
highgui :一个易于使用的界面简单UI功能
VideoI/O: 一个易于使用的接口来视频捕获和视频编解码器。
gpu :GPU-accelerated不同OpenCV的算法模块
一些其他辅助模块,如FLANN和谷歌测试包装,Python绑定等等。
二、API概念:
文档的进一步章节描述每个模块的功能,但首先,一定要熟悉所使用的通用API概念
cv Namespace
所有的 OpenCV类和函数都放置在了 cv的namespace中。因此,从代码访问此功能,用cv:: 指示语或者用 usingnamespace cv 指示语
#include "opencv2/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2,CV_RANSAC, 5);
...
Or
#include "opencv2/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2,CV_RANSAC, 5);
...
一些当前或未来的OpenCV外部名称可能与STL冲突或其他库,在这种情况下,使用显式的名称空间说明符解决名称冲突use explicit namespace
自动内存管理
OpenCV自动处理所有内存
首先std::vector, Mat,和其它被函数应用的 数据结构体被函数和方法应用并且带有销毁者(销毁者指的是消除潜在内存当需要的时候)。这就意味着,Mat销毁者不会经常的释放内存。他们将会共享数据。一个destructor消减矩阵的引用计数数据缓存。这块缓存被释放,当且仅当引用计数为0的时候。那是,当没有其它结构引用相同的内存的时候。
相同地,当一个 Mat单例被拷贝,没有真实的数据仅仅是拷贝。反而,引用计数是增加记忆的。那就是有一个其它的拥有者有这块数据。
也有Mat::clone方法,创建一个完整的拷贝矩阵数据。看接下来的例子:
// create a big 8Mb matrix
Mat A(1000, 1000, CV_64F);
// create another header for the same matrix;
// this is an instant operation, regardless of the matrixsize.
Mat B = A;
// create another header for the 3-rd row of A; no datais copied either
Mat C = B.row(3);
// now create a separate copy of the matrix
Mat D = B.clone();
// copy the 5-th row of B to C, that is, copy the 5-throw of A
// to the 3-rd row of A.
B.row(5).copyTo(C);
// now let A and D share the data; after that themodified version
// of A is still referenced by B and C.
A = D;
// now make B an empty matrix (which references no memorybuffers),
// but the modified version of A will still be referencedby C,
// despite that C is just a single row of the original A
B.release();
// finally, make a full copy of C. As a result, the bigmodified
// matrix will be deallocated, since it is not referencedby anyone
C = C.clone();
你能看到Mat 和其它基础数据结构是单一的。但是什么是高级的类或是甚至用户数据类型
被创建带有引用计数管理呢?对他们来说,OpenCV提供了指针模板类,那就和std::shared_ptrC++ 11
里面的相近。所以,而不是用
T* ptr = new T(...);
你可以用
Ptr<T> ptr(new T(...));
自动分配输出数据
OpenCV自动重新分配内存的, 以及大部分时间自动分配内存输出函数参数。所以,如果一个函数有一个或是多个输入数组
(cv::Mat instances) 和一些输出的数组,这些数组是自动释放和分配内存的.输出数组的大小和类型,是由输入的数组大小和类型决定的。如果被需要,函数带有额外的参数(帮助解决输出的数组属性)
Example:
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0);
if(!cap.isOpened()) return -1;
Mat frame, edges;
namedWindow("edges",1);
for(;;)
{
cap >> frame;
cvtColor(frame, edges, COLOR_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if(waitKey(30) >= 0) break;
}
return 0;
}
数组框架是自动分配的 通过 >> 运算符 当video的帧率 和 位深度 被 video模块捕捉
数组的边界是自动分配的 通过 cvtCOlor函数。它有相同的大小和为书读作为输入的数组。
通道的数量是1 因为在第一次 执行循环的时候 ,所有下一个video 帧有相同的分辨率。
如果你以某种方法改变video分辨率,数组会自动释放。
这项技术的关键是Mat::create方法。它会带来要求的数组大小和类型。如果数组准备有指定的
大小和类型,这个方法做不了什么。否则它会释放之前的分配的内存。,如果任何(这部分包括引用计数和比较引用计数为0的),并且然后分一个按照需要的大小分配新的内存。大部分函数调用
Mat::create 方法为了输出数组。并且自动释放输出的数据被应用。
一些明显的异常从 这个约束cv::mixChannels,cv::RNG::fill,并且一小部分其它的函数和方法。他们将不会分配输出的数组,所以你可以提前自己做。
饱和度算法
作为一个计算机视觉库,opencv处理很多像素图片,它们经常是组合编码,8 或是 16位 每个通道,
形式,从而有一个有限的值范围。此外,某些操作图像,比如颜色空间转换,亮度/对比度调整,锐化,复杂的插值(bi-cubic兰索斯)能产生可用的范围值.如果你只是存储最低8(16)位这将导致视觉工件和可能影响进一步的图像分析。为了解决这个问题,使用所谓的饱和算法。例如,存储 R,这个操作的结果,对于一个b位图片,你可能找到相近的值在0..255范围内。
I(x,y)=min(max(round(r),0),255)
同样的规则适用于8位有符号,有符号的16位和无符号类型。在库到处都使用这个语义.在c++代码,它是使用saturate_cast< >类似于标准c++操作.见下文的实现上面提供的公式:
I. at<uchar>(y, x) =saturate_cast<uchar>(r);
uchar是个OpenCV 8位无符号整数类型。在优化的SIMD代码中,诸如paddusb SSE2指令,使用packuswb等等。他们帮助实现完全相同的行为如c++代码。
Note:
色饱和度不会被应用,当 int是32位的时候
错误处理
OpenCV使用异常信号危险错误。当输入的数据有一个正确的格式并且属于指定的值范围,但是算法不能成功因为有这些理由
(例如,优化算法不集中),它的返回一个特殊的错误码(代表,仅是一个布尔变量)。
异常可以被实例 cv::Exception或是它的派生类处理。在它的转换,cv::Exception 是一个派生于std::exception.所以它能被优雅的处理,通过在代码使用其它 C++库组件。
异常抛出使用CV_Error(errcode, description)宏
try
{
... // call OpenCV
}
catch( cv::Exception& e )
{
const char* err_msg = e.what();
std::cout << "exception caught: " <<err_msg << std::endl;
}
多线程 和可重用的
当前的 OpenCV实现是可重用的。那就是,相同的功能,相同的常量方法类的实例,或相同的不是常量的方法,都可以从不同的线程被调用。同样,相同的cv::Mat可以被使用在不同的线程。因为引用计数操作的特殊结构,自动释放。
未完,待续~~~~~~~