一、Mat初始化
1.使用Mat構造函數
//方法一:
Mat M( 2, 2, CV_8UC3, Scalar(0,255,0) );//其實是2*6的矩陣,因爲每個元素有3個通道。
Mat M1( 2, 2, CV_8UC1,Scalar(0) );//單通道
//方法二:
int sz[3] = {2, 2, 2};
Mat L( 3, sz, CV_8UC(1), Scalar::all(0) );
2.爲已存在的IplImage指針創建信息頭
IplImage* img = cvLoadImage("1.jpg",1);
Mat test(img);
3.利用create函數
M.create( 4, 4, CV_8UC2);//CV_8UC2裏面的2表示2通道
4.採用Matlab形式的初始化方式
Mat E = Mat::eye(4, 4, CV_64F);
Mat O = Mat::ones(2, 3, CV_32F);
Mat Z = Mat::zeros(3, 3, CV_8UC1);
5.Mat矩陣比較小時,學會直接賦值的方法,即用Mat_
Mat C =(Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);//直接賦初始值的方法
6.使用數組或指針初始化
Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
example:
int a[2][3] = { 1, 2, 3, 4, 5, 6};
Mat m1(2,3,CV_32S,a); //float 對應的是CV_32F,double對應的是CV_64F
cout << m1 << endl;
二、Mat訪問
Mat和Matlab裏的數組格式有點像,但一般是二維向量,如果是灰度圖,一般存放類型;如果是RGB彩色圖,存放類型。首先先看看圖像的是怎麼存儲的。
單通道圖像
多通道圖像
opencv中,由於使用Mat.at訪問數據時,必須正確填寫相應的數據類型,因此必須弄清楚opencv中的數據類型與我們常用
數據類型一一對應關係。
Mat_---------CV_8U
Mat-----------CV_8S
Nat_---------CV_16S
Mat_--------CV_16U
Mat_-----------CV_32S
Mat_----------CV_32F
Mat_--------CV_64F
下面主要記錄三種常見的訪問Mat的方式:1.at訪問 2.ptr訪問 3.data訪問
Mat中不管是以at訪問還是ptr訪問,都是行優先 ,先Y軸後X軸(即先行後列)
//方法1:
t = (double)getTickCount();
Mat img1(1000, 1000, CV_32F);
for (int i=0; i<1000; i++)
{
for (int j=0; j<1000; j++)
{
img1.at<float>(i,j) = 3.2f;
}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());
//***方法2************************************************************
t = (double)getTickCount();
Mat img2(1000, 1000, CV_32F);
for (int i=0; i<1000; i++)
{
for (int j=0; j<1000; j++)
{
img2.ptr<float>(i)[j] = 3.2f;
}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());
//***方法3************************************************************
t = (double)getTickCount();
Mat img3(1000, 1000, CV_32F);
float* pData = (float*)img3.data;
for (int i=0; i<1000; i++)
{
for (int j=0; j<1000; j++)
{
*(pData) = 3.2f;
pData++;
}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());
//***方法3************************************************************
t = (double)getTickCount();
Mat img4(1000, 1000, CV_32F);
for (int i=0; i<1000; i++)
{
for (int j=0; j<1000; j++)
{
((float*)img3.data)[i*1000+j] = 3.2f;
}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());
對比幾種方法,速度測試如下:
Debug | Release | |
方法1 | 139.06ms | 2.51ms |
方法2 | 66.28ms | 2.50ms |
方法3-1 | 4.95ms | 2.28ms |
方法3-2 | 5.11ms | 1.37ms |
/*********加強版********/
t = (double)getTickCount();
Mat img5(1000, 1000, CV_32F);
float *pData1;
for (int i=0; i<1000; i++)
{
pData1=img5.ptr<float>(i);
for (int j=0; j<1000; j++)
{
pData1[j] = 3.2f;
}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());
Debug | Release | |
加強版 | 5.74ms | 2.43ms |