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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV参考手册之Mat类详解1

發(fā)布時間:2025/4/16 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV参考手册之Mat类详解1 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Mat類

OpenCV c + + n 維稠密數(shù)組類

class CV_EXPORTS Mat

{

public:

/ / … …很多的方法...

...

/*!包括幾位字段:

-神奇的簽名

-連續(xù)性標(biāo)志

-深度(Note:應(yīng)該是位深)

-通道數(shù)

*/

int flags;Note :目前還不知道flags做什么用的)

//!數(shù)組的維數(shù),> = 2

int dims ;

//!行和列的數(shù)量或 (-1,-1) 此時數(shù)組已超過 2 維

int rows,cols;

//!指向數(shù)據(jù)的指針

uchar *data ;

//!指針的引用計數(shù)器 ;

/ / 陣列指向用戶分配的數(shù)據(jù)時,當(dāng)指針為 NULL

int * refcount ;

/ / 其他成員

...

};

Mat類表示一個 n 維的稠密數(shù)值型的單通道或多通道數(shù)組。它可以用于存儲實數(shù)或復(fù)數(shù)值的向量和矩陣、灰度或彩色圖像、體素、向量場、點云、張量、直方圖 (盡管較高維的直方圖存儲在SparseMat可能更好)。M 數(shù)組的數(shù)據(jù)布局是由陣列? M.step[]定義的,使元素的地址(i0,。。。。iM.dims-1),其中 0<= ik?< M.size [k],可以計算為:

addr( Mi0?;:::;iM.dims-1) = M.data+ M.step[ 0]*i0?+ M.step[ 1] *i1?+ .…+ M.step[ M:dims- 1] iM:dims- 1

2維的數(shù)組的情況下根據(jù)上述公式被減至:

addr( Mi,j)= M.data+ M.step[ 0]*i+ M.step[ 1] *j

請注意,M.step[i] > =M.step[i+1] (事實上,M.step[i] > =M.step[i+1]*M.size[i+1])。這意味著2維矩陣是按行存儲的,3 維矩陣是由平面存儲,以此類推。M.step[M.dims-1] 是最小的而且總是等于元素大小M.elemSize()。因此,Mat中的數(shù)據(jù)布局完全兼容OpenCV 1.x 中CvMat、 IplImage、 CvMatND類型。它也和標(biāo)準(zhǔn)工具包和SDK,如Numpy(ndarray),Win32(獨立設(shè)備位圖)等主流的密集數(shù)組類型相兼容,也就是說,與任何使用步進(或步長)來計算像素位置的陣列相兼容。由于這種兼容性,使用戶分配的數(shù)據(jù)創(chuàng)建Mat頭以及用OpenCV函數(shù)實時處理該頭成為可能。有很多不同的方法,創(chuàng)建一個Mat的對象。下面列出了最常見的選項:

使用 create(nrows,ncols,type)方法或類似的Mat(nrows,ncols,type [,fillValue])構(gòu)造函數(shù)。一個新的指定了大小和類型的數(shù)組被分配。type和cvCreateMat 方法中的type參數(shù)具有相同的含義。

例如,CV_8UC1 是指一個 8 位單通道陣列,CV_32FC2 指 2 通道(復(fù)平面)浮點陣列,以此類推。

//創(chuàng)建一個用1+3j填充的 7 x 7 復(fù)矩陣。

Mat ?M(7,7,CV_32FC2,Scalar(1,3)) ;

/ /現(xiàn)在將 M轉(zhuǎn)換為100 x 60的CV_8UC(15)的矩陣。

/ / 舊內(nèi)容將會被釋放

M.create(100,60,CV_8UC(15)) ;

這一章導(dǎo)言中指出,當(dāng)當(dāng)前的數(shù)組與指定的數(shù)組的形狀或類型create() 分配唯一的新數(shù)組時的形狀或類型。

創(chuàng)建多維數(shù)組:

/ / 創(chuàng)建 100 x 100 x 100 8 位數(shù)組

int sz[] = {100, 100, 100};

Mat. bigCube (3,sz,CV_8U,Scalar::all(0)) ;它將維度數(shù)(= 1)傳遞給Mat的構(gòu)造函數(shù),但列數(shù)設(shè)置為 1時,創(chuàng)建數(shù)組將是 2 維的。因此,Mat::dims 始終是>=2的(該數(shù)組為空時,也可以是 0)。

使用的復(fù)制構(gòu)造函數(shù)或賦值運算符可以是一個數(shù)組或右側(cè)的表達式(請參閱下圖)。正像在導(dǎo)言中指出的,數(shù)組賦值運算復(fù)雜度是O(1)因為當(dāng)你需要它的時候,它僅復(fù)制頭和增加引用計數(shù)。Mat::clone() 方法可用于獲取全(深)的副本數(shù)組。

為另一個數(shù)組的一部分構(gòu)建頭。它可以是單個行、 單個列,幾個行,幾個列,矩形區(qū)域(代數(shù)中稱為較小值) 的數(shù)組或?qū)蔷€。這種操作也是復(fù)雜度為O(1),因為,新頭引用相同的數(shù)據(jù)。實際上,您可以使用此特性修改該數(shù)組的一部分例如:

/ /第 5行,乘以 3,加到第 3 行,

M.row(3) = M.row(3) + M.row (5) * 3 ;

/ / 現(xiàn)在將第7列復(fù)制到第1列

/ / M.col(1) = M.col(7) ;/ / 這個不能實現(xiàn)。

Mat? M1= M.col(1) ;

M.col(7).copyTo(M1) ;

/ / 創(chuàng)建一種新的 320 x 240 圖像

Mat img(Size(320,240),CV_8UC3) ;

/ / 選擇ROI(region of interest)

Mat roi(img,Rect(10,10,100,100)) ;

/ / 填充 (0,255,0) 的ROI (這是RGB 空間中的綠色);

/ / 320 x 240 原始圖像將被修改。

roi = Scalar(0,255,0) ;

由于額外的 datastart 和 dataend 的成員,它們使得用locateROI() 計算子數(shù)組在主容器數(shù)組中的相對的位置成為可能:

Mat A = Mat::eye ( 10, 10, CV_32S);

/ / 提取 A 的1 (含)到 3 (不包含)列。

Mat B = A(Range::all(),Range(1,3)) ;

/ / 提取 B 的5 (含)到 9 (不包含)行。

/ /即 C ~ A(Range(5,9),Range (1,3))

Mat C = B(Range(5,9),Range::all()) ;

Size size;Point ofs;

C.locateROI (size,ofs);

/ / size將變?yōu)?(width= 10,height= 10),ofs會變?yōu)?(x = 1,y = 5)

考慮到整個矩陣,如果您需要深層副本,使用子矩陣的sclone() 方法的提取。

為用戶分配數(shù)據(jù)創(chuàng)建矩陣頭。有利于執(zhí)行下列操作:

1. 使用 OpenCV處理"外來"的數(shù)據(jù)(例如,當(dāng)您執(zhí)行 DirectShow *?lter 或 gstreamer的pro-cessing 模塊,等等)。例如:

void process_video_frame (const unsignedchar * pixels,

int width,int height,int step)

{

Mat img (width,height, CV_8UC3,pixels,step);

GaussianBlur (img,img ,Size(7,7),1.5,1.5) ;

}

2.快速初始化小矩陣和/或獲取超快的元素的訪問。

double m[3] [3] = {{a,b,c},{d,e,f} {g, h, i}}};

Mat M = Mat(3,3,CV_64F,m).inv() ;

本例中用戶分配數(shù)據(jù)的一些很常見情況是從CvMat 和 IplImage 轉(zhuǎn)換到Mat。為達到此目的,有些特殊的構(gòu)造函數(shù)以指向CvMat 或 IplImage 和?ag可選參數(shù)指示是否數(shù)據(jù)復(fù)制。從Mat到 CvMat 或 IplImage 的后臺轉(zhuǎn)換是通過類型轉(zhuǎn)換運算符 Mat::operator CvMat() const 和 Mat::operator IplImage()實現(xiàn)的。operators不要復(fù)制數(shù)據(jù)。

IplImage * img = cvLoadImage("greatwave.jpg",1) ;

Mat mtx(img) ;/ / IplImage *-> Mat

CvMat oldmat = mtx ;/ / Mat-> CvMat

CV_Assert (oldmat.cols = = img-> width&& oldmat.rows = = img-> height & &

oldmat.data.ptr = = (uchar *) img->imageData & & oldmat.step = = img-> widthStep);

使用 MATLAB 樣式數(shù)組初始值設(shè)定項zeros()、 ones()、 eye(),例如:

/ / 創(chuàng)建具雙精度標(biāo)識矩陣并將其添加到M。

M + = Mat::eye (M.rows,M.cols,CV_64F);

使用逗號分隔的初始值設(shè)定項:

/ / 創(chuàng)建 3 x 3 雙精度恒等矩陣

Mat M = (Mat_ <double> (3,3) <<1,0,0,0,1,0,0,0,1) ;

使用此方法,您首先調(diào)用具有適當(dāng)?shù)膮?shù)的 Mat_類構(gòu)造函數(shù),然后只要把 << 運算符后面的值用逗號分隔,這些值可以是常量、變量、 表達式,等等。此外請注意所需的額外的圓括號((Mat_<double> (3,3)<< 1,0,0,0,1,0,0,0,1))以免出現(xiàn)編譯錯誤。

數(shù)組一旦創(chuàng)建起來,它可以自動通過引用計數(shù)的機制被管理。如果數(shù)組頭是在用戶分配的數(shù)據(jù)的基礎(chǔ)上構(gòu)建的,您應(yīng)該自己處理這些數(shù)據(jù)。當(dāng)沒有指向它的引用時,數(shù)組中的數(shù)據(jù)將被釋放。如果在數(shù)組的析構(gòu)函被調(diào)用之前要釋放一個由矩陣頭指向的數(shù)據(jù),請使用Mat::release()。

掌握Array類的另一個重要的環(huán)節(jié)是元素的訪問。本手冊已經(jīng)描述了如何計算每個數(shù)組元素的地址。通常情況下,不需要在代碼中直接使用的公式。如果你知道數(shù)組元素類型(它可以使用 Mat::type() 方法檢索得到),您可以用以下方式訪問二維數(shù)組的元素Mij

M.at <double>(i,j)? + = 1.f ;

假定 M 一個雙精度浮點型數(shù)組。有幾個變體的不同方法來針對不同的維度數(shù)進行處理。

如果您要處理整行的二維數(shù)組,最有效的方式是獲取該行的頭指針然后只需使用普通的 C運算符[]:

/ / 正矩陣元素之和計算

/ / (假定M 是一個雙精度矩陣)

double sum = 0;

for (int i = 0 ;i < M.rows ; i + +)

{

const double *Mi = M.ptr <double> (i) ;

???? for (int j = 0; j < M.cols ; j + +)

sum + = std::max(Mi [j],0.) ;

}

以上的操作中,某些操作實際上不依賴該數(shù)組的形狀。他們只是一個接一個(或多個具有相同的坐標(biāo)的多個數(shù)組中的元素,例如,數(shù)組相加)地處理數(shù)組元素。這種操作稱為 元素指向(element-wise)。檢查是否所有的輸入/輸出陣列是連續(xù)的,即有沒有間斷在每行的結(jié)尾,是有意義的。如果是的話,將它們(這些數(shù)組)作為單獨的一個長行來處理:

/ / 計算正矩陣元素,優(yōu)化的變量的總和

double sum = 0;

int cols =M.cols,rows = M.rows ;

if(M.isContinuous())

{

??? cols * = rows ;

??? rows = 1 ;

}

for (int i = 0 ;i < rows; i + +)

{

const double * Mi = M.ptr <double>(i) ;

for (int j = 0; j < cols ; j ++)

???sum + = std::max (Mi [j],0.) ;

}

對于連續(xù)的矩陣來說,外部循環(huán)體只需一次執(zhí)行。所以,開銷是規(guī)模較小,

小型矩陣的情況下尤其明顯。

最后,還有足以成功跳過連續(xù)的行之間的間隔智能的STL 樣式迭代器:

/ / 計算正矩陣元素和基于迭代器類型的變量之和

double sum = 0;

Mat Const Iterator_ <double> it =M.begin <double> (),it_end = M.end <double> () ;

for(; it! = it_end ; ++it)

sum+ = std::max (*it,0.);

矩陣迭代器是隨機存取的迭代器,所以他們可以被傳遞給任何 STL 算法,包括 std::sort()。

矩陣表達式

這是已經(jīng)實現(xiàn)的可以組合在任意復(fù)雜的表達式中的矩陣運算操作, (此處 A 、B 的表示矩陣 (Mat)、 s表示標(biāo)量(Scalar),alpha為實數(shù)標(biāo)量 (雙精度型):

? 加法、減法、求反: A + B + A-B、 A + s、 A-s、 s + A、 s-A、-A;

? 縮放: A * alpha

? 每個元素乘法和除法: A.mul (B)、 A / B,alpha/A

? 矩陣相乘: A * B

? 大動脈轉(zhuǎn)位: A.t() (指在)

?矩陣反演和偽反演,求解線性系統(tǒng)和最小二乘問題:

A.inv([method]) (~ A-1) , A.inv([method])*B (~ X: AX=B)

? 比較: cmpop B、 cmpop alpha、 alpha cmpop A,其中 cmpop 是以下幾種運算符之一: >,> =,= =,! =,< =,<。比較的結(jié)果是其元素設(shè)置為 255的 8 位單通道掩碼(如果特殊元素對滿足條件) 或 0。

? 按位邏輯運算: logicop B、 logicop s slogicop A、 ~ A,其中 logicop 是以下運算符之一: &,|, ^.

? 元素的最小值和最大值:分 (A、 B)、 民 (,alpha),最大值 (A,B),最大 (,alpha)

? 元素的絕對價值: abs(A)

? 叉乘,點乘: A.cross(B) A.dot(B)

? 任何標(biāo)量與矩陣或矩陣的函數(shù),返回一個矩陣或標(biāo)量(scalar),如norm、, mean、 sum、countNonZero、trace、determinant、repeat和其他。

? 矩陣初始值設(shè)定項(Mat::eye(),Mat::zeros(),Mat::ones())、矩陣以逗號分隔的初始值設(shè)定項、可提取sub-matrices的m atrix構(gòu)造函數(shù)和運算符,(請參見Mat的說明)。

? Mat_ <destination_type> () 構(gòu)造函數(shù)將結(jié)果強制轉(zhuǎn)換為適當(dāng)?shù)念愋汀?/strong>

Note:有些逗號分隔初始值設(shè)定項和一些其他的運算符可能需要顯示調(diào)用Mat();或Mat_<T>();的構(gòu)造函數(shù)來解決可能產(chǎn)生的歧義。

???????? 以下是一些矩陣表達式的例子:

//計算矩陣A的偽反演等價于A.inv(DECOMP_SVD)

SVD svd(A);

Mat pinvA =svd.vt.t()*Mat::diag(1./svd.w)*svd.u.t();

//計算萊文伯格-馬夸特算法中的參數(shù)的新向量

x -= (A.t()*A +lambda*Mat::eye(A.cols,A.cols,A.type())).inv(DECOMP_CHOLESKY)*(A.t()*err);

//用“Unsharp Mask”算法銳化圖像

Mat blurred; double sigma = 1, threshold =5, amount = 1;

GaussianBlur(img, blurred, Size(), sigma,sigma);

Mat lowConstrastMask = abs(img - blurred)< threshold;

Mat sharpened = img*(1+amount) +blurred*(-amount);

img.copyTo(sharpened, lowContrastMask);

下面正式講解Mat的各種方法。

Mat:: Mat

各種Mat構(gòu)造函數(shù)。

C++: Mat::Mat()

C++: Mat::Mat(int rows, int cols, int type)

C++: Mat::Mat(Size size, int type)

C++: Mat::Mat(int rows, int cols, int type,const Scalar& s)

C++: Mat::Mat(Size size, int type, constScalar& s)

C++: Mat::Mat(const Mat& m)

C++: Mat::Mat(int rows, int cols, int type,void* data, size_t step=AUTO_STEP)

C++: Mat::Mat(Size size, int type, void*data, size_t step=AUTO_STEP)

C++: Mat::Mat(const Mat& m, constRange& rowRange, const Range& colRange)

C++: Mat::Mat(const Mat& m, constRect& roi)

C++: Mat::Mat(const CvMat* m, boolcopyData=false)

C++: Mat::Mat(const IplImage* img, boolcopyData=false)

C++: template<typename T, int n>explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)

C++: template<typename T, int m, intn> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)

C++: template<typename T> explicitMat::Mat(const vector<T>& vec, bool copyData=false)

C++: Mat::Mat(const MatExpr& expr)

C++: Mat::Mat(int ndims, const int* sizes,int type)

C++: Mat::Mat(int ndims, const int* sizes,int type, const Scalar& s)

C++: Mat::Mat(int ndims, const int* sizes,int type, void* data, const size_t* steps=0)

C++: Mat::Mat(const Mat& m, constRange* ranges)

?????????參數(shù)

ndims– 數(shù)組的維數(shù).

rows?– 2維數(shù)組中行行數(shù)

cols?– Number of columnsin a 2D array.

size?– 2維數(shù)組的尺寸Size(cols, rows) .在Size()構(gòu)造函數(shù)中行數(shù)和列數(shù)在次序上剛好反轉(zhuǎn)過來了。

sizes–指定 n 維數(shù)組形狀的整數(shù)數(shù)組。

type–數(shù)組的類型。使用 CV_8UC1,… …,創(chuàng)建 1-4 通道的矩陣,CV_64FC4 或CV_8UC(n),… …,CV_64FC(n)可以創(chuàng)建多通道 (高達 CV_MAX_CN 通道)矩陣。

s–一個可選的初始化每個矩陣元素的參數(shù)。要在矩陣建成后將所有元素設(shè)置為特定值可以用Mat的賦值運算符Mat:operator=(constScala& value)。

data–指向用戶數(shù)據(jù)的指針。矩陣構(gòu)造函數(shù)傳入data和step參數(shù)不分配矩陣數(shù)據(jù)。相反,它們只是初始化矩陣頭指向指定的數(shù)據(jù),這意味著沒有數(shù)據(jù)的復(fù)制。此操作是很高效的,可以用來處理使用 OpenCV 函數(shù)的外部數(shù)據(jù)。外部數(shù)據(jù)不會自動釋放,所以你應(yīng)該小心處理它。

step–每個矩陣行占用的字節(jié)數(shù)。如果任何值應(yīng)包括每行末尾的填充字節(jié)。如果缺少此參數(shù)(設(shè)置為 AUTO_STEP),假定沒有填充和實際的步長用cols*elemSize()計算。請參閱Mat::elemSize()。

steps–多維數(shù)組(最后一步始終設(shè)置為元素大小) 的情況下的 ndims-1個步長的數(shù)組。如果沒有指定的話,該矩陣假定為連續(xù)。

m–分配給構(gòu)造出來的矩陣的陣列(作為一個整體或部分)。這些構(gòu)造函數(shù)沒有復(fù)制數(shù)據(jù)。相反,指向 m 的數(shù)據(jù)或它的子數(shù)組的頭被構(gòu)造并被關(guān)聯(lián)到m上。引用計數(shù)器中無論如何都將遞增。所以,當(dāng)您修改矩陣的時候,自然而然就使用了這種構(gòu)造函數(shù),您還修改 m 中的對應(yīng)元素。如果你想要獨立的子數(shù)組的副本,請使用 Mat::clone()。

img?–指向老版本的 IplImage圖像結(jié)構(gòu)的指針。默認(rèn)情況下,原始圖像和新矩陣之間共享數(shù)據(jù)。但當(dāng) copyData 被設(shè)置時,完整的圖像數(shù)據(jù)副本就創(chuàng)建起來了。

vec–矩陣的元素構(gòu)成的STL 向量。矩陣可以取出單獨一列并且該列上的行數(shù)和矢量元素的數(shù)目相同。矩陣的類型匹配的向量元素的類型。構(gòu)造函數(shù)可以處理任意的有正確聲明的DataType類型。這意味著矢量元素不支持的混合型結(jié)構(gòu),它們必須是數(shù)據(jù)(numbers)原始數(shù)字或單型數(shù)值元組。對應(yīng)的構(gòu)造函數(shù)是顯式的。由于 STL 向量不會自動轉(zhuǎn)換為Mat實例,您應(yīng)顯式編寫 Mat(vec)。除非您將數(shù)據(jù)復(fù)制到矩陣 (copyData = true),沒有新的元素被添加到向量中,因為這樣可能會造成矢量數(shù)據(jù)重新分配,并且因此使得矩陣的數(shù)據(jù)指針無效。

copyData?–指定STL 向量或舊型 CvMat 或 IplImage是應(yīng)復(fù)制到 (true)新構(gòu)造的矩陣中 還是 (false) 與之共享基礎(chǔ)數(shù)據(jù)的標(biāo)志,復(fù)制數(shù)據(jù)時,使用Mat引用計數(shù)機制管理所分配的緩沖區(qū)。雖然數(shù)據(jù)共享的引用計數(shù)為 NULL,但是分配數(shù)據(jù)必須在矩陣被析構(gòu)之后才可以釋放。

rowRange?– m 的行數(shù)的取值范圍。正常情況下,范圍開始端具有包容性和范圍結(jié)束端是獨占的。使用 Range::all() 來取所有的行。

colRange?–m 列數(shù)的取值范圍。使用 Range::all() 來取所有的列。

ranges?–表示M沿每個維度選定的區(qū)域的數(shù)組。

expr?– 矩陣表達式。請參見矩陣表達式。

以上這些都是Mat生成一個矩陣的各類構(gòu)造函數(shù)。如?輸出數(shù)據(jù)的自動分配 一節(jié)(該節(jié)內(nèi)容在第一章 Introduction)中所提到的,往往默認(rèn)構(gòu)造函數(shù)就足夠了,不同的矩陣可以由 OpenCV 函數(shù)來分配數(shù)據(jù)空間。構(gòu)造的矩陣可以進一步分配給另一個矩陣或矩陣表達或通過Mat::create()獲配。在前一種情況,舊的內(nèi)容是間接引用的。

總結(jié)

以上是生活随笔為你收集整理的OpenCV参考手册之Mat类详解1的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。