OpenCV 對Mat矩陣加、減、乘、除、轉置等操作的總結


1、矩陣加

1) 使用重載的 “+” 運算符

矩陣的加法是指兩個矩陣對於位置的數值相加,使用OpenCv重載的 “+” 運算符,假設兩個矩陣都為uchar類型,例如:

1 Mat src1 = (Mat_<uchar>(2,3) << 23, 123, 90, 100, 250, 0); 2 Mat src2 = (Mat_<uchar>(2,3) << 125, 150, 60, 100, 10, 40); 3 Mat dst = src1 + src2;

123+150應該等於273, 因為兩個矩陣的類型都是uchar, 所以"+“運算計算出來的和也是uchar類型, 但是uchar類型范圍的最大值是255, 所以273限制為了255。

利用”+“運算符計算計算Mat的和需注意:兩個Mat的數據類型必須是一樣的, 否則會報錯。

一個數值與一個Mat對象相加, 也可以使用”+"運算符, 但是無論這個數值是什么數據類型, 返回的Mat的數據類型都與輸入的Mat相同,且結果是矩陣中的每個元素都與這個數值相加:
例如:

1 float value = 100.0; 2 Mat dst1 = src1 + value;
2) 使用add函數
1 void add 2 ( 3  InputArray src1, 4  InputArray src2, 5  OutputArray dst, 6     InputArray mask = noArray(), 7     int dtype = -1
8 );

例如:

1 Mat src1 = (Mat_<uchar>(2,3) << 23, 123, 90, 100, 250, 0); 2 Mat src2 = (Mat_<uchar>(2,3) << 125, 150, 60, 100, 10, 40); 3 Mat dst; 4 add(src1, src2, dst, Mat(), CV_64FC1);

使用add函數時, 輸入矩陣的數據類型可以不同, 二輸出矩陣的數據類型可以根據情況自行指定, 只有當src1和src2的數據類型相同時, 才能令dtype = -1, 否則仍然會報錯。

3) 兩個向量之間也可以做加法運算
1 Vec3f v1 = Vec3f(1, 2, 3); 2 Vec3f v2 = Vec3f(10, 1, 12); 3 Vec3f v = v1 + v2;
4)線性相加scaleAdd
1 C++: void scaleAdd 2 ( 3     InputArray src1,     // 第一個輸入矩陣
4     double alpha,        // 第一個輸入矩陣的比例因子
5     InputArray src2,     // 與src1大小和類型相同的第二個輸入矩陣。
6  OutputArray dst 7 )

它計算一個縮放數組和另一個數組的和:
dst(I) = alpha * src(I) + src2(I)
例如:

scaleAdd(imageA,k,imageB,resultC);

該函數也可以用矩陣表達式模擬,例如:

1 Mat A(3, 3, CV_64F); 2 ... 3 A.row(0) = A.row(1)*2 + A.row(2);
5)兩個數組的加權和addWeighted
 1 C++: void addWeighted  2 (  3     InputArray src1,      // 第一個圖像矩陣
 4     double alpha,         // 第一個數組元素的權重。
 5     InputArray src2,      // 與src1大小和通道相同的第二個輸入圖像矩陣。
 6     double beta,          // 第二個數組元素的權值。
 7     double gamma,         // 與輸入數組具有相同大小和通道數的輸出數組。
 8     OutputArray dst,      // 每個和加上一個標量。
 9     int dtype=-1          // 可選輸出陣列深度;當兩個輸入數組具有相同的 10                           // 深度時,可以將dtype設置為-1,這將等效於src1.depth()。
11 )

該函數可替換為矩陣表達式:
dst = src1 * alpha + src2 * beta + gamma;
例如:

1     Mat img1=imread("./a1.jpg"); 2     Mat img2=imread("./a2.jpg"); 3  Mat dst; 4     addWeighted(img1,0.5,img2,0.3,0,dst);

2、矩陣減

1)使用重載“-”運算符

我們可以使用和**"-"**符號進行 矩陣減運算。
例如:

1 Mat a= Mat::eye(Size(3,2), CV_32F); 2 Mat b= Mat::ones(Size(3,2), CV_32F); 3 Mat d= a-b;
CSDN圖標

注:如果圖像是uchar類型的,144-240不會是 - 96,而是uchar能表示的最小值0

2)減法函數subtract

計算兩個數組或數組與標量之間的每個元素的差。

1 C++: void subtract 2 ( 3     InputArray src1,           // 第一個輸入數組或標量。
4     InputArray src2,           // 第二個輸入數組或標量。
5     OutputArray dst,           // 與輸入陣列相同大小、相同通道數的輸出陣列。
6     InputArray mask=noArray(), // 可選操作面具;這是一個8位的單通道數組, 7                                // 指定要更改的輸出數組的元素。
8     int dtype=-1               // 輸出數組的可選深度
9 )

例如:

1 imshow("img1",img1); 2 imshow("img2",img2); 3 subtract(img1,img2,dst); // saturate(img1 - img2) 4 //注意:要求被處理圖片尺寸一致

注:圖像元素類型是uchar,如果相減小於0,結果值會變成0,如果大於255,變成255。

3) 元素的絕對差absdiff
計算兩個數組或數組與標量之間的每個元素的絕對差。

1 C++: void absdiff 2 ( 3     InputArray src1,    // 第一個輸入數組或標量。
4     InputArray src2,    // 第二個輸入數組或標量。
5     OutputArray dst     // 與輸入數組具有相同大小和類型的輸出數組。
6 )

 dst = saturate(|src1 - src2|)
例如:

1 imshow("img1",src1); 2 imshow("img1",src2); 3 Mat dst; 4 absdiff(src1, src2, dst);//若dst<0,則dst=|dst|>=0

3、矩陣乘

1) 矩陣乘A*B

是以數學運算中矩陣相乘的方式實現的,即Mat矩陣A和B被當做純粹的矩陣做乘法運算,這就要求A的列數等於B的行數時,才能定義兩個矩陣相乘。如A是m×n矩陣,B是n×p矩陣,它們的乘積AB是一個m×p矩陣。

例如:

1 Mat A=Mat::ones(2,3,CV_32FC1); 2 Mat B=Mat::ones(3,2,CV_32FC1); 3 ... 4 AB=A*B;

2) 點乘A.dot(B)(與MATLAB的概念有點區別)
參與點乘的兩個Mat矩陣的數據類型(type)只能是 CV_32F、 CV_64FC1、 CV_32FC2、 CV_64FC2 這4種類型中的一種。若選用其他類型,比如CV_8UC1,編譯器會報錯。

說明: 對於向量a和向量b:

在這里插入圖片描述
在這里插入圖片描述
a和b的點積公式為:

A.dot(B)操作相當於數學向量運算中的點乘,也叫向量的內積、數量積。 對兩個向量執行點乘運算,就是對這兩個向量對應位一一相乘之后求和的操作,點乘的結果是一個標量。 Mat矩陣的dot方法擴展了一維向量的點乘操作,把整個Mat矩陣擴展成一個行(列)向量,之后執行向量的點乘運算,仍然要求參與dot運算的兩個Mat矩陣的行列數完全一致。

dot方法聲明中顯示返回值是double,所以A.dot(B)結果是一個double類型數據,不是Mat矩陣,不能把A.dot(B)結果賦值給Mat矩陣!

例如:

1 Mat A=Mat::ones(2,3,CV_8UC1); 2 Mat B=Mat::ones(2,3,CV_8UC1); 3 double AB; 4 ... 5 AB = A.dot(B);

dot操作不對參與運算的矩陣A、B的數據類型做要求,CV_8UC1、CV_32FC1等,可以是任何Opencv定義的類型,如在2中使用的就是CV_8UC1。

若參與dot運算的兩個Mat矩陣是多通道的,則計算結果是所有通道單獨計算各自.dot之后,再累計的和,結果仍是一個double類型數據。

3) 計算兩個Mat矩陣對應位的乘積A.mul(B)
要求參與運算的矩陣A的行列和B的行列數一致。計算結果是跟A或B行列數一致的一個Mat矩陣。
mul說明:

1、mul操作不對參與運算的兩個矩陣A、B有數據類型上的要求,但要求A,B類型一致,不然報錯;
2、Mat AB=A.mul(B),若聲明AB時沒有定義AB的數據類型,則默認AB的數據類型跟A和B保存一致;
3、若AB精度不夠,可能產生溢出,溢出的值被置為當前精度下的最大值;

例如:

1 Mat A=Mat::ones(2,3,CV_8UC1); 2 Mat B=Mat::ones(2,3,CV_8UC1); 3 ... 4 Mat AB=A.mul(B);
4) 矩陣與標量相乘

使用“*”示矩陣與標量相乘;
例如:

1 Mat m1 = Mat::eye(2,3,CV_32FC1); 2 ... 3 Mat m2 = m1*2;

4、矩陣除

1)使用重載的 “/” 運算符

A/B; alpha/A; A/alpha都是點除
例如:

1 Mat src1 = (Mat_<int>(2, 3) << 4, 7, 1, 5, 20, 24);  //2行3列的矩陣
2 Mat src2 = (Mat_<int>(2, 3) << 2, 7, 5, 5, 4, 48);  //2行3列的矩陣
3 Mat dst1, dst2, dst3; 4 dst1 = src1 / 4; 5 dst2 = 20 / src1; 6 dst3 = src1 / src2; 7 cout << "A/alpha:\n" << dst1 << endl << endl; 8 cout << "alpha/A:\n" << dst2 << endl << endl; 9 cout << "A/B:\n" << dst3 << endl;

輸出結果:

CSDN圖標

2)矩陣除函數 divide

對一個數組執行兩個數組或一個標量的每個元素的除法。

1 C++: void divide 2 ( 3     InputArray src1,     // 第一個輸入矩陣
4     InputArray src2,     // 與src1大小和類型相同的第二個輸入矩陣。
5     OutputArray dst,     // 與src2大小和類型相同的輸出矩陣。
6     double scale=1,      // 標量的因子
7     int dtype=-1         
8 )

函數將一個數組除以另一個數組:
         dst = saturate(src1*scale/src2)
如果沒有src1時:
         dst = saturate(scale/src2);
例如:

1 Mat img0 = cv::imread("img_0.jpg", -1); 2 Mat img1 = cv::imread("img_1.jpg", -1); 3 Mat img2; 4 divide(img0, img1, img2, 50, -1);

5、矩陣的轉置

由Mat類t()函數實現矩陣的轉置
例如:

1 Mat m1 = Mat::eye(4,6,CV_32FC1); 2 ... 3 Mat m1t = m1.t();

6、矩陣的逆

其中inv(A)表示矩陣A的逆矩陣
例如:

1 Mat m1 = Mat::eye(5,5,CV_32FC1); 2 ... 3 Mat m1inv = m1.inv();

7、矩陣中非零元素個數

使用 countNonZero() 函數實現物體的像素或面積常需要用到計算矩陣中的非零元素個數
例如:

1 Mat m1 = Mat::eye(6,6,CV_32FC1); 2 ... 3 int m1num = countNonZero(m1);

8、矩陣中均值和標准差

OpenCV提供了矩陣均值和標准差計算功能,使用 meanStdDev(src,mean,stddev) 函數實現
例如:

 1 Mat m1 = Mat::eye(5,5,CV_32FC1);  2 Mat mean,stddev;  3 ...  4 meanStdDev(m1,mean,stddev);  5 .  6 .  7 .  8 Mat m3(Size(5,5),CV_8UC3,Scalar(255,200,100));  9 Mat mean3,stddev3; 10 ... 11 meanStdDev(m3,mean3,stddev3);

注:當src為多通道或多維矩陣時,則函數分別計算不同通道的均值與標准差,因此返回的mean和stddev為對應維度的向量;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM