opencv常用矩陣操作(加、減、乘、逆、均值、標准差)


OpenCV中的矩陣操作非常重要,本文總結了矩陣的創建、初始化以及基本矩陣操作主要內容包括:

  • 創建與初始化
  • 矩陣加減法
  • 矩陣乘法
  • 矩陣轉置
  • 矩陣求逆
  • 矩陣非零元素個數
  • 矩陣均值與標准差
  • 矩陣全局極值及位置
  • 其他矩陣運算函數列表

1. 創建與初始化矩陣

1.1 數據類型

建立矩陣必須要指定矩陣存儲的數據類型,圖像處理中常用的幾種數據類型如下:

CV_8UC1// 8位無符號單通道
CV_8UC3// 8位無符號3通道
CV_8UC4
CV_32FC1// 32位浮點型單通道
CV_32FC3// 32位浮點型3通道
CV_32FC4

包括數據位深度8位、32位,數據類型U:uchar、F:float型以及通道數C1:單通道、C3:三通道、C4:四通道。

1.2 基本方法

我們可以通過載入圖像來創建Mat類型矩陣,當然也可以直接手動創建矩陣,基本方法是指定矩陣尺寸和數據類型:

1 // 基本方法
2     cv::Mat a(cv::Size(5,5),CV_8UC1); // 單通道
3     cv::Mat b = cv::Mat(cv::Size(5,5),CV_8UC3); //3通道每個矩陣元素包含3個uchar值
4     cout<<"a  = "<<endl<<a<<endl<<endl;
5     cout<<"b  = "<<endl<<b<<endl<<endl;
6     system("pause");

運行結果:

3通道矩陣中,一個矩陣元素包含3個變量。

1.3 初始化方法

上述方法不初始化矩陣數據,因此將出現隨機值。如果想避免這種情況,可使用Mat類的幾種初始化創建矩陣的方法:

// 初始化方法
    cv::Mat mz = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); // 全零矩陣
    cv::Mat mo = cv::Mat::ones(cv::Size(5,5),CV_8UC1);  // 全1矩陣
    cv::Mat me = cv::Mat::eye(cv::Size(5,5),CV_32FC1);  // 對角線為1的對角矩陣
    cout<<"mz = "<<endl<<mz<<endl<<endl;
    cout<<"mo = "<<endl<<mo<<endl<<endl;
    cout<<"me = "<<endl<<me<<endl<<endl;

運行結果:

2. 矩陣運算

2.1 基本概念

 OpenCV的Mat類允許所有的矩陣運算。 

2.2 矩陣加減法

我們可以使用"+"和"-"符號進行矩陣加減運算。

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

 

2.3 矩陣乘法

使用"*"號計算矩陣與標量相乘,矩陣與矩陣相乘(必須滿足矩陣相乘的行列數對應規則)

    Mat m1= Mat::eye(2,3, CV_32F); //使用cv命名空間可省略cv::前綴,下同
    Mat m2= Mat::ones(3,2, CV_32F);
    cout<<"m1  = "<<endl<<m1<<endl<<endl;
    cout<<"m2  = "<<endl<<m2<<endl<<endl;
    // Scalar by matrix
    cout << "\nm1.*2 = \n" << m1*2 << endl;
    // matrix per element multiplication
    cout << "\n(m1+2).*(m1+3) = \n" << (m1+1).mul(m1+3) << endl;
    // Matrix multiplication
    cout << "\nm1*m2 = \n" << m1*m2 << endl;

2.4 矩陣轉置

矩陣轉置是將矩陣的行與列順序對調(第i行轉變為第i列)形成一個新的矩陣。OpenCV通過Mat類的t()函數實現。

// 轉置
    Mat m1= Mat::eye(2,3, CV_32F);    
    Mat m1t = m1.t();
    cout<<"m1  = "<<endl<<m1<<endl<<endl;
    cout<<"m1t  = "<<endl<<m1t<<endl<<endl;
    system("pause");

運行結果:

2.5 求逆矩陣

逆矩陣在某些算法中經常出現,在OpenCV中通過Mat類的inv()方法實現

1 // 求逆
2     Mat meinv = me.inv();
3     cout<<"me  = "<<endl<<me<<endl<<endl;
4     cout<<"meinv = "<<endl<<meinv<<endl<<endl;
5     system("pause");

運行結果:

單位矩陣的逆就是其本身。

2.6 計算矩陣非零元素個數

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

1 // 非零元素個數
2     int nonZerosNum = countNonZero(me); // me為輸入矩陣或圖像
3     cout<<"me  = "<<endl<<me<<endl;
4     cout<<"me中非零元素個數 = "<<nonZerosNum<<endl<<endl;
5     system("pause");

運行結果:

2.7 均值和標准差

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

參數

  • src – 輸入矩陣或圖像
  • mean – 均值,OutputArray
  • stddev – 標准差,OutputArray
1 // 均值方差
2     Mat mean;
3     Mat stddev;
4     meanStdDev(me, mean, stddev); //me為前文定義的5×5對角陣
5     cout<<"mean = "<<mean<<endl;
6     cout<<"stddev = "<<stddev<<endl;
7     system("pause");

運行結果:

需要說明的是,如果src是多通道圖像或多維矩陣,則函數分別計算不同通道的均值與標准差,因此返回值mean和stddev為對應維度的向量。

1     Mat mean3;
2     Mat stddev3;
3     Mat m3(cv::Size(5,5),CV_8UC3,Scalar(255,200,100));
4     cout<<"m3  = "<<endl<<m3<<endl<<endl;
5     meanStdDev(m3, mean3, stddev3);
6     cout<<"mean3 = "<<mean3<<endl;
7     cout<<"stddev3 = "<<stddev3<<endl;
8     system("pause");

多通道矩陣運算結果:

2.8 求最大最小值

求輸入矩陣的全局最大最小值及其位置,可使用函數

1 void minMaxLoc(InputArray src, CV_OUT double* minVal,
2                            CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,
3                            CV_OUT Point* maxLoc=0, InputArray mask=noArray());

參數:

src – 輸入單通道矩陣(圖像).
minVal – 指向最小值的指針, 如果未指定則使用NULL
maxVal – 指向最大值的指針, 如果未指定則使用NULL
minLoc – 指向最小值位置(2維情況)的指針, 如果未指定則使用NULL
maxLoc – 指向最大值位置(2維情況)的指針, 如果未指定則使用NULL
mask – 可選的蒙版,用於選擇待處理子區域

 1 // 求極值 最大、最小值及其位置
 2     Mat img = imread("Lena.jpg",0);
 3     imshow("original image",img);
 4  
 5     double minVal=0,maxVal=0;
 6     cv::Point minPt, maxPt;
 7     minMaxLoc(img,&minVal,&maxVal,&minPt,&maxPt);
 8     cout<<"min value  = "<<minVal<<endl;
 9     cout<<"max value  = "<<maxVal<<endl;
10     cout<<"minPt = ("<<minPt.x<<","<<minPt.y<<")"<<endl;
11     cout<<"maxPt = ("<<maxPt.x<<","<<maxPt.y<<")"<<endl;
12     cout<<endl;
13  
14     cv::Rect rectMin(minPt.x-10,minPt.y-10,20,20);
15     cv::Rect rectMax(maxPt.x-10,maxPt.y-10,20,20);
16  
17     cv::rectangle(img,rectMin,cv::Scalar(200),2);
18     cv::rectangle(img,rectMax,cv::Scalar(255),2);
19  
20     imshow("image with min max location",img);
21     cv::waitKey();

運行結果:

輸入圖像及其最大最小值位置

其他矩陣運算函數見:https://blog.csdn.net/iracer/article/details/51296631

轉載於:https://blog.csdn.net/iracer/article/details/51296631


免責聲明!

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



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