OpenCV Mat矩阵(图像Mat)初始化及访问方法
一、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;
參考鏈接1
二、Mat訪問
Mat和Matlab里的數組格式有點像,但一般是二維向量,如果是灰度圖,一般存放"uchar"類型;如果是RGB彩色圖,存放"Vec3b"類型。首先先看看圖像的是怎么存儲的。
單通道圖像
多通道圖像
多通道的圖像中,每列并列存放通道數量的子列,如RGB三通道彩色圖:
opencv中,由于使用Mat.at訪問數據時,必須正確填寫相應的數據類型,因此必須弄清楚opencv中的數據類型與我們常用數據類型一一對應關系。
Mat_<uchar>---------CV_8U
Mat_<char>-----------CV_8S
Nat_<short>---------CV_16S
Mat_<ushort>--------CV_16U
Mat_<int>-----------CV_32S
Mat_<float>----------CV_32F
Mat_<double>--------CV_64F
CV_8U 8位無符號整數 (0…..255)
CV_8S 8 位符號整數 (-128…..127)
CV_16U 16 位無符號整數 (0……65535)
CV_16S 16 位符號整數 (-32768…..32767)
CV_32S 32 位符號整數 (-2147483648……2147483647)
CV_32F 32 位浮點數 (-FLT_MAX ………FLT_MAX,INF,NAN)
CV_64F 64 位浮點數 (-DBL_MAX ……….DBL_MAX,INF,NAN)
下面主要記錄三種常見的訪問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 |
參考鏈接2
參考鏈接3
參考鏈接4
參考鏈接5
參考鏈接6
多通道Mat訪問
用at進行多通道訪問,對應的數據類型如下:
typedef Vec<uchar, 2> Vec2b; //無符號雙通道 CV_8U:0~255
typedef Vec<uchar, 3> Vec3b; //無符號3通道
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s; //short型雙通道 CV_16S:-32768~32767
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i; //整型雙通道 CV_32S:-2147483648~2147483647
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f; //浮點型雙通道 CV_32F:1.1810-38~3.401038
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d; //double型雙通道 CV_64F:2.2310-308~1.7910308
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;
示例程序,創建及訪問雙通道Mat
#include <opencv2/core/core.hpp>
#include <iostream>using namespace std;
using namespace cv;int main()
{int i, j;Mat dimg(3, 5, CV_16SC2,Scalar(-5,5));//構造一個3*5的short型雙通道矩陣cout << "原矩陣" << endl << dimg << endl;short int a=1,b=15;for (i = 0; i < dimg.rows; i++){for (j = 0; j < dimg.cols; j++){dimg.at<Vec2s>(i, j)[0] = a;//at<type>其中type由矩陣的類型確定dimg.at<Vec2s>(i, j)[1] = b;}}cout << "改變后矩陣" << endl << dimg << endl;system("pause");
}
參考鏈接6
參考鏈接7
歡迎大家點贊、收藏、評論,讓更多的人看到哦~
總結
以上是生活随笔為你收集整理的OpenCV Mat矩阵(图像Mat)初始化及访问方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 处有未经处理的异常:0xC0000005
- 下一篇: OpenCV中图像Mat,二维指针和Cx