openCV开源库-简介

简介

OpenCV(Open Source Computer Vision Library: http://opencv.org)是一个开源BSD库,该库包括数百个机器视觉算法。该手册基于OpenCV2.X API。是一个C++版本的API。

OpenCV是一个模块化结构,即由几个共享和静态库组成。模块如下:

  • core -一个定义基本数据结构的模块,包括多维数组和其它模块使用的核心函数
  • imgproc-图像处理模块,包括线性非线性滤波,几何图像变化(尺寸变换、仿射、透视、基于表的映射),图像域卷积,直方图等
  • video-视频分析模块,包括运动检测,背景移除,目标跟踪。
  • calib3d-多视图几何算法,一维和三维相机jiaozheng2,目标位置估计,立体匹配算法,三维重构。
  • features2d - 特征检测和描述匹配
  • objdetect -类(如人脸、眼睛、人、车等)的检测
  • highgui-视频抓取、图像以及视频编码接口
  • gpu- GPU对OpenCV不同模块算法的加速
  • ...一些帮助性模块,如FLANN和谷歌测试封装,Python等

API接口的概念

CV命名空间

 所有OpenCV类和函数均位于cv命名空间。所以使用这些函数使用cv::标识符,或者using namespace cv指示符。
#include "opencv2/core/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2, CV_RANSAC, 5);
...
或者
#include "opencv2/core/core.hpp"
using namespace cv;
...
Mat H = findHomography(points1, points2, CV_RANSAC, 5 );
...
当前或者未来OpenCV外部名称可能和STL或者其它库冲突,明确使用命名空间标识符指定以解决该冲突。
Mat a(100, 100, CV_32F);
randu(a, Scalar::all(1), Scalar::all(std::rand()));
cv::log(a, a);
a /= std::log(2.);
自动内存管理
OpenCV 自动处理内存。
首先,std::vector, Mat以及其它数据结构的解析函数在情况允许下回处理内存释放问题,这就意味着就Mat数据结构而言,解析函数并不总是会释放内存。这涉及到数据共享。一个解析函数减少数据矩阵内存的引用计数,只有当引用计数等于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 matrix size.
Mat B = A;
// create another header for the 3-rd row of A; no data is 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-th row of A
// to the 3-rd row of A.
B.row(5).copyTo(C);
// now let A and D share the data; after that the modified version
// of A is still referenced by B and C.
A = D;
// now make B an empty matrix (which references no memory buffers),
// but the modified version of A will still be referenced by 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 big modified
// matrix will be deallocated, since it is not referenced by anyone
C = C.clone();
可以看到使用Mat以及其它基本数据结构很简单。但是更高级的类或者并没内存管理数据结构情况会是怎样的呢?对于它们OpenCV提供Ptr<>模板类,该类类似于C++zhong TR1中的std::shared_ptr。所以不使用裸指针:
T* ptr = new T(...);
使用
Ptr<T> ptr = new T(...);
也就是Ptr<T> ptr封装了一个T类型的实例和一个引用计数,参考ptr的详细描述。

输出数据的自动分配

OpenCV自动释放内存,如果大多数情况下自动为输出函数分配参数空间一样。所以,对于一个有一个或多个输入/出数组(如  cv::Mat)时,输出数组被自动分配或自动重新分配。输出数组的大小和类型由输入数组的大小和类型决定。如果需要,会有额外的参数指明数组的特性。
例如:
#include "cv.h"
#include "highgui.h"

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, CV_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;
}
由于视频帧分辨率和比特数对于视频捕捉模块移植,数组帧内存由>>操作符自动分配。edges数组由 cvtColor  自动分配,大小和比特数同输入数组相同。因为色彩转变函数是CV_BGR2GRAY(彩色到灰度图),所以通道号是1。因为视频帧的分辨率一样,所以在for循环第一次时fram和edges就申请好了,并且只会申请一次。如果图像的分辨率动态改变了,frame和edges会重新分配。
该技术的关键点是Mat::create方法。它接收的矩阵大小和类型参数,如果矩阵已经是该大小和类型,则该方法什么也不做。反之,首先释放先前分配的数据,减少引用计数,然后重新分配矩阵大小。大多数函数为每一个输出矩阵调用Mat::create方法,多以输出数据内存的分配也是自动实现的。

取整算法

作为机器视觉库,OpenCV处理图像像素,这些像素通常被压缩到8-或16-bit每个通道。此外,对图像的操作,如彩色空间变换,亮度/对比度调整,锐度、差值(bi-cubic,Lanczos)可能导致上述bit数溢出。如果只保留结果的低8或16位,视觉假象会影响图像的进一步分析。为了解决这个问题,饱和度算法被采用。例如,为了存储一个计算结果r到8bit,需要找到离其最近的0..255范围的那个值。

I(x,y)=min ( max (round(r), 0), 255)

该方法同样被用于8位、16位有符号和无符号数。在C++代码中,使用saturate_cast<>函数完成,上述公式的实现如下:
I.at<uchar>(y, x) = saturate_cast<uchar>(r);
cv::uchar是一个OpenCV 8bit无符号类型。32为整型数不支持。

固定像素类型,有限的模板类型

大量使用模板也许会导编译和运行时间的增加,对于基本的算法使用模板较好,但对于一个有数千行的算法而言模板并不好。正是由于这个原因以及简化其它无模板语言(如Python、Java、Matlab)的算法实现,OpenCV倾向于使用多态和运行时调度等方法。

因此,可供使用的原始数据类型和库是一个有限的固定集合。即,阵列元素应当是下列类型:

  • 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)
  • 多个相同元素组成的元组。如果这种阵列的元素是前面的元组,该阵列被称为多通道阵列。最大通道数由CV_CN_MAX定义,目前是512. 
对于这些基本类型,一个枚举类型表示:
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };

多通道可由如下选项确定:
  • CV_8UC1 ... CV_64FC4 常量表示通道1到通道4 
  • CV_8UC(n) ... CV_64FC(n) or CV_MAKETYPE(CV_8U, n) ... CV_MAKETYPE(CV_64F, n) macros when the number of channels is more than 4 or unknown at the compilation time.
例如:
Mat mtx(3, 3, CV_32F); // make a 3x3 floating-point matrix
Mat cmtx(10, 1, CV_64FC2); // make a 10x1 2-channel floating-point
                           // matrix (10-element complex vector)
Mat img(Size(1920, 1080), CV_8UC3); // make a 3-channel (color) image
                                    // of 1920 columns and 1080 rows.
Mat grayscale(image.size(), CV_MAKETYPE(image.depth(), 1)); // make a 1-channel image of
                                                            // the same size and same
                                                            // channel type as img

更复杂的元素类型将不能被OpenCV创建和处理。此外,每一个函数仅能处理所有可能阵列的一个子集。通常越复杂的算法支持的子集越小。看下面的典型例子:
  • 脸部识别只支持8-bit灰度和彩色图
  • 线性函数和机器学习算法只支持浮点阵列。
  • 基本函数,如cv::add,支持所有类型。
  • 彩色变化支持8-bit、16-bit无符号和32-bit浮点数。
每个函数支持的类型根据实际使用而定,以后可能扩展。

输入和输出数组

许多OpenCV函数处理2或者多维数组。通常这些函数以cpp:class:Mat作为参数,但有时使用std::vector<>或者 Matx<>更方便,为了避免API重复,引入特殊的“代理”类。基本的代理类是 InputArray,用于处理一个函数的只读数组。由InputArray 衍生出来的OutputArray用于处理一个函数的输出。通常不需要关心这类的中间类型。当一个函数有可选输入输出参数时,使用cv::noArray()传递。

错误处理

OpenCV使用异常标识严重错误。当输入数据类型和数据数据范围均正确时,但是算法发生了错误(如最优化算法不收敛),将返回一个特殊的错误码。


异常可能是cv::Exception类或其衍生实例,cv::Exception衍生于 std::exception,所以可以使用C++库函数处理。

异常通常由CV_Error宏抛出,或者printf之类的CV_Error_和CV_Assert宏。 对于性能关键的代码,可使用CV_DbgAssert(condition) ,由于内存自动管理,错误发生所需的内存会自动分配,如果需要,只需要添加一个用于抓住异常的try声明。

try
{
    ... // call OpenCV
}
catch( cv::Exception& e )
{
    const char* err_msg = e.what();
    std::cout << "exception caught: " << err_msg << std::endl;
}

多线程和重载

当前OpenCV支持完全的重载,相同的 cv::Mat 可以应用于不同的线程。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值