在opencv早期的版本中,圖像通過一個(gè)叫做IplImage的結(jié)構(gòu)(structure)存儲在內(nèi)存中。由于C語言對程序員高度的信任,因此它需要手動地對內(nèi)存進(jìn)行管理,比如內(nèi)存的分配和回收,這在大型程序設(shè)計(jì)中是比較麻煩的。幸運(yùn)地是,C++可以很好地幫助程序員管理內(nèi)存,因此opencv2.0后就引入了C++接口。但是C++也有缺點(diǎn),比如說目前大部分的嵌入式系統(tǒng)只支持C語言,在這些平臺上開發(fā)opencv程序的話用C++就不是很好。
cv::Mat是一個(gè)C++類,包含兩部分:1)Matrix header,包括矩陣的size、存儲方式、矩陣的存儲地址等信息;2)指向Marix的指針ji。由于圖像處理算法通常都是計(jì)算密集型算法,出于程序速度上的考慮,opencv的設(shè)計(jì)應(yīng)盡可能地避免拷貝大圖像,為了解決這個(gè)問題,opencv使用了引用計(jì)數(shù)機(jī)制(reference counter system)【python也使用了這個(gè)機(jī)制,參考之前的博客】。簡單來說,滅個(gè)Mat對象都有自己的header,在進(jìn)行copy運(yùn)算時(shí),只有headers和指向矩陣的指針會被拷貝,而矩陣本身不會被拷貝,舉個(gè)栗子:
上面的三個(gè)Mat對象srcImg,dstImg,C最終都只想同一個(gè)數(shù)據(jù)矩陣,雖然它們的headers是不同的。對它們其中的任意一個(gè)進(jìn)行修改都會影響另外兩個(gè)對象。上面程序的運(yùn)行結(jié)果如圖:
當(dāng)然,如果想拷貝矩陣本身也是有辦法的,opencv提供了兩個(gè)方法:clone()和copyTo():
Mat F = A.clone();
Mat G;
A.copyTo(G);
最后總結(jié)一下:
1)opencv函數(shù)中輸出圖像的內(nèi)存是自動分配的;
2)賦值運(yùn)算和拷貝構(gòu)造函數(shù)只是拷貝了header,我們可以把這種拷貝理解為一種淺拷貝;
3)如果想進(jìn)行深拷貝,即拷貝矩陣本身的數(shù)據(jù),可以采用clone()或copyTo()函數(shù)。
對1和2的理解可以很重要,這可以解釋下面這個(gè)程序:
其運(yùn)行結(jié)果為:
關(guān)于如何創(chuàng)建一個(gè)Mat對象,最好的辦法就是看mat.hpp,因?yàn)閷?shí)在有太多了...,這里在介紹一下opencv里面的一下data
type,比如說CV_8UC3,CV_32FC3,CV_32F是什么意思:
CV_[the number of bits per item][signed or unsigned][Type prefix]C[The channel number]
最后是一個(gè)大頭部分:介紹如何遍歷cv::Mat。
Q1:圖像在Mat中是如何存儲的呢?
通常我們有足夠多的內(nèi)存,使得上面這個(gè)矩陣可以一行接著一行地連續(xù)存儲,具體是不是呢,可以用isContinous()函數(shù)來判斷。因此最高效的遍歷方法還是采用指針(還有迭代器方法):
-
C++
+關(guān)注
關(guān)注
22文章
2114瀏覽量
73773 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41451 -
python
+關(guān)注
關(guān)注
56文章
4805瀏覽量
84928
原文標(biāo)題:opencv——Mat數(shù)據(jù)格式及其遍歷
文章出處:【微信號:C_Expert,微信公眾號:C語言專家集中營】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論