1.4【OpenCV圖像處理】Mat對象

Mat構造函數、複製A.copyTo(B)、通道src.channels()、像素指針、數據類型轉換convertTo

1.4.1 Mat對象與IplImage對象

Mat對象OpenCV2.0之後引進的圖像數據結構、自動分配內存、不存在內存泄漏的問題,是面向對象的數據結構。分了兩個部分,頭部與數據部分。

(圖中人眼中是個汽車,計算機眼中opencv會把它解析成一個數組,裡面就是一個個像素,把這些值存放在Mat里)

IplImage是從2001年OpenCV1.0發布之後就一直存在,是C語言風格的數據結構,需要開發者自己分配與管理內存,對大的程序使用它容易導致內存泄漏問題。(不用它)

1.4.2 Mat對象構造函數與常用方法

(1)構造函數(Mat對象構造)

Mat(Size size, int type);

Mat dst;ndst = Mat(src.size(), src.type());//初始化Mat對象dst大小類型跟src一樣ndst = Scalar(127, 0, 255);//賦值3個通道BGR(紅色),全0為黑色,全255為白色n

Mat (int rows, int cols, int type, const Scalar &s); 行 列 類型 通道BGR值:

Mat M(2,2,CV_8UC3, Scalar(0,0,255)); //3個通道(BGR,全0為黑色,全255為白色)

Mat M(2,2,CV_8UC1, Scalar(127)); //1個通道(127灰色)

其中前兩個參數分別表示行(row)跟列(column)、第三個CV_8UC3中的8表示每個通道佔8位、U表示無符號、C表示Char類型、3表示通道數目是3,第四個參數是向量表示初始化每個像素值是多少,向量長度對應通道數目一致

Mat M(3, 3, CV_8UC3, Scalar(127, 0, 255)); //3*3的像素集合,每個像素有3個通道BGR,第1 2通道為0,第3通道為255nMat M(3, 3, CV_8UC1, Scalar(127)); //1個通道,127灰色n

(2)常用方法:

Mat B;

A.copyTo(B); 完全複製

src.copyTo(dst, mask) ; 將src和mask的非零像素都複製到dst

Mat dst; nsrc.copyTo(dst); //完全克隆拷貝一份ndst.create(src.size(), src.type()); //創建空黑圖像dstnsrc.copyTo(dst, mask) ; n

Mat B = A.clone(); 完全克隆複製一份Mat:

Mat dst = src.clone(); //完全克隆拷貝一份n

int channels() 通道數:

printf("output image channels:%dn", src.channels()); //列印原圖通道數(RGB 3個)ncout << "output image channels:" << dst.channels() << endl; ////列印目的圖通道數(灰度 1個)n

bool empty(); 是不是空的:

if (src.empty()) {}n

uchar* ptr(i=0) 獲取圖像第i行的指針:

const uchar* fristRow = dst.ptr<uchar>(0); //指針法,第一個像素的灰度值,fristRow是地址nprintf("frist pixel value:%dn", *fristRow);//*fristRow是地址里的值n

void convertTo(Mat dst, int type) 數據類型轉變,比如為從一個8位長度切換成一個浮點型。

Mat m1;nsrc.convertTo(m1, CV_32F); //src數據類型轉變為m1的32位,切換成浮點型n

int depth() 深度。

1.4.3 Mat對象創建

cv::Mat::create 創建多維數組 :

int sz[3] = {2,2,2};

Mat L(3,sz, CV_8UC1, Scalar::all(0));

cv::Mat::create實現構造矩陣圖像:

Mat M;nM.create(4, 3, CV_8UC3); //create不能直接賦值nM = Scalar(0,0,125);n

Mat定義小數組:

Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); //定義小數組ncout << "kernel = " << endl << " " << kernel << endl << endl;n

1.4.4 Mat對象使用

部分複製:一般情況下只會複製Mat對象的頭和指針部分,不會複製數據部分

Mat A= imread(imgFilePath);

Mat B(A) // 只複製頭,不複製A的數據(數據部分指針指向同一地址)

完全複製:如果想把Mat對象的頭部和數據部分一起複制,可以通過如下兩個API實現

Mat B = A.clone(); 或

Mat B; A.copyTo(B);

Mat對象使用-四個要點:

輸出圖像的內存是自動分配的;

使用OpenCV的C++介面,不需要考慮內存分配問題;

賦值操作和拷貝構造函數只會複製頭部分;

使用clone與copyTo兩個函數實現數據完全複製。


完整程序:

/*1.4 Mat對象構造*/n#include<opencv2/opencv.hpp>n#include<iostream>n#include<math.h>nnusing namespace cv;nusing namespace std;nnint main(int argc, char** argv) {nMat src; //定義一個Mat結構n src = imread("E:/OpenCV/testimage/test5.jpg");nif (src.empty()) {n cout << "could not load image" << endl;nreturn -1;n }n namedWindow("input image", WINDOW_AUTOSIZE);n imshow("input image", src);nn/* Mat dst;n dst = Mat(src.size(), src.type()); //初始化Mat對象dst大小類型跟src一樣n dst = Scalar(127, 0, 255); //賦值3個通道BGR(紅色),全0為黑色,全255為白色 */n/* Mat dst = src.clone(); //完全克隆拷貝一份 */n/* Mat dst; n src.copyTo(dst); //完全克隆拷貝一份 */nnMat dst;n cvtColor(src, dst, CV_BGR2GRAY); //色彩空間轉換成灰色n printf("output image channels:%dn", src.channels()); //列印原圖通道數(RGB 3個)n cout << "output image channels:" << dst.channels() << endl; ////列印目的圖通道數(灰度 1個)n namedWindow("output image", WINDOW_AUTOSIZE);n imshow("output image", dst);nnint rows = dst.rows; //總共多少行nint cols = dst.cols; //總共多少列n printf("rows:%d cols:%dn", rows, cols);nconst uchar* fristRow = dst.ptr<uchar>(0); //指針法,第一個像素的指針,fristRow是地址n printf("frist pixel value:%dn", *fristRow);//*fristRow是地址里的值nnMat M1(3, 3, CV_8UC3, Scalar(127, 0, 255));//3*3的像素集合,每個像素有3個通道BGR,第1 2通道為0,第3通道為255nMat M2(3, 3, CV_8UC1, Scalar(127)); //1個通道,127灰色nMat M3;n M3.create(4, 3, CV_8UC3); //create實現,不能賦值n M3 = Scalar(0,0,125);nMat M4 = Mat::eye(2, 2, CV_8UC1); //2*2矩陣主對角線上值為1,其他為0nMat M5 = Mat::zeros(2, 2, CV_8UC1); //2*2矩陣的值全為0nMat M6 = Mat::zeros(src.size(), src.type()); //與原圖大小類型一致的全黑矩陣圖像n cout << "M = " << endl << M1 << endl;n namedWindow("M image", WINDOW_AUTOSIZE);n imshow("M image", M1);nnMat csrc;nMat kernel = (Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); //定義小數組n cout << "kernel = " << endl << " " << kernel << endl << endl;n filter2D(src, csrc, -1, kernel); //filter2D矩陣掩膜n namedWindow("csrc image", WINDOW_AUTOSIZE);n imshow("csrc image", csrc);nn waitKey(0);nreturn 0;n}n

運行結果:


推薦閱讀:

《Conditional Generative Adversarial Nets》閱讀筆記
詳解:智能醫學影像分析的前沿與挑戰 | 硬創公開課
PS教程-通過海綿工具凸顯圖片中的人物
載入選區與儲存選區
《Fully Convolutional Instance-aware Semantic Segmentation》論文筆記

TAG:OpenCV | 图像处理 | OpenCV3编程入门书籍 |