openCV开源库简介

Posted FPGA开发圈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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  ptr = new T(...);

    也就是Ptr  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 (y, x) = saturate_cast (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 可以应用于不同的线程。


    文章来源:


以上是关于openCV开源库简介的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 基础功能简介

opencv开源库

开源计算机视觉库 OpenCV 被曝两个严重的任意代码执行漏洞(详情)

caffe依赖库简介

开源!OpenCV预训练模型库

opencv基础ubunu16.04 编译安装包含viz模块的opencv开源库