淺談Opencv Mat類(常用建構函式和成員函式整理)
在Opencv1代的時候,是使用lplImage 和 CvMat 資料結構來表示影象的。他們都是C語言的結構,申請的記憶體需要自己手動管理。從Opencv2.3往後就引入了Mat類,他可以自動管理記憶體,而我接觸opencv開始,用的就是Mat類,再之後在學習opencv過程中才接觸了lplImage和CvMat 但是這兩個資料結構畢竟給我們帶來了一定的負擔,所以我不是很喜歡用。所以lplImage 和 CvMat 就不聊了。我們還是看看Mat類。
Mat類關鍵的屬性和定義如下:
class CV_EXPORTS Mat { public: / /一系列函式... /* flag 引數中包含序號關於矩陣的資訊,如: -Mat 的標識 -資料是否連續 -深度 -通道數目 */ int flags; int dims ;//!陣列的維數,取值大於等於2//!行和列的數量,如果矩陣超過 2 維,那這兩個值為-1 int rows,cols; uchar *data ;//!指向資料的指標 int * refcount ;//!指標的引用計數器 ; / / 陣列指向使用者分配的資料時,當指標為 NULL / / 其他成員 ... };
然後我們看看Mat常用的建構函式:
1、Mat::Mat()
無引數構造方法;
2、Mat::Mat(int rows, int cols, int type)
建立行數為 rows,列數為 col,型別為 type 的影象;
3、Mat::Mat(Size size, int type)
建立大小為 size,型別為 type 的影象;
4、Mat::Mat(int rows, int cols, int type, const Scalar& s)
建立行數為 rows,列數為 col,型別為 type 的影象,並將所有元素初始化為值 s;
5、Mat::Mat(Size size, int type, const Scalar& s)
建立大小為 size,型別為 type 的影象,並將所有元素初始化為值 s;
6、Mat::Mat(const Mat& m)
將m賦值給新建立的物件,此處不會對影象資料進行復制,m和新物件共用影象資料,屬於淺拷貝;
7、Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
建立行數為rows,列數為col,型別為type的影象,此建構函式不建立影象資料所需記憶體,而是直接使用data所指記憶體,影象的行步長由 step指定。
8、Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
建立大小為size,型別為type的影象,此建構函式不建立影象資料所需記憶體,而是直接使用data所指記憶體,影象的行步長由step指定。
9、Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
建立的新影象為m的一部分,具體的範圍由rowRange和colRange指定,此建構函式也不進行影象資料的複製操作,新影象與m共用影象資料;
10、Mat::Mat(const Mat& m, const Rect& roi)
建立的新影象為m的一部分,具體的範圍roi指定,此建構函式也不進行影象資料的複製操作,新影象與m共用影象資料。
這些建構函式中,很多都涉及到型別type。type可以是CV_8UC1,CV_16SC1,…,CV_64FC4 等。裡面的 8U 表示 8 位無符號整數,16S 表示 16 位有符號整數,64F表示 64 位浮點數(即 double 型別);C 後面的數表示通道數,例如 C1 表示一個
通道的影象,C4 表示 4 個通道的影象,以此類推。
如果你需要更多的通道數,需要用巨集 CV_8UC(n),例如:
Mat M(3,2, CV_8UC(5));//建立行數為 3,列數為 2,通道數為 5 的影象。
建構函式就說到這裡,然後我們看看Mat類常用的成員函式:
Mat::Create
建立新的陣列資料
void Mat::create(int rows, int cols, int type)
void Mat::create(Size size, int type)
void Mat::create(int ndims, const int* sizes, inttype)
ndims – 新陣列的維數。
rows –新的行數。
cols – 新的列數。
size – 替代新矩陣大小規格:Size(cols, rows)。
sizes – 指定一個新的陣列形狀的整數陣列。
type – 新矩陣的型別。
Mat::resize
重新定義圖片大小
void Mat::resize(size_t sz)
void Mat::resize(size_t sz, const Scalar& s)
sz –新的行數。
s –分配給新新增的元素的值。
Mat::adjustROI
調整子陣大小及其在父矩陣中的位置
Mat& Mat::adjustROI(int dtop, int dbottom,int dleft, int dright)
dtop –頂部子陣邊界向上的平移量。
dbottom –底部子陣邊界向下的平移量。
dleft –左子陣邊界向左的平移量。
dright –右子陣邊界向右的平移量。
Mat::total
返回陣列元素的總數
size_t Mat::total() const
Mat::isContinuous
判斷矩陣是否連續
bool Mat::isContinuous() const
Mat::elemSize
返回矩陣元素大小 (以位元組為單位)。
size_t Mat::elemSize() const
該方法返回以位元組為單位的矩陣元素大小。例如,如果矩陣型別是 CV_16SC3,該方法返回3*sizeof(short)或 6。
Mat::elemSize1
以位元組為單位返回每個矩陣元素通道的大小。
size_t Mat::elemSize1() const
該方法返回以位元組為單位的矩陣元素通道大小,也就是忽略通道的數量。例如,
如果矩陣型別是 CV_16SC3,該方法返回 sizeof(short) 或 2。
Mat::type
返回一個矩陣元素的型別。
int Mat::type() const
該方法返回一個矩陣的元素型別。這是相容CvMat 型別系統,像 CV_16SC3識別符號
或 16 位有符號的3 通道陣列,等等。
Mat::depth
返回一個矩陣元素的深度。
int Mat::depth() const
該方法返回矩陣元素深度(每個單獨的通道型別)的識別符號。例如,對於16位有符號的3通道陣列,該方法返回CV_16S。矩陣型別的完整列表包含以下內容值:
• 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::channels
返回矩陣通道的數目。
int Mat::channels() const
Mat::step1
返回矩陣歸一化邁出的一步。
size_t const Mat::step1()
該方法返回以矩陣的step除以Mat::elemSize1()。它對快速訪問任意矩陣元素很有用。
Mat::size
返回一個矩陣大小。
Size Mat::size() const
該方法返回一個矩陣大小:Size(cols, rows)。矩陣超過 2 維時返回大小為(-1,-1)。
Mat::empty
如果陣列有沒有 elemens,則返回 true。
bool Mat::empty() const
如果 Mat::total() 是 0 或 Mat::data 為 NULL,則方法返回 true。因為pop_back() 和 resize()方法M.total()== 0,並不意味著M.data = =NULL。
Mat::ptr
返回指定矩陣行的指標。
uchar* Mat::ptr(int i=0)
const uchar* Mat::ptr(int i=0) const
template<typename _Tp> _Tp* Mat::ptr(inti=0)
template<typename _Tp> const _Tp*Mat::ptr(int i=0) const
引數:
i –一個基於0的行索引。
Mat::at
返回對指定陣列元素的引用。
template<typename T> T& Mat::at(int i)const
template<typename T> const T&Mat::at(int i) const
template<typename T> T& Mat::at(int i,int j)
template<typename T> const T&Mat::at(int i, int j) const
template<typename T> T& Mat::at(Pointpt)
template<typename T> const T&Mat::at(Point pt) const
template<typename T> T& Mat::at(int i,int j, int k)
template<typename T> const T&Mat::at(int i, int j, int k) const
template<typename T> T& Mat::at(constint* idx)
template<typename T> const T&Mat::at(const int* idx) const
引數
i –索引 0 維度
j – 1 維度的索引
k – 沿 2 維度的索引
pt – Point(j,i) 作為指定元素的位置。
idx – Mat::dims 陣列的索引。
該模板方法返回指定陣列元素的引用。為了具有更高的效能,索引範圍檢查只在除錯配置下執行。請注意使用具有單個索引 (i) 的變數可以訪問的單行或單列的2 維的陣列元素。也就是比方說,如果A是1 x N 浮點矩陣和B是M x 1的整數矩陣,您只需編寫A.at(k+4) 和 B.at(2i+1) 分別代替A.at(0,k+4)和
B.at(2i+1,0)。
//下面的示例將初始化希爾伯特矩陣:
Mat H(100, 100, CV_64F);
for(inti=0; i<H.rows; i++)
for(intj=0; j<H.cols; j++)
H.at<double>(i,j)=1./(i+j+1);
Mat::begin
返回矩陣迭代器,並將其設定為第一矩陣元。
template<typename _Tp>MatIterator_<_Tp> Mat::begin()
template<typename _Tp>MatConstIterator_<_Tp> Mat::begin() const
該方法返回矩陣的只讀或讀寫的迭代器。矩陣迭代器的使用和雙向 STL 迭代器的使用是非常相似的。在下面的示例中,alpha融合函式是使用矩陣迭代器重寫:
template<typename T>
void alphaBlendRGBA(const Mat& src1,const Mat& src2, Mat& dst)
{
typedef Vec<T, 4> VT;
const float alpha_scale =(float)std::numeric_limits<T>::max(),
inv_scale = 1.f/alpha_scale;
CV_Assert( src1.type() == src2.type()&&
src1.type() == DataType<VT>::type&&
src1.size() == src2.size());
Size size = src1.size();
dst.create(size, src1.type());
MatConstIterator_<VT> it1 =src1.begin<VT>(), it1_end = src1.end<VT>();
MatConstIterator_<VT> it2 =src2.begin<VT>();
MatIterator_<VT> dst_it =dst.begin<VT>();
for( ; it1 != it1_end; ++it1, ++it2,++dst_it )
{
VT pix1 = *it1, pix2 = *it2;
float alpha = pix1[3]*inv_scale, beta =pix2[3]*inv_scale;
*dst_it =VT(saturate_cast<T>(pix1[0]*alpha + pix2[0]*beta),
saturate_cast<T>(pix1[1]*alpha + pix2[1]*beta),
saturate_cast<T>(pix1[2]*alpha +pix2[2]*beta),
saturate_cast<T>((1 -(1-alpha)*(1-beta))*alpha_scale));
}
}
Mat::end
返回矩陣迭代器,並將其設定為 最後元素之後(after-last)的矩陣元。
template<typename _Tp>MatIterator_<_Tp> Mat::end()
template<typename _Tp>MatConstIterator_<_Tp> Mat::end() const
該方法返回矩陣只讀或讀寫的迭代器,設定為緊隨最後一個矩陣元素的點。
Mat的構造和常用的成員函式就梳理到這裡了,如果有未提到的後續會繼續補充。