OpenCv學習筆記(四)--Mat基本映像容器Mat對象資訊頭,矩陣體的建立,深複製,淺複製詳解

來源:互聯網
上載者:User

1--我們知道Mat是一個映像容器類,這個資料結構由兩部分組成:1--矩陣頭--即class Mat類所執行個體化的類對象所開闢的空間裡面儲存的資料---就是這個矩陣的資訊,當我們以   Mat object;這樣聲明類對象的時候,也僅僅是建立了一個Mat的資訊頭,並沒有建立矩陣體,也就是說,我們並   沒有給將要儲存的映像開闢相應的空間2--矩陣頭--包含:1--矩陣的尺寸----比如---class Mat這個類中的----資料成員rows,cols---就可以指定映像的尺寸2--儲存方法------對應---各種Mat的建構函式3--儲存地址4--和一個指向----儲存所有像素值的矩陣的----指標2--因此,當在程式中,傳遞映像並建立拷貝時,大的開銷是由矩陣造成的,而不是資訊頭。3--OpenCv是一個影像處理庫,囊括了大量的影像處理函數,為瞭解決問題,通常要使用庫中的多個函數,因此,在函數中傳   遞映像是家常便飯的事情.同時,不要忘了我們正在討論的是計算量很大的圖形處理演算法,因此,除非萬不得已,我們不應該   拷貝大的映像,因為這會降低程式的速度4--為了搞定這個問題,OpenCv使用---引用計數機制,其思路就是讓每個Mat對象有自己的資訊頭,但共用一個矩陣。通過讓矩陣   指標指向同一地址而實現。而拷貝建構函式則只拷貝:1--資訊頭2--矩陣指標而不拷貝矩陣./*********************************************************************************************程式功能:        Mat基本映像容器Mat對象資訊頭,矩陣體的建立,深複製,淺複製詳解編寫環境:        OpenCv2.4.8+VS2010地點時間:        陝西師範大學 2016.4.25作者資訊:        九月**********************************************************************************************//********************************【標頭檔.命名空間包含部分】***********************************/#include<opencv2/highgui/highgui.hpp>#include<opencv2/core/core.hpp>#include<iostream>using namespace cv;using namespace std;#define MAT_INFO_HEADER_SIZE  "Mat映像容器類資訊頭所佔記憶體空間的大小----->"#define WINDOW_SRC_NAME       "【原始映像】"#define WINDOW_DST_NAME       "【複製建構函式映像】"#define WINDOW_ASSIGN_NAME    "【賦值映像】"#define WINDOW_ROI_NAME       "【ROI原映像部分資料】"#define WINDOW_RANGE_NAME     "【Range指定的映像資料部分】"/*****************************************【main()函數】**************************************/int main(int argc,char** argv){/*****   在這裡需要說明的一點是,C++中類對象的定義和java中對象的定義是有巨大區別的:*【1】C++中,當定義一個類的對象時,就為其分配了類的儲存空間---說的通俗一點,就是說C++中,當用*     一個類去定義一個類對象時,其實就是將類---進行了執行個體化,產生了一個類的----具體執行個體   *【2】而java中,類對象的定義和類對對象的執行個體化是分開進行的:*    【1】Person lili---類對象的定義---開闢了一個四個位元組的空間----lili這個類對象其實相當於*         C++中的一個對象指標,此時並沒有產生類的---具體執行個體*    【2】Java中只能手動的,用new關鍵字去執行個體化一個類的對象,如下所示:*         lili=new Person();****///【1】只建立了資訊頭部分Mat src,assign;//【2】我們在這裡測試一下,Mat資訊頭所佔記憶體空間的大小cout<<MAT_INFO_HEADER_SIZE<<sizeof(src)<<"位元組"<<endl;    //【3】在這裡,為矩陣開闢了記憶體空間---這相當於---矩陣體src=imread("D:\\scenery.png",CV_LOAD_IMAGE_COLOR);    //【4】顯示圖片imshow(WINDOW_SRC_NAME,src);//【5】使用拷貝建構函式,只複製矩陣的資訊頭-----典型的淺複製Mat dst(src);assign=src;//【6】顯示圖片imshow(WINDOW_DST_NAME,dst);imshow(WINDOW_ASSIGN_NAME,assign);/*****【1】通過上述代碼的結果可知.所有的Mat對象最終都指向了一個也是唯一的一個----資料矩陣。雖然它們的*     資訊頭不同,但是通過任何一個對象對映像矩陣所做的改變也會影響其它對象*【2】實際上,不同的Mat類對象,只是訪問相同資料的不同途徑而已****//*****【1】這裡介紹一個比較厲害的功能:你可以建立只引用---映像矩陣部分資料---的資訊頭。比如想要建立一個*     感興趣的地區(ROI),你只需要建立包含邊界資訊的資訊頭*【2】執行個體如下所示:*     Mat dstROI(src,Rect(0,0,100,100))*     Mat dstROI_1(Range:all(),Range(1,3))****///【7】使用一個矩形,定義ROI地區Mat dstROI(src,Rect(0,0,200,200));//【8】建立視窗+顯示映像namedWindow(WINDOW_ROI_NAME,CV_WINDOW_AUTOSIZE);imshow(WINDOW_ROI_NAME,dstROI);//【9】用行rows和列cols截取原圖指定地區的映像//【10】指定的src映像的地區包括映像的所有行和從第0列到第199列//【11】Mat Mat::operator()( Range _rowRange, Range _colRange ) const----為src對象的子數組建立        //新的資訊頭,底下的相當於src.colRange()Mat dstRange=src(Range::all(),Range(0,200));namedWindow(WINDOW_RANGE_NAME,CV_WINDOW_AUTOSIZE);imshow(WINDOW_RANGE_NAME,dstRange);/***【1】現在你也許會問,如果矩陣屬於多個Mat對象,那麼當不在需要它時,誰來負責清理呢。答案是:最後一個*     使用它的對象。通過引用計數機制來實現.無論什麼時候,有人拷貝一個Mat對象的資訊頭,都會增加矩陣的*     引用次數;反之,當一個頭被釋放後,這個計數減一;當計數為零時,矩陣會被清理。*【2】在這塊我們通過Mat src這樣的方法建立的類對象都是----類的靜態對象,在程式啟動並執行過程中,這樣的對象*     佔用的空間的分配和釋放的時間點是固定的***//***【1】但是,某些時候,你仍會想拷貝矩陣本身(不只是資訊頭和矩陣指標),這時你可以用---深複製---函數:*    Mat clone() const;* void copyTo( OutputArray m ) const;* void copyTo( OutputArray m, InputArray mask ) const;  **/Mat dstDeep1=src.clone();Mat dstDeep2;src.copyTo(src);    //【12】經過深複製後,這時,我們再改變,就再也不會影響原映像了//【13】比如說,我們現在將映像中的所有元素都置為白色//【14】存取彩色映像的像素for(int i=0;i<dstDeep1.rows;i++){for(int j=0;j<dstDeep1.cols;j++){dstDeep1.at<Vec3b>(i,j)[0]=255;//藍色通道dstDeep1.at<Vec3b>(i,j)[1]=255;//紅色通道dstDeep1.at<Vec3b>(i,j)[2]=255;//綠色通道}}imshow("【原始映像】",src);imshow("【經過深複製處理過後的映像】",dstDeep1);waitKey(0);}現在,總結一下,我們需要記住的是:1--OpenCv函數中輸出映像的記憶體配置是自動完成的(如果不是特別指定的話)2--使用OpenCv的C++介面時,不需要考慮記憶體釋放問題3--複製運算子和拷貝建構函式只拷貝---資訊頭4--使用函數clone()或者copyTo()來拷貝一副映像的矩陣

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.