目標
我們有多種方法可以獲得從現實世界的數字圖像:數碼相機、掃描儀、計算機體層攝影或磁共振成像就是其中的幾種。在每種情況下我們(人類)看到了什么是圖像。但是,轉換圖像到我們的數字設備時我們的記錄是圖像的每個點的數值。
例如在上圖中你可以看到車的鏡子只是一個包含所有強度值的像素點矩陣。現在,我們如何獲取和存儲像素值可能根據最適合我們的需要而變化,最終可能減少計算機世界內的所有圖像數值矩陣和一些其他的信息的描述基質本身。OpenCV 是一個計算機視覺庫,其主要的工作是處理和操作,進一步了解這些信息。因此,你需要學習和開始熟悉它的第一件事是理解OpenCV 是如何存儲和處理圖像。
Mat
OpenCV 自 2001 年出現以來。在那些日子里庫是圍繞C接口構建的。在那些日子里,他們使用名為IplImage C 的結構在內存中存儲圖像。這是您將在大多數較舊的教程和教材中看到的那個。使用這個結構的問題是將 C 語言的所有負面效果都擺到了桌面上。最大的問題是手動管理。它是建立在用戶來負責處理內存分配和解除分配的假設之上的。當程序規模較小時,這是沒有問題的,一旦代碼基開始變得越來越大它將會越來越掙扎着處理所有這一切而不是着眼於實際解決自己的開發目標。
幸運的是 c + + 出現了,並引入了類的概念,使得為用戶開辟另一條路成為可能:
自動內存管理 (或多或少)。好消息是,c + +,如果完全兼容 C 所以進行更改時沒有兼容性問題產生。因此, OpenCV其2.0 版本引入一個新的c + + 接口,通過利用這些優點將為你的工作提供新的方法。某種程度上,在其中您不需要撥弄內存管理讓你的代碼簡潔 (寫得更少,實現的更多)。C + + 接口的唯一主要缺點在於,目前許多嵌入式的開發系統支持僅 C.因此,除非您的目標是這一平台,否則就沒有理由再使用舊的方法(除非你是個受虐狂程序員和喜歡自討苦吃)。
你需要知道的關於Mat的第一件事是你不再需要手動分配其大小並且當你不需要它的時候你不再需要手動釋放它。雖然這樣做仍然是可能的,大多數 OpenCV 函數將手動分配其輸出數據。還有一個額外的好處是如果傳遞一個已存在Mat對象,它已經為矩陣分配所需的空間,這段空間將被重用。也就是說我們在任何時候只使用與我們執行任務時所必須多的內存一樣多的內存。
Mat本質上是由兩個數據部分組成的類: (包含信息有矩陣的大小,用於存儲的方法,矩陣存儲的地址等) 的矩陣頭和一個指針,指向包含了像素值的矩陣(可根據選擇用於存儲的方法采用任何維度存儲數據)。矩陣頭部的大小是恆定的。然而,矩陣本身的大小因圖像的不同而不同,通常是較大的數量級。因此,當你在您的程序中傳遞圖像並在有些時候創建圖像副本您需要花費很大的代價生成圖像矩陣本身,而不是圖像的頭部。OpenCV 是圖像處理庫,它包含大量的圖像處理函數。若要解決的計算挑戰,最終大部分時間你會使用庫中的多個函數。由於這一原因圖像傳給庫中的函數是一種常見的做法。我們不應忘記我們正在談論往往是計算量相當大的圖像處理算法。我們想要做的最后一件事是通過制作不必要的可能很大的圖像的拷貝進一步降低您的程序的速度。
為了解決這一問題 OpenCV 使用引用計數系統。其思想是Mat的每個對象具有其自己的頭,但可能他們通過讓他們矩陣指針指向同一地址的兩個實例之間共享該矩陣。此外,拷貝運算符將只能復制矩陣頭部,也還將復制指向矩陣的指針,但不復制矩陣本身。
- Mat A, C; //僅創建了頭部
- A = imread(argv[1], CV_LOAD_IMAGE_COLOR); //在此我們知道使用的方法(分配矩陣)
- Mat B(A); //使用拷貝構造函數
- C = 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);
現在 modifyingForGwill 不會影響由 theMatheader 指出的矩陣。你要記得從所有的是:
1、輸出圖像分配 OpenCV 功能是自動 (除非另行指定,否則)。
2、用c + + OpenCV的接口就無需考慮內存釋放。
3、賦值運算符和復制構造函數 (構造函數)只復制頭。
4、使用clone () 或copyTo () 函數將復制的圖像的基礎矩陣。
存儲方法
這是關於你是如何存儲的像素值。您可以選擇的顏色空間和使用的數據類型。色彩空間是指我們如何結合為了代碼指定的顏色的顏色分量。最簡單的是灰色的規模。在這里我們所掌握的顏色是黑色和白色。組合的這些讓我們能創造很多的灰度級。
對於彩色的方法,我們有很多方法可供選擇。不過,每一就是將他們拆解成三個或四個基本組成部分,這些部分就會組合給所有其他的方法。最受歡迎的這一個 RGB,主要是因為這也是我們的眼睛如何建立中我們的眼睛的顏色。其基准的顏色是紅、 綠、 藍。編寫代碼的一種顏色的透明度有時第四個元素: 添加 alpha (A)。但是,它們很多顏色系統每個具有自身的優勢:
1、RGB 是最常見的是我們的眼睛使用類似的事情,我們顯示系統還撰寫使用這些顏色。
· 單純皰疹和合肥分解顏色到他們的色相、 飽和度和亮度值/組件,這是我們來描述顏色更自然的方式。您使用,例如可駁回的最后一個組件,使你不那么明智的輸入圖像的光照條件的算法。
2、 YCrCb 使用流行的 JPEG 圖像格式。
3、 CIE L *b*a 是均勻顏色空間,它是非常方便的如果您需要測量給定的顏色,以另一種顏色的距離。
現在,每個建築構件都自己有效的域。這會導致使用的數據類型。我們如何存儲組件的定義只是如何精細的控制,我們已於其域。最小的數據類型可能是 char 類型,這意味着一個字節或 8 位。這可能是有符號(值-127 到 + 127)或無符號(以便可以存儲從 0 到 255 之間的值)。雖然這三個組件的情況下已經給 16 萬可能的顏色來表示 (如 RGB 的情況下) 我們可能通過使用浮點數 (4 字節 = 32 位) 或double(8 字節 = 64 位) 數據類型的每個組件獲得甚至更精細的控制。然而,請記住增加組件的大小也會增加在內存中的整張圖片的大小。
顯式創建Mat對象
在Load, Modify and Save an Image 教程中,你已經可以看到如何使用readWriteImageVideo: 'imwrite() <imwrite>' 函數將一個矩陣寫到一個圖像文件中。然而,出於調試目的顯示的實際值就方便得多。您可以實現此通過Mat的 <<運算符。不過,請注意這僅適用於二維矩陣。
雖然Mat是一個偉大的圖像容器類,它也是一般矩陣類。因此,利用Mat創建和操作多維矩陣是可能的。您可以通過多種方式創建Mat的對象:
1、 Mat()構造函數
Mat M(2,2, CV_8UC3, Scalar(0,0,255));
cout << "M = " << endl << " " << M << endl << endl;
對於二維的和多通道的圖像,我們首先定義它們的大小:按行和列計數。
然后我們需要指定的數據類型,用於存儲元素和每個矩陣點通道的數量。為此,我們根據以下的約定可以作出多個定義:
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、為一個已經存在的IplImage創建一個頭:
IplImage* img = cvLoadImage("greatwave.png", 1);
Mat mtx(img); // 轉換 IplImage*-> Mat
3、 Create()函數:
M.create(4,4, CV_8UC(2));
cout << "M = "<< endl << " " << M << endl << endl;
你不能通過這個構造來初始化矩陣中的數值。它只會在新的矩陣尺寸與舊的矩陣尺寸不合時重新分配矩陣的數據空間。
MATLAB風格的初始化函數:zeros(), ones(),
:eyes().指定使用的尺寸和數據類型
Mat E = Mat::eye(4, 4, CV_64F);
cout << "E = " << endl << " " << E << endl << endl;
Mat O = Mat::ones(2, 2, CV_32F);
cout << "O = " << endl << " " << O << endl << endl;
Mat Z = Mat::zeros(3,3, CV_8UC1);
cout << "Z = " << endl << " " << Z << endl << endl;
對於小的矩陣來說你可以使用逗號隔開的初始化函數:
Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << " " << C << endl << endl;
為一個已有的Mat對象創建一個新的頭然后clone()或者copyTo()這個頭.
Mat RowClone = C.row(1).clone();
cout << "RowClone = " << endl << " " << RowClone << endl << endl;
打印格式
注意:你可以通過用randu()函數產生的隨機值來填充矩陣。你需要給定一個上限和下限來確保隨機值在你期望的范圍內:
Mat R = Mat(3, 2, CV_8UC3);
cv::randu(R, Scalar::all(0), Scalar::all(255));
randu(cv::Mat &dat ,const cv::Scalar &low,const cv::Scalar &high);
在上一個例子中你可以看到默認的格式選項。盡管如此,OpenCV允許你在符合以下規則的同時格式化你的輸出:
默認
cout << "R (default) = " << endl << R << endl << endl;
Python
cout << "R (python) = " << endl << format(R,"python") << endl << endl;
Comma separated values (CSV)
cout << "R (csv) = " << endl << format(R,"csv" ) << endl << endl;
Numpy
cout << "R (numpy) = " << endl << format(R,"numpy" ) << endl << endl;
C
cout << "R (c) = " << endl << format(R,"C" ) << endl << endl;
打印出其它常見數據項
OpenCV 通過<<操作符也為其他常用OpenCV數據結構提供打印輸出的支持,如:
2D 點
Point2f P(5, 1);
cout << "Point (2D) = " << P << endl << endl;
3D 點
Point3f P3f(2, 6, 7);
cout << "Point (3D) = " << P3f << endl << endl;
std::vector通過 cv::Mat
vector<float> v;
v.push_back( (float)CV_PI); v.push_back(2); v.push_back(3.01f);
cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;
點的std::vector
vector<Point2f> vPoints(20);
for (size_t E = 0; E < vPoints.size(); ++E)
vPoints[E] = Point2f((float)(E*5), (float)(E % 7));
cout << "A vector of 2D Points = " << vPoints << endl << endl;
這里大多數的例程都是在一個小控制台程序里運行。你可以在這里下載或是在cpp示例文件夾下找到。
Mat::~Mat
Mat的析構函數。
C++: Mat::~Mat()
析構函數調用Mat::release()。
Mat::operator =
提供矩陣賦值操作。
C++: Mat& Mat::operator=(const Mat& m)
C++: Mat& Mat::operator=(const MatExpr_Base& expr)
C++: Mat& Mat::operator=(const Scalar& s)
參數:
m – 被賦值的右側的矩陣。 矩陣的賦值是一個復雜度為O(1) 的操作。 這就意味着沒有復制數據段,並且兩矩陣將使用同一引用計數器。在給矩陣賦新數據之前先由Mat::release()釋放引用。
expr –被賦值的矩陣表達式對象。 作為第一種賦值方式的逆操作第二種形式可以被重新用到具有適當大小和尺寸的已分配空間的矩陣上以適應表達式的結果。矩陣表達式擴展得到的實函數將自動處理這個分配過程。例如:
C=A+B 擴展成add(A, B, C) , andadd() 要當心C重新分配數據的操作。.
s – 標量賦值給每一個矩陣元,矩陣的大小和類型將不會改變。有現成的賦值運算符。由於他們各不相同請閱讀運算符參數說明。
Mat::operator MatExpr
提供一種Mat-to-MatExpr轉換運算符
C++: Mat::operator MatExpr_<Mat, Mat>() const
轉換運算符不能顯示調用而是由矩陣表達式引擎(Matrix Expression engine)內部調用The cast operator should not be called explicitly. It is used internally by the Matrix Expressions engine.
Mat::row
創建一個指定行數的矩陣頭。.
C++: Mat Mat::row(int i) const
參數:
i – 一個0基的行索引.
該方法創建一個具有指定了行數的新矩陣頭的矩陣並返回它。這是一個復雜度為O(1) 的操作,無須考慮矩陣的尺寸。新矩陣和原矩陣共享一份基礎數據。這是一個典型基本矩陣處理操作的例子, axpy是LU和許多其它算法都使用的一個函數
inline void matrix_axpy(Mat& A, int i, int j, double alpha)
{
A.row(i) += A.row(j)*alpha;
}
Note:在當前實現中,下面的代碼不會無法按預期的效果工作:
Mat A ;
...
A.row(i) = A.row(j) ;/ /不起作用
發生這種情況是因為 A.row(i) 形成臨時矩陣頭進一步分配給另一個矩陣頭。請記住,每個操作復雜度為O(1),即沒有復制任何數據。因此,如果你預期第 j行被復制到第 i行,那么上述賦值不成立。要做到這一點,應該把這種簡單的賦值轉換到表達式中或使用 Mat::copyTo() 方法:
Mat A ;
...
/ / 可行,但看上去有點目的不明確。
A.row(i) = A.row(j) + 0;
/ / 這是有點兒長,但這是推薦的方法。
A.row(j).copyTo(A.row(i)) ;
Mat::col
創建一個具有指定了矩陣頭中列數這個參數的矩陣
C++: Mat Mat::col(int j) const
參數:
j –一個0基(從0開始)的列索引
該方法創建一個具有指定了矩陣頭中列數這個參數的新矩陣並作為函數返回值。這是一種復雜度為O(1)的操作,不用考慮矩陣的尺寸大小。新矩陣和原始矩陣共享一份基礎數據。參看Mat::row()說明信息。
Mat::rowRange
為指定的行span創建一個新的矩陣頭。
C++: Mat Mat::rowRange(int startrow, int endrow) const
C++: Mat Mat::rowRange(const Range& r) const
參數:
startrow – 一個包容性的0基(從0開始)的行span起始索引.。
endrow – 一個0基的獨占性的行span.終止索引。
r – Range 結構包含着起始和終止的索引值。該方法給矩陣指定的行span創建了新的頭。 與Mat::row() 和 Mat::col()相類似這是一個復雜度為O(1)的操作。
Mat::colRange
為指定的行span創建一個矩陣頭。
C++: Mat Mat::colRange(int startcol, int endcol) const
C++: Mat Mat::colRange(const Range& r) const
參數:
startcol – 一個包容性的0基(從0開始)的span列起始索引。
endcol –一個0基的獨占性的列span.終止索引。
r –Range 結構包含着起始和終止的索引值。該方法給矩陣指定的列span創建了新的頭。 與Mat::row() 和 Mat::col()相類似這是一個復雜度為O(1)的操作。
Mat::diag
提取或創建矩陣對角線。
C++: Mat Mat::diag(int d) const
C++: static Mat Mat::diag(const Mat& matD)
參數:
d – 對角線的索引值,可以是以下的值:
– d=0 是主對角線
– d>0表示下半部的對角線。例如:d=1對角線是緊挨着住對角線並位於矩陣下方。
– d<0表示來自矩陣上半部的對角線。例如:d= 1表示對角線被設置在對角線的上方並緊挨着。
matD – 單列用於形成矩陣對角線的列。
該方法為指定的矩陣創建一個新的頭。然后新矩陣被分割為單獨的列矩陣。類似於Mat::row() 和Mat::col() ,它是復雜度為O(1)操作。
Mat::clone
創建一個數組及其基礎數據的完整副本。
C++: Mat Mat::clone() const
該方法創建了一個完整的數組副本。原始的step[]不會被考慮在內的。因此數組的副本是一占用total()*elemSize()字節的連續陣列。
Mat::copyTo
把矩陣復制到另一個矩陣中。
C++: void Mat::copyTo(OutputArray m) const
C++: void Mat::copyTo(OutputArray m, InputArray mask) const
參數:
m – 目標矩陣。如果它的尺寸和類型不正確,在操作之前會重新分配。
mask – 操作掩碼。它的非零元素表示矩陣中某個要被復制。
該方法把矩陣的復制到另一個新的矩陣中在復制之前該方法會調用
m.create(this->size(), this->type);
因此,目標矩陣會在必要的情況下重新分配
盡管m.copyTo(m) works ?awlessly,該函數並不處理源矩陣和目標矩陣之間有重疊的部分的情況。當操作掩碼指定以及上述的Mat::create重新分配矩陣,新分配的矩陣在數據復制到里面之前全都被初始化為0。
Mat::convertTo
在縮放或不縮放的情況下轉換為另一種數據類型。
C++:
void Mat::convertTo(OutputArray m,int rtype,double alpha=1,double beta=0)const
參數:
m – 目標矩陣。如果它的尺寸和類型不正確,在操作之前會重新分配。
rtype – 要求是目標矩陣的類型,或者在當前通道數與源矩陣通道數相同的情況下的depth。如果rtype 為負,目標矩陣與源矩陣類型相同。
beta – 可選的delta加到縮放值中去。
該方法將源像素值轉化為目標類型saturate_cast<> 要放在最后以避免溢出
m( x;y) = saturate_cast < rType > ( α*( *this)( x;y) +β)
Mat::assignTo
提供了一個convertTo的功能形式。
C++: void Mat::assignTo(Mat& m, int type=-1 ) const
Parameters
m – 目標陣列。
type – 要求是目標陣列depth或-1(如果陣列的類型和源矩陣類型相同)
這是一個 internally 使用的由 Matrix Expressions引擎調用的方法。
Mat::setTo
將陣列中所有的或部分的元素設置為指定的值。
C++: Mat& Mat::setTo(const Scalar& s, InputArray mask=noArray())
參數:
s – 把標量賦給陣列並轉化到陣列的實際類型。
mask – 與 *this尺寸相同的操作掩碼。這是Mat::operator=(const Scalar& s)運算符的一個高級變量。
Mat::reshape
在無需復制數據的前提下改變2D矩陣的形狀和通道數或其中之一。
C++: Mat Mat::reshape(int cn, int rows=0) const
參數:
cn – 新的通道數。若cn=0,那么通道數就保持不變。
rows –新的行數。 若rows = 0, 那么行數保持不變。
該方法為*this元素創建新的矩陣頭。這新的矩陣頭尺寸和通道數或其中之一發生改變,在以下的情況任意組合都是有可能的:
ü 新的矩陣沒有新增或減少元素。通常,rows*cols*channels()在轉換過程中保持一致。.
ü 無數據的復制。也就是說,這是一個復雜度為 O(1)的操作。通常,如果該操作改變行數或透過其他方式改變元素行索引,那么矩陣必定是連續的。參見Mat::isContinuous()。
例如,有一存儲了STL向量的三維點集,你想用3xN的矩陣來完成下面的操作:
std::vector<Point3f> vec;
...
Mat pointMat = Mat(vec). //把向量轉化成Mat, 復雜度為O(1)的運算
reshape(1). // 從Nx1的3通道矩陣得出Nx3 的單通道矩陣
//同樣是復雜度為O(1)的運算
t(); // 最后轉置Nx3 的矩陣
//這個過程要復制所有的元素
Mat::t
轉置矩陣。.
C++: MatExpr Mat::t() const
該方法通過矩陣表達式(matrix expression)實現矩陣的轉置The method performs matrix transposition by means of matrix expressions. 它並未真正完成了轉置但卻返回一個臨時的可以進一步用在更復雜的矩陣表達式中或賦給一個矩陣的轉置矩陣對象:
Mat A1 = A + Mat::eye(A.size(), A.type)*lambda;
Mat C = A1.t()*A1; //計算(A + lambda*I)^t * (A + lamda*I).
Mat::inv
反轉矩陣
C++: MatExpr Mat::inv(int method=DECOMP_LU) const
參數:
method – 反轉矩陣的方法。有以下幾種可能的值:
– DECOMP_LU是 LU 分解一定不能是單數的。
– DECOMP_CHOLESKY 是 Cholesky LLT只適用於對稱正矩陣的分解。該類型在處理大的矩陣時的速度是LU的兩倍左右。
– DECOMP_SVD是 SVD 分解。如果矩陣是單數或甚至不是2維,函數就會計算偽反轉矩陣。
該方法執行矩陣的反轉矩陣表達。這意味着該方法返回一個臨時矩陣反轉對象並可進一步用於更復雜的矩陣表達式的中或分配給一個矩陣。
Mat::mul
執行兩個矩陣按元素相乘或這兩個矩陣的除法。
C++: MatExpr Mat::mul(InputArray m, double scale=1) const
參數:
m – 與*this具有相同類型和大小的矩陣,或矩陣表達式。
scale – 可選縮放系數。
該方法返回一個用可選的縮放比率編碼了每個元素的數組乘法的臨時的對象。 注意:這不是一個對應“*”運算符的簡單的矩陣乘法。.
例::
Mat C = A.mul(5/B); // 等價於divide(A, B, C, 5)
Mat::cross
計算3元素向量的一個叉乘積。
C++: Mat Mat::cross(InputArray m) const
參數:
m –另一個叉乘操作對象。
該方法計算了兩個3元素向量的叉乘的積被操作向量必須是3元素浮點型的具有相同形狀和尺寸的向量。結果也是一語被操作對象的具有相同形狀和大小的浮點型3元素向量。
Mat::dot
計算兩向量的點乘。
C++: double Mat::dot(InputArray m) const
參數:
m –另一個點積操作對象。
方法計算兩個矩陣的點積。如果矩陣不單列或單行的向量,用頂部到底部從左到右掃描次序將它們視為 1 D向量。這些向量必須具有相同的大小和類型。如果矩陣有多個通道,從所有通道得到的點積會被加在一起。
Mat::zeros
返回指定的大小和類型的零數組。
C++: static MatExpr Mat::zeros(int rows, int cols, int type)
C++: static MatExpr Mat::zeros(Size size, int type)
C++: static MatExpr Mat::zeros(int ndims, const int* sizes, int type)
參數
ndims – 數組的維數。
rows–行數。
cols –列數。
size–替代矩陣大小規格Size(cols, rows)的方法。
sizes– 指定數組的形狀的整數數組。
type– 創建的矩陣的類型。
該方法返回一個 Matlab 式的零數組初始值設定項。它可以用於快速形成一個常數數組作為函數參數,作為矩陣的表達式或矩陣初始值設定項的一部分。
Mat A;
A = Mat::zeros (3,3,CV_32F);
在上面的示例中,只要A不是 3 x 3浮點矩陣它就會被分配新的矩陣。否則為現有的
矩陣 A填充零。
Mat::ones
返回一個指定的大小和類型的全為1的數組。
C++: static MatExpr Mat::ones(int rows, int cols, int type)
C++: static MatExpr Mat::ones(Size size, int type)
C++: static MatExpr Mat::ones(int ndims, const int* sizes, int type)
參數:
ndims –數組的維數。
rows –行數。.
cols –列數。
size –替代矩陣大小規格Size(cols, rows)的方法。
sizes –指定數組的形狀的整數數組。
type –創建的矩陣的類型。
該方法返回一個 Matlab 樣式 1 的數組初始值設定項,類似Mat::zeros()。請注意,這種方法中你可以使用任意一個值和Matlab 語法初始化數組如下:
Mat A = Mat::ones (100,100,CV_8U) * 3 ;/ / 使100 x 100 矩陣里充滿 3。
上述操作不會形成一個 100 x 100 1 的矩陣,然后乘以 3。相反,它只是記住
縮放因子(在本例中 3)在實際調用矩陣初始值設定項時使用它。