Mat
OpenCV 自 2001 年出現以來。在那些日子里庫是圍繞C接口構建的。在那些日子里,他們使用名為IplImage C 的結構在內存中存儲圖像。這是您將在大多數較舊的教程和教材中看到的那個。使用這個結構的問題是將 C 語言的所有負面效果都擺到了桌面上。最大的問題是手動管理。它是建立在用戶來負責處理內存分配和解除分配的假設之上的。當程序規模較小時,這是沒有問題的,一旦代碼基開始變得越來越大它將會越來越掙扎着處理所有這一切而不是着眼於實際解決自己的開發目標。
幸運的是 c + + 出現了,並引入了類的概念,使得為用戶開辟另一條路成為可能:
自動內存管理 (或多或少)。好消息是,c + +,如果完全兼容 C 所以進行更改時沒有兼容性問題產生。因此, OpenCV其2.0 版本引入一個新的c + + 接口,通過利用這些優點將為你的工作提供新的方法。某種程度上,在其中您不需要撥弄內存管理讓你的代碼簡潔 (寫得更少,實現的更多)。C + + 接口的唯一主要缺點在於,目前許多嵌入式的開發系統支持僅 C.因此,除非您的目標是這一平台,否則就沒有理由再使用舊的方法(除非你是個受虐狂程序員和喜歡自討苦吃)。
你需要知道的關於Mat的第一件事是你不再需要手動分配其大小並且當你不需要它的時候你不再需要手動釋放它。雖然這樣做仍然是可能的,大多數 OpenCV 函數將手動分配其輸出數據。還有一個額外的好處是如果傳遞一個已存在Mat對象,它已經為矩陣分配所需的空間,這段空間將被重用。也就是說我們在任何時候只使用與我們執行任務時所必須多的內存一樣多的內存。
Mat本質上是由兩個數據部分組成的類:(包含信息有矩陣的大小,用於存儲的方法,矩陣存儲的地址等) 的矩陣頭和一個指針,指向包含了像素值的矩陣(可根據選擇用於存儲的方法采用任何維度存儲數據)。矩陣頭部的大小是恆定的。然而,矩陣本身的大小因圖像的不同而不同,通常是較大的數量級。因此,當你在您的程序中傳遞圖像並在有些時候創建圖像副本您需要花費很大的代價生成圖像矩陣本身,而不是圖像的頭部。OpenCV 是圖像處理庫,它包含大量的圖像處理函數。若要解決的計算挑戰,最終大部分時間你會使用庫中的多個函數。由於這一原因圖像傳給庫中的函數是一種常見的做法。我們不應忘記我們正在談論往往是計算量相當大的圖像處理算法。我們想要做的最后一件事是通過制作不必要的可能很大的圖像的拷貝進一步降低您的程序的速度。
為了解決這一問題 OpenCV 使用引用計數系統。其思想是Mat的每個對象具有其自己的頭,但可能他們通過讓他們矩陣指針指向同一地址的兩個實例之間共享該矩陣。此外,拷貝運算符將只能復制矩陣頭部,也還將復制指針到大型矩陣,但不是矩陣本身。(以上理解有點困難后續需要參考C++幾個重要函數)
Mat A,C; //進創建頭部
A = imread("……",1);//讀一張圖片
Mat B(A);//使用拷貝構造函數,或者還可以使用賦值運算符 B= A;
上文中的所有對象,以相同的單個數據矩陣的結束點。他們頭不同,但是使用的其中任何一個對矩陣進行任何修改,也將影響所有其他的。在實踐中的不同對象只是提供相同的底層數據不同的訪問方法,然而,它們的頭部是不同的。真正有趣的部分是您可以創建僅指向完整數據的一小部分的頭。例如,要在圖像中創建興趣區域 ( ROI) 您只需創建一個新頭設置新邊界:
Mat D (A,Rect(10,10,100,100)) ;//使用矩形界定
Mat E = A (Range::all(),Range(1,3)) ; //用行和列界定
現在,你可能會問是否矩陣的本身可以屬於多個Mat對象在不再需要時負責清理數據。簡短的回答是:最后一個使用它的對象。這對於使用引用計數的機制,每當有人復制Mat對象的頭,矩陣的計數器被增加。每當一個頭被清除,此計數器被下調。當該計數器變為零,矩陣也就被釋放了。因為有時會仍然也要復制矩陣的本身,存在着 clone() 或 copyTo() 函數。
Mat F = A.clone();
Mat G ;
A.copyto(G);
總結:
• 輸出圖像分配 OpenCV 功能是自動 (除非另行指定,否則)。
• 用c + + OpenCV的接口就無需考慮內存釋放。
• 賦值運算符和復制構造函數 (構造函數)只復制頭。
• 使用clone () 或copyTo () 函數將復制的圖像的基礎矩陣。
存儲方法
這是關於你是如何存儲的像素值。您可以選擇的顏色空間和使用的數據類型。色彩空間是指我們如何結合為了代碼指定的顏色的顏色分量。最簡單的是灰色的規模。在這里我們所掌握的顏色是黑色和白色。組合的這些讓我們能創造很多的灰度級。
對於彩色的方法,我們有很多方法可供選擇。不過,每一就是將他們拆解成三個或四個基本組成部分,這些部分就會組合給所有其他的方法。最受歡迎的這一個 RGB,主要是因為這也是我們的眼睛如何建立中我們的眼睛的顏色。其基准的顏色是紅、 綠、 藍。編寫代碼的一種顏色的透明度有時第四個元素: 添加 alpha (A)。
現在,每個建築構件都自己有效的域。這會導致使用的數據類型。我們如何存儲組件的定義只是如何精細的控制,我們已於其域。最小的數據類型可能是 char 類型,這意味着一個字節或 8 位。這可能是有符號(值-127 到 + 127)或無符號(以便可以存儲從 0 到 255 之間的值)。雖然這三個組件的情況下已經給 16 萬可能的顏色來表示 (如 RGB 的情況下) 我們可能通過使用浮點數 (4 字節 = 32 位) 或double(8 字節 = 64 位) 數據類型的每個組件獲得甚至更精細的控制。然而,請記住增加組件的大小也會增加在內存中的整張圖片的大小。
顯式創建Mat對象
1. Mat 構造函數
Mat M(2,2, CV_8UC3, Scalar(0,0,255));
cout<<"M = "<<M<<endl;
M = [0,0,255;0,0,255;0,0,255,0,0,255]
對於二維的和多通道的圖像,我們首先定義它們的大小:按行和列計數。
然后我們需要指定的數據類型,用於存儲元素和每個矩陣點通道的數量。為此,我們根據以下的約定可以作出多個定義:
CV_ [每一項的位數] [有符號或無符號] [類型前綴] C [通道數]
例如,CV_8UC3 意味着我們使用那些長的 8 位無符號的 char 類型和每個像素都有三個項目的這三個通道的形成。這是預定義的四個通道數字。Scalar 是四個元素短向量。指定此和可以初始化所有矩陣點與自定義的值。但是如果你需要更多您可以創建與上部宏和頻道號碼放在括號中,您可以看到下面的類型。
使用 C\C++ 數組和通過構造函數來初始化
-
int sz[3] = {2,2,2};
-
Mat L(3,sz,CV_8UC(1),Scalar::all(0));
2. 其余參考
https://blog.csdn.net/guyuealian/article/details/70159660
https://blog.csdn.net/yang_xian521/article/details/7107786
https://blog.csdn.net/ktigerhero3/article/details/77248922(矩陣基本操作)
https://blog.csdn.net/weixin_35695879/article/details/85948011
https://blog.csdn.net/qq_37406130/article/details/78725406(總結最好)