OpenCV學習(九)之Mat基本數據結構_2

一、Mat Constructors:

C++: Mat::Mat()
C++: Mat::Mat(int rows, int cols, int type)
C++: Mat::Mat(Size size, int type)
C++: Mat::Mat(int rows, int cols, int type, const Scalar& s)
C++: Mat::Mat(Size size, int type, const Scalar& s)
C++: Mat::Mat(const Mat& m)
C++: Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all() )
C++: Mat::Mat(const Mat& m, const Rect& roi)
C++: Mat::Mat(const CvMat* m, bool copyData=false)
C++: Mat::Mat(const IplImage* img, bool copyData=false)
C++: template<typename T, int n> explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)
C++: template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)
C++: template<typename T> explicit Mat::Mat(const vector<T>& vec, bool copyData=false)
C++: Mat::Mat(int ndims, const int* sizes, int type)
C++: Mat::Mat(int ndims, const int* sizes, int type, const Scalar& s)
C++: Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)
C++: Mat::Mat(const Mat& m, const Range* ranges)
參數解釋:

ndims– 數組的維數.


rows – 2維數組中行行數


cols – 2維數組中的列數


size – 2維數組的尺寸Size(cols, rows)Size(width,height).在Size()構造函數中行數和列數在次序上剛好反轉過來了。


sizes–指定 n 維數組形狀的整數數組,表示維度的數組


type–數組的類型。使用 CV_8UC1,… …,創建 1-4 通道的矩陣,CV_64FC4 或CV_8UC(n),… …,CV_64FC(n)可以創建多通道 (高達 CV_MAX_CN 通道)矩陣。


s–個可選的初始化每個矩陣元素的參數。要在矩陣建成後將所有元素設置爲特定值可以用Mat的賦值運算符Mat:operator=(const Scalar& value)。


data–指向用戶數據區域的指針。矩陣構造函數傳入data和step參數不分配矩陣數據。相反,它們只是初始化矩陣頭指向指定的數據,這意味着沒有數據的複製。此操作是很高效的,可以用來處理使用 OpenCV 函數的外部數據。外部數據不會自動釋放,所以你應該小心處理它。


step – 每個矩陣行佔用的字節數。如果任何值應包括每行末尾的填充字節。如果缺少此參數(設置爲 AUTO_STEP),假定沒有填充和實際的步長用cols*elemSize()計算。請參閱Mat::elemSize(),elemSize() = sizeof(type) * channels.


step1 -- 這裏需要介紹一下step1. step1 = step/elemSize1(), elemSize1() = sizeof(type), elemSize1() 返回一個通道的大小,而不是一個像素值的大小。所以step1 = cols * channels。


steps–多維數組(最後一步始終設置爲元素大小) 的情況下的 ndims-1個步長的數組。如果沒有指定的話,該矩陣假定爲連續。


m–分配給構造出來的矩陣的陣列(作爲一個整體或部分)。這些構造函數沒有複製數據。相反,指向 m 的數據或它的子數組的頭被構造並被關聯到m上。引用計數器中無論如何都將遞增。所以,當您修改矩陣的時候,自然而然就使用了這種構造函數,您還修改 m 中的對應元素。如果你想要獨立的子數組的副本,請使用 Mat::clone()。

img –指向老版本的 IplImage圖像結構的指針。默認情況下,原始圖像和新矩陣之間共享數據。但當 copyData 被設置時,完整的圖像數據副本就創建起來了。


vec–矩陣的元素構成的STL 向量。矩陣可以取出單獨一列並且該列上的行數和矢量元素的數目相同。矩陣的類型匹配的向量元素的類型。構造函數可以處理任意的有正確聲明的DataType類型。這意味着矢量元素不支持的混合型結構,它們必須是數據(numbers)原始數字或單型數值元組。對應的構造函數是顯式的。由於 STL 向量不會自動轉換爲Mat實例,您應顯式編寫 Mat(vec)。除非您將數據複製到矩陣 (copyData = true),沒有新的元素被添加到向量中,因爲這樣可能會造成矢量數據重新分配,並且因此使得矩陣的數據指針無效。

copyData –指定STL 向量或舊型 CvMat 或 IplImage是應複製到 (true)新構造的矩陣中,還是(false) 與之共享基礎數據的標誌,複製數據時,使用Mat引用計數機制管理所分配的緩衝區。雖然數據共享的引用計數爲 NULL,但是分配數據必須在矩陣被析構之後纔可以釋放。

rowRange – m 的行數的取值範圍。正常情況下,範圍開始端是包含的,而末尾段是不包含的。使用 rowRange::all() 來取所有的行。

colRange – m 列數的取值範圍。使用 colRange::all() 來取所有的列。

ranges –表示M沿每個維度選定的區域的數組。

expr – 矩陣表達式,請參見矩陣表達式。

下面添加一些函數的測試:

實驗環境:VS2010 + OpenCV2.4.9.0

int main(int argc,char** argv)
{
	Mat M(2,2,CV_8UC3,Scalar(0,0,255));
	//Mat M;
	//M.create(4,4,CV_8UC2);
	cout << "M = " << endl <<" " << M << endl << endl;
	system("pause");
	return 0;
}

//Define some matrices
int main(int argc,char** argv)
{
	Mat E = Mat::eye(4,4,CV_64F);
	cout << "E = " << endl <<" " << E<< endl << endl;

	Mat ON  = Mat::ones(4,4,CV_32F);
	cout << "ON = " << endl <<" " << ON << endl << endl;

	Mat Z = Mat::zeros(3,3,CV_8UC1);
	cout << "Z = " << endl << " " << Z << endl << endl;
	system("pause");
	return 0;
}

//For small matrices,may use comma separated initializers
int main(int argc,char** argv)
{
	Mat C = (Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
	cout << "C = " << endl <<" " << C<< endl << endl;

	//Create a new header for an existing Mat object and clone() or copyTo() it
	Mat rowClone = C.row(1).clone();
	cout << "rowClone = " << endl <<" " << rowClone << endl << endl;

	Mat rowCopy;
	C.row(1).copyTo(rowCopy);
	cout << "rowCopy = " << endl <<" " << rowCopy << endl << endl;
	
	system("pause");
	return 0;
}

//random function
int main(int argc,char** argv)
{
	Mat R = Mat(3,2,CV_8UC3);
	randu(R,Scalar::all(0),Scalar::all(255));
	cout << "R = " << endl <<" " << R << endl << endl;
	system("pause");
	return 0;
}

//output
int main(int argc,char** argv)
{
	//2D Point
	Point2f P(5,1);
	cout << "Point (2D) = " << P << endl << endl;

	//3D Point
	Point3f P3f(2,6,7);
	cout << "Point (3D) = " << P3f << endl << endl;

	//std::vector via cv::Mat
	vector<float> v;
	v.push_back((float)CV_PI);
	v.push_back(2);
	v.push_back(3.01f);
	cout << "Vector of float via Mat = " << Mat(v) << endl << endl;

	//std::vector of points
	vector<Point2f> vPoints(20);
	for(size_t i = 0;i < vPoints.size();i++)
		vPoints[i] = Point2f((float)(i*5),(float)(i % 7));
	cout << "A vector of 2D Points = " << vPoints << endl << endl;
	system("pause");
	return 0;
}

下面代碼是對Mat矩陣的一些基本操作函數的測試:

#include <iostream>
#include <vector>
#include "cv.h"
#include "highgui.h"
#include <math.h>

using namespace std;
using namespace cv;

int main(int argc,char** argv)
{
	//Mat M1(3,3,CV_8UC1,Scalar(1));
	Mat M1 = Mat::eye(3,3,CV_8U);
	cout << "M1 = " << M1 << endl<< endl;

	Mat M2 = (Mat_<int>(3,3) << 8,1,6,3,5,7,4,9,2);  //data type is not compatible
	M2.convertTo(M2,CV_8U);  //convert to the same data type
	//Mat M2;
	//M2.create(3,3,CV_8U);
	cout << "M2 = " << M2 << endl << endl;
	
	//matrix add
	Mat mAdd;
	//mAdd = M1 + M2;
	add(M1,M2,mAdd);
	cout << "mAdd = " << mAdd << endl << endl;

	//matrix subtraction
	Mat mSub,absSub;
	absdiff(M1,M2,absSub);  //|M1 - M2|
	cout << "absSub = " << absSub << endl << endl;
	//mSub = M2 - M1;
	subtract(M2,M1,mSub);  //M2 - M1
	cout << "mSub = " << mSub << endl << endl;

	//matrix multiply
	Mat dotMulti,crossMulti(3,3,CV_8UC3,Scalar::all(0));
	dotMulti = M2.mul(M1);  //dot multiply
	cout << "dotMulti = " << dotMulti << endl<< endl;
	//crossMulti = M3.cross(M4);	//cross multiply
	//cout << "crossMulti = " << crossMulti << endl<< endl;

	//matrix divide
	Mat mDiv;
	//divide(I1,I2,dst,scale,int dtype=-1); //dst=saturate_cast(I1*scale/I2);
	divide(mSub,absSub,mDiv,1);  //dot divide
	cout << "mDiv = " << mDiv << endl<< endl;

	//matrix transpose
	Mat transM;
	transM = M2.t();
	cout << "transM = " << transM << endl<< endl;

	//matrix flip
	Mat flipM;
	//flip(I,dst,int flipCode);	//flipCode = 0是上下翻轉,>0時左右翻轉,<0時上下左右翻轉
	flip(transM,flipM,0);
	cout << "flipM = " << flipM << endl<< endl;

	//matrix pow
	Mat powM;
	pow(M2,2,powM);
	cout << "powM = " << powM << endl<< endl;

	//matrix bit - not
	Mat bitM;
	bitwise_not(M2,bitM);  //取反
	cout << "bitM = " << bitM << endl<< endl;

	//matrix range
	Mat rMat = M2(Range::all(),Range(0,2));  //用矩陣M2初始化rMat,使用M2的所有行,0,1列,注意右端是開區間
	cout << "rMat = " << rMat << endl<< endl;

	//matrix setTo
	Mat setM;
	setM = rMat.setTo(Scalar::all(0));
	cout << "setM = " << setM << endl<< endl;

	//uchar a = M2.ptr<uchar>(1)[1];
	uchar a = M2.at<uchar>(1,1);  //得不到值?? why?
	cout << "a = " << a << endl;

	system("pause");
	return 0;
}

參考博客:OpenCV的基本數據結構      OpenCV矩陣運算   

關於Mat更多細節將在後續中逐漸更新。。。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章