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
输出数据的自动分配
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
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开源库简介的主要内容,如果未能解决你的问题,请参考以下文章