opencv1.0版本于2006年面世,主要基于C语言。2009年发布opencv2,主要基于C++。我主要学习了2.0版本。其实两者之间的函数调用还是有些相同的,只不过有的时候使用的是全局函数cv***,而2.0使用的是不带cv的函数。
此时opencv库被划分为多个模块,这些模块被编译成库文件后,位于lib文件夹中,这是我截取的全部模块,我们需要的就是引用这些模块。
Opencv_core模块:包含核心功能,尤其是低层数据结构和算法函数。
Opencv_improc模块:包含图像处理函数
Opencv_highgui模块:包含读写图像及视频的函数,以及操作图形用户界面函数。
opencv_features2d模块:包含兴趣点检测子,描述子以及兴趣点匹配框架
Opencv_video模块:包含运动估算,特征特征以及前景提取函数与类
Opencv_objdetect模块:包括物体检测函数,如脸部和行人检测。
库文件中还包含其他的工具模块,如机器学习(opencv_ml),计算几何(opencv_flann),第三方代码(opencv_contrib)等。
#include “cv.h”这是旧的代码方式,那是库还没有被划分为模块。
opencv2的库文件声明如下:
#include
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat image = imread("1.jpg",1);
if (!image.data)
{
//没有这个图像文件
}
cout<<image.size().height<<","<<image.size().width;
namedWindow("show");
imshow("show",image);
waitKey(0); //这个必须用,否则界面会卡死
getchar();
return 0;
}
image.data是指向已分配的内存块的指针,当图片没有加载进来,则为 NULL。
image.size()返回的是一个结构体,实际上包括width和height两个成员变量。
图像的浅拷贝和深拷贝:
(1)浅拷贝
Mat B;
B = image;
Mat C(iamge);
这两种方式都被称为浅copy,他们有不同的矩阵头,但是他们共享内存空间,即指向同一个图像矩阵。当图像矩阵发生变化时,两者相关联,都会变化。
(2)深拷贝
Mat B,C;
B = image.clone();
image.copyTo(C);
IplImage转化为Mat:
我们常常算法会需要IplImage类型,而不是Mat类型。这两者之间的转换也非常常见。
IplImage* pImage = cvLoadImage("1.jpg",1);
pImage =&IplImage(result);
Mat result(pImage,false);//后面一个参数的意思是。是否提供深拷贝。默认情况是false,true为深拷贝
简单存取像素值:
void salt(Mat &image,int n)
{
for (int k=0;k<n;k++)
{
int i = rand()%image.cols;
int j = rand()%image.rows;
if (image.channels()==1)
{
image.at<uchar>(j,i) = 255;
}
else if (image.channels()==3)
{
image.at<Vec3b>(j,i)[0] = 255;
image.at<Vec3b>(j,i)[1] = 255;
image.at<Vec3b>(j,i)[2] = 255;
}
}
}
//Main函数中
//简单存取像素值 写入像素值
Mat imageSource = imread("1.jpg",1);
salt(imageSource,3000);
namedWindow("SaltImage");
imshow("SaltImage",imageSource);
注意: image.at< vec3b >(j,i)[0] = 255。成员函数at(x,y)可以用来存取图像元素,但是他是模板函数,你需要指定操作成员的类型 at< uchar >(y,x)。
vec3b是由3个uchar组成的,可以通过操作符[]来获取。
通过指针遍历图像:
int nRows = imageSource.rows;
int nCols = imageSource.cols*imageSource.channels();
for (int j=0;j<nRows;j++)
{
uchar* data = imageSource.ptr(j);
for (int i=0;i<nCols;i++)
{
data[i] = data[i]/2;
}
}
通过迭代器遍历图像:
//通过迭代器访问图像
Mat imageIterator = imread("1.jpg",1);
Mat_<Vec3b>::iterator begin = imageIterator.begin<Vec3b>();
Mat_<Vec3b>::iterator end = imageIterator.end<Vec3b>();
for (;begin!=end;begin++)
{
(*begin)[0] = (*begin)[0]/2;
(*begin)[1] = (*begin)[1]/2;
(*begin)[2] = (*begin)[2]/2;
}
namedWindow("IteratorImage");
imshow("IteratorImage",imageIterator);
附:如何来计算一个函数运行的时间:
函数开始处:
double time = static_cast< double >(getTickCount());
time = (static_cast< double >(getTickCount())- time)/getTickFrequency(); //单位秒