对于OpenCV的开发团队来讲,不断提高OpenCV库是很是重要的。咱们不断考虑那些能够减轻你工做过程的方法,同时还要保障库的灵活性。新的C++接口就是咱们为了这个而开发出来的东西。然而,向后兼容性仍然是很重要的。咱们不想打碎那些你使用更早的OpenCV库写下的代码。所以,咱们为了保障这个事情从而加上了一些函数。在下面的教程中,你会学习到:ios
一、相比于一样使用的初版本的OpenCV库,第二版本中有了什么变化。算法
二、如何在图像中添加一些高斯噪点。安全
三、什么是查找表,为何要用他们。数据结构
你作出改变的第一步就是学习关于图像的一些新的数据结构:Mat-The Basic Image Container这里代替了老旧的CvMat 和ImpImage。使用新的方程看起来更为容易一些。你只须要记住一下几件新的事情。app
OpenCV 2 接受改编。再也不将全部的函数都塞进单一库中。咱们有许多模块,其中每个都包括数据结构和函数相关的某些任务。经过这个方法,若是你只须要OpenCV的一部分,你就不用调用这个库。这就意味着你须要引入那些你须要的头文件。例如:ide
#Include<opencv2/core/core.hpp>函数
#include<opencv3/imgproc/imgproc.hpp>学习
#include<opencv2/highgui/highgui.hpp>ui
全部和OpenCV相关的东西都北方到了cv名字空间(namespace)中从而防止和其余库的数据结构和函数发生名字冲突。所以你须要再任何来自于OpenCV库的东西前面添加cv::关键字或者直接添加这一行代码直接包含全部:spa
using namespace cv;
由于函数已经在命名空间中了,也就不须要在名字前面添加cv前缀。全部的新的可兼容函数不具备这一点,他们遵循驼峰命名法。这就意味名字的第一个字母是小写字母(除非它自己就是一个名字(人名等)像Canny)接下来的单词使用大写字母开头(像copyMakeBorder)。
如今,要记住你须要将你用的全部模块链接到你的应用程序中。在Windows环境下,你须要将使用了的DLL再次添加进全部的二进制的路径中。更多深层次的信息,若是你使用Windows,请阅读 How to build applications with OpenCV inside the Microsoft Visual Studio对于Linux的使用案例,在Using OpenCV with Eclipse(添加CDT)中有所解释。
如今,为了转换Mat 对象,你可使用IplImage或者CvMat操做符。然而在C接口中一般使用的指针,在这里不复存在了。在C++接口中,咱们更多使用Mat 对象。这种对象能够不花费任何代价只须要简单的赋值就能够转换为IplImage和CvMat类型。例如:
Mat I;
IplImager PI=I;
CvMat mI=I;
如今若是你想转换到指针的,就会有一点麻烦。编译器再也不自动决定你想要什么而是你须要明确指定你的目的。也就是调用IplImage和CvMat 操做符而且获得他们的指针。为了的到指针,咱们使用&标记:
Mat I;
IplImage *pI=&I,operator IplImage();
CvMat *mI= &I.opeartor CvMat();
C接口的最大的弊端就是让你本身进行内存管理。你须要知道何时你析构一个再也不用到的内存是安全的而且确保你在程序运行完成后进行,不然你可能就会有内存泄漏的麻烦了。为了解决OpenCV中的这个问题,这里引入了一系列的智能指针。当对象再也不使用时,就会被自动析构掉。使用这个被特殊声明的指针Ptr:
Ptr<IplImage> piI=&I.operator IplImage();
从C的数据结构转换到Mat 是经过将它们传入内部的构造函数完成的。例如:
Mat K(piL),L;
L=Mat(pI);
如今你已经基本完成了混合使用C接口和C++接口的例子。你也将会在OpenCV的实例文件夹中找到源代码。为了帮助你看到二者的不一样:一个是C和C++的混合,另一个则是纯C++。若是你定义DEMO_MIXED_API_USE你就再也不使用第一个。程序将色彩平面分离,而后在上面作一些改动,最后将它们融合到一块儿。
#include<stdio.h>
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
Using namespace cv;
Using namespace std;
#define DEMO_MIXED_API_USE
int main(int argc,char**argv)
{
Const char* imagename=argc>1?argv[1]:”lena.jpg”;
}
#ifdef DEMO_MIXED_API_USE
Ptr<Iplimage> IplI=cvLoadImage(imagename);
If(IplI.empty())
{
Cerr<<”an not load image”<<imagename<<endl;
Return -1;
}
Mat I(IplI);
#else
Mat I=imread(imagename);
If(I.empty())
{
Cerr<<”can not load image”<<imagename<<endl;
Return -1;
}
#endif
在这里你能看到使用了新的结构,咱们再也不有指针问题,尽管使用了老旧的函数,可是最终仍是将结果转换为Mat 对象
Mat I_YUV;
cvtColor(I,I_YUV,COLOR_BGR2YCrCb);
Vector<Mat> planes;
Split(I_YUV,planes);
由于咱们想要将图像中的亮度成分混合,咱们首先将默认RGB色彩系统转换为YUV色域而后将它分离为不一样的色彩平面。这里的程序分离:在第一个示例中使用三个(C语言中的[]操做符,迭代器,读取独立元素)主要的图像遍历算法中的一个来处理每个平面。第二个变化就是咱们在图像中加入高斯噪声而且根据某些方程将它们的通道融合。
MatIterator_<uchar> it=planes[0].begin<uchar>(),it_end=planes[0].end<uchar>();
For(;it!=it_end;++it)
{
Double v=*it*1.7+rand()%21-10;
*it=saturate_case<uchar>(v*v/255);
}
For(int y=0;y<I_YUV.rows;y++)
{
Uchar* Uptr=planes[1].ptr<ujchar>(y);
For(int x=0;x<I_YUV.cols;x++)
{
Uptr[x]=saturate_cast<uchar>((Uptr[x]-128/2)+128);
Uchar&Vxy=planes[2].at<uchar>(y,x);
Vxy=saturate_cast<uchar>((Vxy-128)/2+128);
}
}
在这里你可以看到咱们经过三种方式(迭代器,C指针以及独立元素进入方式)来遍历整个图像中的像素。你能够从How to scan images,lookup tables and time measurement with OpenCV教程来得到更多的深层次的描述。很容易转换老旧的函数名称。仅仅把cv前缀去掉而后使用新的Mat 数据结构。下面就是经过使用增长权重的函数的使用案例:
Mat noisyI(I.size(),.CV_8U);
Randn(noisyI,Scalar::all(128),Scalar::all(20));
GaussianBlur(noisyI,noisyI,Size(3,3),0.5,0.5);
Const double brightness_gain=0;
Const double contrast_gain=1.7;
#ifdef DEMO_MIXED_API_USE
IplImage cv_planes_0=planes[0],cv_noise=noisyI;
cvAddWeighted(&cv_lanes_0,contrast_gain,&cv_noise,1,-128+brightness_gain,&cv_planes_0);
#else
addWeighted(planes[0],contrast_gain,noisyI,1,-128+brightness_gain,planes[0]);
#endif
Const double color_scale=0.5;
Planes[1].convertTo(planes[1],planes[1].type(),color_scale,128*(1-color_scale));
Planes[2]=Mat_<uchar>(planes[2]*color_scale+128*(1-color_scale));
Planes[0]=planes[0].mul(planes[0],1./255);
你可能看到平面变量的类型是Mat。然而从Mat 转换到IplImage容易并且使用一个赋值操做就能够自动完成。
Merge(planes,I_YUV);
cvColor(I_YUV,I,CV_YCrCb2BGR);
namedWindow(“image with grain”,WINDOW_AUTOSIZE);
#ifdef DEMO_MIXED_API_USE
cvShowImage(“image with grain”.IplI);
#else
Imshow(“image with grain”,I);
新的imshow highgui函数接受Mat和IplImage两种数据结构。编译和运行程序,若是下面第一幅图像是你的输入图像,你可能的到第二章或者第三章图像做为输出。