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