opencv常用类&函数
1. Mat类
Mat 区别于IplImage的是,你不再需要手动分配其大小并且当你不需要它的时候你不再需要手动释放它。Mat本质上是由两个数据部分组成的类: Header和Pointer。Header中主要包含矩阵的大小,存储方式,存储地址等信息,Pointer中存储指向像素值的指针。
Mat A, C;
A=imread("lena.jpg");
Mat B(A);
C=A;
这段程序,A、B、C指向的是同一块数据,他们的 header不同,但对于 A 的操作同样也影响着 B、C 的结果。如果想建立互不影响的 Mat,即真正的复制操作,需要使用函数 clone()或者 copyTo()
Mat dst;
Mat src=imread("lena.jpg");
Mat src1=src.clone();
dst.create(src1.size(),src1.type());
Mat M(2,2,CV_8UC3,Scalar(0,0,125));//初始化
M.create(4,4,CV_8UC(2));//使用这种方法不能初始化矩阵
/*2,2表示尺寸 CV_[The number of bits per itrm][signed or Unsigned][Typeprefix]C[the channel number] Scalar(0,0,125)表示初始值 */
//特殊矩阵
Mat zero=Mat::zeros(3,3,CV_8UC1);//零矩阵
Mat I=Mat::eye(4,4,CV_64F);//单位矩阵
Mat one=Mat::ones(2,2,CV_32F);//全1矩阵
//.ptr头指针
Mat image = Mat(400, 600, CV_8UC1);
uchar * data00 = image.ptr<uchar>(0);//data00是指向image第一行第一个元素的指针
uchar * data10 = image.ptr<uchar>(1);//data10是指向image第二行第一个元素的指针
uchar * data01 = image.ptr<uchar>(0)[1];//data01是指向image第一行第二个元素的指针
2. Point类
为了描述图像中的点,opencv中提供了点的模板类,分为2维点模板类
Point_
和3维点模板类Point3_
。Point_
通过2维图像平面中的x和y坐标确定点的位置,Point3_
通过3维立体图像中的x、y、z坐标确定点的位置。对于点的坐标的类型可以是int、double、float类型
Point point;
point.x = 10;
point.y = 8;
Point point = Point(10, 8);
//常见输出项
//2D Point
Point2f P(5, 1);
cout << "Point (2D) = " << P << endl;
//3D Point
Point3f P3f(2, 6, 7);
cout << "Point (3D) = " << P3f << endl;
3. Rect类
Rect类的成员变量x、y、width、height,分别为左上角点的坐标和矩形的宽和高。常用的成员函数有size()返回值为一个size,area()返回矩形的面积,contains(Point)用来判断点是否在矩形内,inside(Rect)函数判断矩形是否在该矩形内,tl()返回左上角点坐标,br()返回右下角点坐标
//如果创建一个Rect对象rect(100, 50, 50, 100),那么rect会有以下几个功能:
rect.area(); //返回rect的面积 5000
rect.size(); //返回rect的尺寸 [50 × 100]
rect.tl(); //返回rect的左上顶点的坐标 [100, 50]
rect.br(); //返回rect的右下顶点的坐标 [150, 150]
rect.width(); //返回rect的宽度 50
rect.height(); //返回rect的高度 100
rect.contains(Point(x, y)); //返回布尔变量,判断rect是否包含Point(x, y)点
//还可以求两个矩形的交集和并集
rect = rect1 & rect2;
rect = rect1 | rect2;
//还可以对矩形进行平移和缩放
rect = rect + Point(-100, 100); //平移,也就是左上顶点的x坐标-100,y坐标+100
rect = rect + Size(-100, 100); //缩放,左上顶点不变,宽度-100,高度+100
//还可以对矩形进行对比,返回布尔变量
rect1 == rect2;
rect1 != rect2;
//判断rect1是否在rect2里面
bool isInside(Rect rect1, Rect rect2)
{
return (rect1 == (rect1&rect2));
}
//获取矩形中心点
Point getCenterPoint(Rect rect)
{
Point cpt;
cpt.x = rect.x + cvRound(rect.width/2.0);
cpt.y = rect.y + cvRound(rect.height/2.0);
return cpt;
}
//围绕矩形中心缩放
Rect rectCenterScale(Rect rect, Size size)
{
rect = rect + size;
Point pt;
pt.x = cvRound(size.width/2.0);
pt.y = cvRound(size.height/2.0);
return (rect-pt);
}
//用矩形画矩形窗
rectangle(img,rect,Scalar(0,0,255),3,8,0);
除了基本的矩形之外,opecv还提供了一个可以旋转的矩形RotatedRect,它是由中心、变长、旋转角度决定的。可以访问它的这三个成员,也可以使用points函数返回它的4个顶点,使用boundingRect求出它的外接矩形(非旋转)
int main(void)
{
Mat bg(200,200,CV_8UC3,Scalar(0));
imshow("",bg);
RotatedRect rRect(Point2f(100,100),Size(100,100),40);
Point2f vertices[4];
rRect.points(vertices);
for(int i = 0; i < 4;++i)
line(bg,vertices[i],vertices[(i+1)%4],Scalar(0,255,0));
Rect brect = rRect.boundingRect();
rectangle(bg,brect,Scalar(255,0,0));
imshow("",bg);
waitKey();
return 0;
}
4. 容器类(vector)
vector 能够像容器一样存放各种类型的对象,简单地说,vector 是一个能够存放任意类型的动态数组,能够增加和压缩数据
int main()
{
vector<Point2f> vp2f;
vp2f.push_back(Point2f(2, 3));//添加元素
bool isEmpty = vp2f.empty();//判断是否为空
vector<Point3f> vp3f(20);
for (size_t i = 0; i < vp3f.size(); i++)
{
vp3f[i] = Point3f((float)(i + i), (float)(i * i), (float)(i + 1));
}
vector<Point3f>::iterator it = vp3f.begin();//迭代器
for(;it != vp3f.end(); it++)
{
cout<<*it<<endl;
}
waitKey();
return 0;
}
5. 数组-图像互转
void img2data(Mat &image,uchar *tmp)
{
int nl = image.rows;
int nc = image.cols * image.channels();
for(int j=0; j<nl ;++j)
{
uchar *data = image.ptr<uchar>(j);
for(int i=0; i<nc; ++i)
{
tmp[nc*j+i]=data[i];
}
}
}
void data2img(uchar *tmp,Mat &image)
{
int nl = image.rows;
int nc = image.cols * image.channels();
for(int j=0; j<nl ;++j)
{
uchar *data = image.ptr<uchar>(j);
for(int i=0; i<nc; ++i)
{
data[i] = tmp[i+j*nc];
}
}
}
6. 图片上显示数据
void putText(Mat& img,
const string& text,
Point org,
int fontFace,
double fontScale,
Scalar color,
int thickness=1,
int lineType=8,
bool bottomLeftOrigin=false)
void show_data(string name,Mat* img,Point p,int data)
{
char str[10];
sprintf(str,"%d",data);
putText(*img,str,p,CV_FONT_NORMAL,1,cvScalar(255),1,8,false);
imshow(name,*img);
}
7. 鼠标响应
void setMousecallback(const string& winname,//winname:窗口的名字
MouseCallback onMouse,//onMouse:鼠标响应函数,指定窗口里每次鼠标事件发生的时候,被调用的函数指针
void* userdata=0)//userdate:传给回调函数的参数
void on_Mouse(int event,//event是 CV_EVENT_*变量之一
int x, int y,//x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系)
int flags,//flags是CV_EVENT_FLAG的组合
void* param);//param是用户定义的传递到setMouseCallback函数调用的参数
/*常用event #defineCV_EVENT_MOUSEMOVE #defineCV_EVENT_LBUTTONDOWN #defineCV_EVENT_RBUTTONDOWN #defineCV_EVENT_LBUTTONUP #defineCV_EVENT_RBUTTONUP */
8. 测试代码时间
double time0 = static_cast<double>(getTickCount());//记录起始时间
colorReduce(srcImage,dstImage,32);//调用颜色空间缩减函数
time0 = ((double)getTickCount() - time0)/getTickFrequency();//计算运行时间并输出
//另附上 linux 中测试代码时间的代码段
#include <stdio.h>
#include <sys/time.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char **argv)
{
struct timeval tpstart, tpend;
float timeuse;
while(1)
{
gettimeofday(&tpstart, NULL);
waitKey(100);
gettimeofday(&tpend, NULL);
timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec - tpstart.tv_usec;
timeuse /= 1000000;
printf("Used Time: %f seconds\n", timeuse);
}
return 0;
}
9. 指定位置保存图片
char str0[10]="./HJ/";
char str1[10];
int i=10;
sprintf(str1,"%d",i);
strcat(str1,".png");
strcat(str0,str1);
imwrite(str0,mat);//即./HJ/10.png,务必要先确保HJ文件夹的存在