圖像儲存容器Mat[OpenCV 筆記11]


IplImage 與 Mat

IplImage是OpenCV1中的圖像存儲結構體,基於C接口創建。在退出之前必須release,否則就會造成內存泄露。在一些只能使用C語言的嵌入式系統中,不得不使用。

IplImage* img = cvLoadImage("imagename.jpg",1);

Mat類內存分配是自動完成的,不必手動開辟空間(非必須),不必在不需要時釋放空間。

Mat類的構成

Mat由矩陣頭和一個指向存儲圖像矩陣的指針組成。為應該盡量避免圖像的復制,加快程序運行速度,Mat的拷貝構造函數只復制信息頭和矩陣指針,不復制矩陣。因此通過任何一個對象所做的改變也會影響其他對象。如果想要創建一個感興趣的區域(Region of Interest (ROI))只需要創建包含邊界信息的信息頭:

Mat ROI1(matrix, Rect(x,y,width,height)); // use rectangle to set the boundary
Mat ROI2 = matrix(Range:all(), Range(1,3)); // use rows and cols 

Mat通過對象計數機制來實現最后一個使用它的對象自動負責清理存儲空間。如果想要復制矩陣本身,可以使用:

Mat duplicate1 = matrix.clone();
Mat duplicate2;
matrix.copyTo(duplicate2);

改變duplicate1和duplicate2不會影響matrix指向的矩陣。

構造函數

Mat()
Mat(int rows, int cols, int type, const Scalar & s)
  • rows:矩陣行數
  • cols:矩陣列數
  • type:規定存儲元素的數據類型和每個矩陣點的通道數
    • CV_[the number of bits per item: 8/16/32/64] [Signed, Unsigned, or Float: S/U/F] C [The channel number: 1/2/3/4]
    • CV_8UC3:三通道8位的unsigned char型
  • s:可以省去,Scalar是short型的向量,用來初始化矩陣  
Mat(Size size, int type, const Scalar & s)
  • size: 二位矩陣尺寸,Size(cols, rows),注意維數尺寸跟前面的構造函數是相反的
  • type和s:同上
Mat(int ndims, const int* sizes, type, const Scalar & s)
  • ndims: 第二個參數,size矩陣,的維數
  • sizes: 整型矩陣,規定Mat的尺寸
  • type和s:同上
Mat (const Mat &m)
Mat (const Mat &m, const Range &rowRange, const Range &colRange=Range::all())
Mat (const Mat &m, const Rect &roi)
Mat (const Mat &m, const Range *ranges)
  • m: 賦值矩陣,它的部分或者全部值將以指針傳遞給構造出的矩陣,注意數據不會被拷貝給新矩陣
  • 其他參數:規定賦值部分的范圍
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)
Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=0)
  • data:指向用戶數據的指針,構造的矩陣將指向這些用戶數據,沒有進行數據拷貝
  • step:矩陣更新到下一行需要跨過的字節數,如果矩陣每行的尾部包含無用的填充數據,需要把這部分計算進去,自動計算時設為cols*elemSize()
  • 其他參數:設置矩陣的大小和類型 
Mat::Mat(const IplImage* img, bool copyData=false)
  • img: IplImage類型的圖,利用它來創建信息頭
  Mat (const std::vector< _Tp > &vec, bool copyData=false)
  • vec:STL vector,矩陣行數等於vec的元素數,矩陣的數據類型與vec相同,因此vec必須為單一類型的數據結構。默認情況下,不會進行數據拷貝,這種情況下在矩陣被釋放之前,不能再向vec內加入新數據(這樣會造成存儲空間重新分配,之前的指針可能會失效)或進行其他可能改變vec內存空間的操作。

  

其他構造函數可以參見OpenCV Documentation: 

OpenCV3

OpenCV2

其他初始化方法

void    create (int rows, int cols, int type)
void    create (Size size, int type)
void    create (int ndims, const int *sizes, int type)

分配新內存,但不能為矩陣設置初值。大部分需要分配空間的OpenCV函數都會從內部調用這個函數,所以在調用他們之前不用手動分配內存空間

  • 如果現在矩陣的形狀數據類型與目標相同,直接返回。否則釋放原來的內存空間。
  • 初始化新矩陣頭
  • 分配total()*elemSize()字節內存
  • 設置新的對象計數值,並設為1
static MatExpr eye (int rows, int cols, int type)
static MatExpr  eye (Size size, int type)
static MatExpr  ones (int rows, int cols, int type)
static MatExpr  ones (Size size, int type)
static MatExpr  ones (int ndims, const int *sz, int type)
static MatExpr  zeros (int rows, int cols, int type)
static MatExpr  zeros (Size size, int type)
static MatExpr  zeros (int ndims, const int *sz, int type)

Matlab形式的初始化方式。MatExpr是Matrix expression representation,可以進行各種矩陣運算操作。用法如下,

Mat E = Mat::eye(4,4,CV_64F);
Mat O = Mat::ones(2,2,CV_32F)*0.1;

逗號分隔式初始化

Mat C = (Mat_<double>(3,3) << 0,-1,0, -1,5,-1, 0,-1,0);
Mat     clone () const
void    copyTo (OutputArray m) const
void    copyTo (OutputArray m, InputArray mask) const

拷貝矩陣,回先調用create函數分配內存空間,

  • mask:非零數據代表了需要拷貝的數據,如果傳遞了這個參數那么分配完內存空間后,矩陣先被初始化為0,mask是CV_8U類型可以包含一個或多個通道

格式化輸出方法

5種輸出風格:OpenCV默認,Python,逗號分隔,Numpy, C語言風格。事例程序和運行結果如下:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
// main
int main( int argc, char** argv )
{
    cv::Mat r = cv::Mat(10,3,CV_8UC3);
    cv::randu(r, cv::Scalar::all(0), cv::Scalar::all(255));
    
    // [1] OpenCV default style
    std::cout << "r (OpenCV default style) = \n" << r << ";" << std::endl << std::endl;
    
    // [2] Python style
    // OpenCV2
    // std::cout << "r (Python style) = " << format(r,"python") << ";" << std::endl << std::endl;
    // OpenCV3
    std::cout << "r (Python style) = \n" << format(r,cv::Formatter::FMT_PYTHON) << ";" << std::endl << std::endl;
    
    // [3] Comma separated values (CSV)
    // OpenCV2
    // std::cout << "r (CSV style) = " << format(r,"csv") << ";" << std::endl << std::endl;
    // OpenCV3
    std::cout << "r (CSV style) = \n" << format(r,cv::Formatter::FMT_CSV) << ";" << std::endl << std::endl;
    
    // [4] Numpy style
    // OpenCV2
    // std::cout << "r (Numpy style) = " << format(r,"numpy") << ";" << std::endl << std::endl;
    // OpenCV3
    std::cout << "r (Numpy style) = \n" << format(r,cv::Formatter::FMT_NUMPY) << ";" << std::endl << std::endl;
    
    // [3] C style
    // OpenCV2
    // std::cout << "r (C style) = " << format(r,"C") << ";" << std::endl << std::endl;
    // OpenCV3
    std::cout << "r (C style) = \n" << format(r,cv::Formatter::FMT_C) << ";" << std::endl << std::endl;
    
    return 0;
}
r (OpenCV default style) = 
[ 91,   2,  79, 179,  52, 205, 236,   8, 181;
 239,  26, 248, 207, 218,  45, 183, 158, 101;
 102,  18, 118,  68, 210, 139, 198, 207, 211;
 181, 162, 197, 191, 196,  40,   7, 243, 230;
  45,   6,  48, 173, 242, 125, 175,  90,  63;
  90,  22, 112, 221, 167, 224, 113, 208, 123;
 214,  35, 229,   6, 143, 138,  98,  81, 118;
 187, 167, 140, 218, 178,  23,  43, 133, 154;
 150,  76, 101,   8,  38, 238,  84,  47,   7;
 117, 246, 163, 237,  69, 129,  60, 101,  41];

r (Python style) = 
[[[ 91,   2,  79], [179,  52, 205], [236,   8, 181]],
 [[239,  26, 248], [207, 218,  45], [183, 158, 101]],
 [[102,  18, 118], [ 68, 210, 139], [198, 207, 211]],
 [[181, 162, 197], [191, 196,  40], [  7, 243, 230]],
 [[ 45,   6,  48], [173, 242, 125], [175,  90,  63]],
 [[ 90,  22, 112], [221, 167, 224], [113, 208, 123]],
 [[214,  35, 229], [  6, 143, 138], [ 98,  81, 118]],
 [[187, 167, 140], [218, 178,  23], [ 43, 133, 154]],
 [[150,  76, 101], [  8,  38, 238], [ 84,  47,   7]],
 [[117, 246, 163], [237,  69, 129], [ 60, 101,  41]]];

r (CSV style) = 
 91,   2,  79, 179,  52, 205, 236,   8, 181
239,  26, 248, 207, 218,  45, 183, 158, 101
102,  18, 118,  68, 210, 139, 198, 207, 211
181, 162, 197, 191, 196,  40,   7, 243, 230
 45,   6,  48, 173, 242, 125, 175,  90,  63
 90,  22, 112, 221, 167, 224, 113, 208, 123
214,  35, 229,   6, 143, 138,  98,  81, 118
187, 167, 140, 218, 178,  23,  43, 133, 154
150,  76, 101,   8,  38, 238,  84,  47,   7
117, 246, 163, 237,  69, 129,  60, 101,  41
;

r (Numpy style) = 
array([[[ 91,   2,  79], [179,  52, 205], [236,   8, 181]],
       [[239,  26, 248], [207, 218,  45], [183, 158, 101]],
       [[102,  18, 118], [ 68, 210, 139], [198, 207, 211]],
       [[181, 162, 197], [191, 196,  40], [  7, 243, 230]],
       [[ 45,   6,  48], [173, 242, 125], [175,  90,  63]],
       [[ 90,  22, 112], [221, 167, 224], [113, 208, 123]],
       [[214,  35, 229], [  6, 143, 138], [ 98,  81, 118]],
       [[187, 167, 140], [218, 178,  23], [ 43, 133, 154]],
       [[150,  76, 101], [  8,  38, 238], [ 84,  47,   7]],
       [[117, 246, 163], [237,  69, 129], [ 60, 101,  41]]], dtype='uint8');

r (C style) = 
{ 91,   2,  79, 179,  52, 205, 236,   8, 181,
 239,  26, 248, 207, 218,  45, 183, 158, 101,
 102,  18, 118,  68, 210, 139, 198, 207, 211,
 181, 162, 197, 191, 196,  40,   7, 243, 230,
  45,   6,  48, 173, 242, 125, 175,  90,  63,
  90,  22, 112, 221, 167, 224, 113, 208, 123,
 214,  35, 229,   6, 143, 138,  98,  81, 118,
 187, 167, 140, 218, 178,  23,  43, 133, 154,
 150,  76, 101,   8,  38, 238,  84,  47,   7,
 117, 246, 163, 237,  69, 129,  60, 101,  41};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM