OpenCV原始碼閱讀 1 1 Mat的結構

2021-06-22 15:27:20 字數 4098 閱讀 3598

抱著學習的態度,閱讀opencv原始碼。我閱讀的版本是opencv2.4.8,其實2.x在思路上是很相似的。opencv自帶了詳盡的文件。其中opencv_tutorials.pdf是opencv入門文件,該文件中有大量的示例;opencv2refman.pdf是函式手冊。這兩個文件也是重要的參考資料。

本章主要內容:mat類的結構、記憶體管理、運算、_inputarray類

主要涉及檔案有:

include         |  opencv2  |  core  |  core.hpp                     其中有mat類定義

|  mat.hpp                     其中有mat類實現

|  types_c.h                   c語言型別定義和部分函式

modules      |       core    |    src   |  arithm.cpp                 演算法實現

|  matop.cpp                 mat的運算

mat是opencv中最關鍵的類之一,破解mat類對把握opencv有重要作用,同時通過這部分閱讀可以了解opencv的設計理念。

另外,opencv中定義了matx(小矩陣)的結構,vec(向量)是matx的子類。他們通過_inputarray(輸入陣列)類實現相互轉換。在矩陣運算、影象處理等函式中,通過以_inputarray類為**,訪問mat或vec。mat_是mat的子類,是mat的模板化。

【core.hpp 1475-2010行】【opencv2refman.pdf 25-44頁】

/*! includes several bit-fields:

- the magic signature

- continuity flag

- depth

- number of channels

*/int flags;

//! the matrix dimensionality, >= 2

int dims;

//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions

int rows, cols;

//! pointer to the data

uchar* data;

//! pointer to the reference counter;

// when matrix points to user-allocated data, the pointer is null

int* refcount;

//! helper fields used in locateroi and adjustroi

uchar* datastart;

uchar* dataend;

uchar* datalimit;

//! custom allocator

matallocator* allocator;

msize size;

mstep step;

(1) flag

是標記,他由五部分組成:

1、0-2位:深度,在types_c.h中深度值如下:

cv_8u

00x000

cv_8s

10x001

cv_16u

20x010

cv_16s

30x011

cv_32s

40x100

cv_32f

50x101

cv_64f

60x110

cv_usrtype1

70x111

2、3-11位:通道數減1,因為即灰度影象(1通道)時3-11位是0x000000000,彩色影象(

3通道)時3-11位是0x000000010

3、14位:mat_cont_flag,矩陣的資料儲存是否連續的標記,1表示連續,0表示不連續

4、15位:submat_flag,子矩陣標記,mat支援從大矩陣中取出子矩陣,資料沒有複製。

例如,假設mat a是3×3的矩陣

| 1  2  3 |

a = | 4  5  6 |

| 7  8  9 |

mat b = a.rowrange(1,2);//b取a的第2到3行,行號以0開始
則 b = | 4  5  6 |  

| 7  8  9 |, 

b的資料並沒有新增加,而是直接指向了a的資料,b的datastart和dataend表明了起止位置,rows和cols表明了尺寸。具體將在mat的記憶體管理中說明。

5、16-31位:預設的標記

magic_val,由於矩陣有很多種型別,

_inputarray**所有的資料輸入時,需要依賴這個量來判斷資料型別,

這個值就表達了該類的型別。

檢視原始碼可以知道 型別

magic_val

值sparsemat(係數矩陣)

0x42fd0000

mat0x42ff0000

cvmat

0x42420000

cvma***

0x42430000

cvsparsemat

0x42440000

cvhistogram

0x42450000

cvmemstorage

0x42890000

cvseq

0x42990000

cvset

0x42980000

iplimage

0x00000070

他們都是類或結構體的前兩個位元組(int)。iplimage來自以往的庫,他的前兩個位元組是int  nsize,是結構體的大小,也就是說他的magic_val是0x00000070。

(2)dims是維度(一般是2);rows是行數;cols是列數。

(3)data指標指向了資料;refcount指標指向了乙個計數器,這個計數器記錄著多少個mat指向了同乙個data,當計數為0時,釋放data;allocator是動態記憶體申請器。

(4)step儲存了一行的寬度,完整連續的影象step.p[0]與cols相等,子矩陣的step.p[0]與原始影象的cols相等。

**注釋非常給力,以下幾行注釋清楚地表現了mat的結構:

建構函式、賦值運算、型別轉換都表現了資料轉換能力:

(1)建構函式

1、空建構函式【

1690行】

2、指定尺寸和型別【1692行】,或由scalar結構定義尺寸和型別【1696行】

3、高維【

1700行】

4、從其他mat拷貝【1704行】

5、從資料塊拷貝並指定尺寸和型別【1706行】

6、只定義乙個頭,資料指向其他mat中一部分(行列範圍、roi)【1711行】

7、從老式的cvmat、cvma***、iplimage轉換成mat【1715-1719行

】8、從新式的std::vector、cv::vec、cv::matx、2d point、3d point、comma initializer轉換成mat【1722-1731行】

(2)賦值運算

9、const mat& m從另乙個mat轉換【1740行】

10、const matexpr& expr從矩陣表示式轉換成mat【1741行】

矩陣表示式matexpr,構造了乙個運算結構,具體在mat的計算中解釋

11、const scalar& s從scalar轉換成mat,是用一種顏色將整個影象填充【1774行】

(3)資料轉換運算

11、括號運算子:擷取子矩陣【1842-1844行】

12、資料轉換:由mat轉換成老式結構cvmat、cvma***、iplimage【1846-1851行】

13、資料轉換:由mat轉換成

vector<_tp>、

vec<_tp n>、

matx<_tp m n>【1853-1855行】

OpenCV原始碼閱讀 1

開始從讀取檔案的函式說起,這裡主要有兩個函式用於讀取影象的 實際上,當我們在做數字影象處理系統的時候,主要要考慮的也是怎麼讀乙個進來。第乙個函式 cvloadimage主要是用於返回乙個iplimage 的資料結構。第二個函式 cvloadimagem主要是用於返回乙個cvmat 的資料結構。實際上...

Opencv原始碼閱讀 HogDescriptor

opencv中hog特徵提取寫在類hogdescriptor中 預設的建構函式如下 cv wraphogdescriptor winsize 64,128 blocksize 16,16 blockstride 8,8 cellsize 8,8 nbins 9 derivaperture 1 win...

Digester 1 1 原始碼閱讀

size medium 前一段時間我們閱讀了digester的最初始的版本1.0版,現在我們再看一下1.1版,看看變化 來領悟作者的重構思路。首先我們來看一下這個版本的更新 size size medium 1.增加了乙個rules介面,原來是放到digester裡面的 用乙個hashmap 的來儲...