日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

OpenCV 笔记(06)— Mat 结构、像素值存储方法、创建 Mat 对象各种方法、Mat 对象的运算

發布時間:2023/11/28 生活经验 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV 笔记(06)— Mat 结构、像素值存储方法、创建 Mat 对象各种方法、Mat 对象的运算 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數字圖像中的每個點都稱為像素(對于圖像元素),并且每個像素可以存儲一個或多個值,這取決于它是否是僅存儲一個值的黑白圖像(也稱為二進制圖像,比如只存儲0或1),還是存儲兩個值的灰度圖像,或者是存儲三個值的彩色圖像。這些值通常在整數0~255,但也可以使用其他范圍,比如在高動態范圍成像(high dynamic range imaging,簡稱HDRI)或熱圖像領域中的浮點數0~1。

圖像是以矩陣格式存儲的,其中的每個像素都有一個位置,并且可以通過列和行的編號來引用。 OpenCVMat 類來達到這個目的。在灰度圖像中,使用單個矩陣,如下圖所示。


在下圖所示的彩色圖像中,使用了一個寬度×高度×顏色通道數的矩陣。

Mat 類不僅僅用于存儲圖像,它還能存儲任何類型和不同大小的矩陣。你可以將其用作代數矩陣并用它執行運算。在內存中,矩陣被保存為按列和行排序的數組或值序列。表2-1顯示 BGR 圖像格式的像素序列。

關于 Mat 類, 首先我們要知道的是:

  • 不必再手動為其幵辟空間。
  • 不必再在不需要時立即將空M釋放。

這里指的是手動開辟空間并非必須,但它依舊是存在的—大多數 OpenCV 函數仍會手動地為輸出數據幵辟空間。當傳遞一個已經存在的 Mat 對象時, 開辟好的矩陣空間會被重用。也就是說, 我們每次都使用大小正好的內存來完成任務。

1. Mat 結構

Mat 是一個類, 由兩個數據部分組成:矩陣頭(包含矩陣尺寸、存儲方法、存儲地址等信息) 和一個指向存儲所有像素值的矩陣(根據所選存儲方法的不同,矩陣可以是不同的維數)的指針。

矩陣頭的尺寸是常數值, 但矩陣本身的尺寸會依圖像的不同而不同,通常比矩陣頭的尺寸大數個數量級。因此,
當在程序中傳遞圖像并創建副本時,大的開銷是由矩陣造成的, 而不是信息頭。

為了解決此問題, OpenCV 使用了引用計數機制。其思路是讓每個 Mat 對象有自己的信息頭,但共享同一個矩陣。這通過讓矩陣指針指向同一地址而實現。而拷貝構造函數則只復制信息頭和矩陣指針, 而不復制矩陣。

Mat A, C; / / 僅創建信息頭部分
A = imread("1.jpg") / / 這里為矩陣開辟內存
Mat B(A); / /使用拷貝構造函教
C = A; / /賦值運算符

以上代碼中的所有 Mat 對象最終都指向同一個也是唯一一個數據矩陣。雖然它們的信息頭不同,但通過任何一個對象所做的改變也會影響其他對象。

我們可以創建只引用部分數據的信息頭。比如想要創建一個感興趣區域(ROI)只需要創建包含邊界信息的信息頭:

Mat D(A, Rect(10, 10, 100, 100)) ; / / 使用矩形界定
Mat E = A(Range:all() , Range(1,3)) ; / / 用行和列來界定

如果想復制矩陣本身( 不只是信息頭和矩陣指針),這時可以使用函數 clone() 或者 copyTo()

Mat F = A.clone() ;
Mat G;
A.copyTo(G) ;

現在改變 F 或者 G 就不會影響 Mat 信息頭所指向的矩陣。

總結如下:

  • OpenCV 函數中輸出圖像的內存分配是自動完成的(如果不特別指定的話);
  • 使用 OpenCVC++ 接口時不需要考慮內存釋放問題;
  • 賦值運算符和拷貝構造函數(構造函數)只復制信總頭;
  • 使用函數 clone() 或者 copyTo() 來復制一幅圖像的矩陣;

2. 像素值的存儲方法

存儲像素值需要指定顏色空間和數據類型。

  • 顏色空間是指針對一個給定的顏色,如何組合顏色元素以對其編碼。最簡單的顏色空間要屬灰度級空間, 只處理黑色和白色, 對它們進行組合便可以產生不同程度的灰色。

對于彩色方式則有更多種類的顏色空間, 但不論哪種方式都是把顏色分成三個或者四個基元素,通過組合基元素可以產生所有的顏色。 RGB 顏色空間是最常用的一種顏色空間,。它的基色是紅色、綠色和藍色,有時為了表示透明顏色也會加入第四個元素alpha ( A)。

每個組成元素都有自己的定義域, 而定義域収決于其數據類型,如何存儲一個元素決定了我們在其定義域上能夠控制的精度。最小的數據類型是 char ,占一個字節或者 8 位,可以是有符號型(0 到255 之間)或無符號型( -127 到+127之間)。盡管使用三個 char 型元素已經可以表示 1600 萬種可能的顏色(使用 RGB 顏色空間),但若使用 float ( 4 字節,32 位)或 double ( 8 字節,64 位)則能給出更加精細的顏色分辨能力。但同時也要切記, 增加元素的尺寸也會增加圖像所占的內存空間。

3. 創建 Mat 對象方法

我們可以通過 Mat 的運算符 << 來查看其值。但要記住, Mat 的運算符 << 只對二維矩陣有效。 Mat 不但是一個非常有用的圖像容器類,同時也是一個通用的矩陣類,我們也可以用它來創建和操作多維矩陣。

創建一個 Mat 對象有多種方法, 列舉如下:

3.1 使用 Mat 構造函數

最常用的方法是直接使用 Mat() 構造函數,示例如下:

	Mat M(3, 2, CV_8UC3, Scalar(0, 0, 255));cout << "M is "<< endl << M << endl;

輸出結果:

M is 
[  0,   0, 255,   0,   0, 255;0,   0, 255,   0,   0, 255;0,   0, 255,   0,   0, 255]

對于二維多通道圖像, 首先要定義其尺寸,即行數和列數。然后,需要指定存儲元素的數據類型以及每個矩陣點的通道數。為此,依據下面的規則有多種定義:

CV_ [ The number of bits per item] [ Signed or Unsigned] [ Type Prefix ] C [ The
channel number ]

即:

cv_[位數][帶符號與否][類型前綴]c[通道數]

比如 CV_8UC3 表示使用 8 位的 unsigned char 型,每個像素由三個元素組成三通道。而預先定義的通道數可以多達四個。另外, Scalar 是個 short 型的向量。

受支持的類型取決于要存儲的數字類型和通道數,最常見的類型如下:

CV_8UC1;
CV_8UC3;
CV_8UC4;CV_32FC1;
CV_32FC3;
CV_32FC4;

3.2 通過C++構造函數進行初始化

示例代碼:

	int sz[3] = {2,1,3};Mat M(3, sz, CV_8UC3, Scalar::all(0));

上面的例子演示了如何創建一個超過兩維的矩陣:指定維數,然后傳遞一個指向一個數組的指針,這個數組包含每個維度的尺寸。

3.3 利用 create() 函數

利用 Mat 類中的 Create() 成員函數進行 Mat 類的初始化操作,示范代碼如下。

	Mat M;M.create(4, 3, CV_8UC(2));cout << "M is "<< endl << M << endl;

輸出結果:

M is 
[  0,   0,   0,   0,   0,   0;0,   0,   0,   0,   0,   0;0,   0,   0,   0,   0,   0;0,   0,   0,   0,   0,   0]

需要注意的是,此創建方法不能為矩陣設初值,只是在改變尺寸時重新為矩陣數據開辟內存而已。

3.4 使用 zeros()、ones()、eyes() 初始化

示例代碼:

	Mat E = Mat::eye(3, 3, CV_64F);cout << "E is "<< endl << E << endl;Mat O = Mat::ones(3, 2, CV_32F);cout << "O is "<< endl << O << endl;Mat Z = Mat::zeros(3, 2, CV_8UC1);cout << "Z is "<< endl << Z << endl;

輸出結果:

E is 
[1, 0, 0;0, 1, 0;0, 0, 1]O is 
[1, 1;1, 1;1, 1]Z is 
[  0,   0;0,   0;0,   0]

3.5 對小矩陣使用逗號分隔初始化

示例代碼

	Mat C = (Mat_<double> (3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0 );cout << "C is "<< endl << C << endl;

輸出結果:

C is 
[0, -1, 0;-1, 5, -1;0, -1, 0]

3.6 為已存在的對象創建新信息頭

使用成員函數 clone() 或者 copyTo() 為一個已存在的 Mat 對象創建一個新的信息頭,示范代碼如下。

	Mat C = (Mat_<double> (3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0 );Mat RowClone = C.row (1).clone() ;cout << "RowClone is "<< endl << RowClone << endl;

輸出結果:

RowClone is 
[-1, 5, -1]

4. Mat 對象運算

OpenCVMat 類能夠執行所有的矩陣運算。我們可以用 +- 運算符來加上或減去兩個相同大小的矩陣,如以下代碼塊所示:

	Mat a = Mat::eye(Size(3, 2), CV_32F);Mat b = Mat::ones(Size(3, 2), CV_32F);Mat c = a + b;Mat d = a - b;

運算結果如下圖:

我們可以用 * 運算符乘以一個標量,或者用 mul 函數乘以矩陣的每個元素,也可以用 * 運算符執行矩陣乘法:

	Mat a = Mat::eye(2, 3, CV_32F);Mat b = Mat::ones(3, 2, CV_32F);// Mat a2 = a * 2;// Mat d = (a + 1).mul(b + 3);// Mat ab = a * b;cout << a * 2 << endl;cout << (a + 1).mul(b + 3) << endl;cout << a * b << endl;// cout << a + b << endl;// cout << a - b << endl;

理論上會有如下結果,但是調試發現報錯,待繼續分析。

其它運算請參考:
https://docs.opencv.org/2.4/modules/core/doc/core.html

總結

以上是生活随笔為你收集整理的OpenCV 笔记(06)— Mat 结构、像素值存储方法、创建 Mat 对象各种方法、Mat 对象的运算的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。