1. 程式人生 > >OpenCV 學習筆記 (三) 基本矩陣操作與示例

OpenCV 學習筆記 (三) 基本矩陣操作與示例

OpenCV 的基本矩陣操作與示例

OpenCV 中的矩陣操作非常重要。 要熟悉起來!

學習該博主的基本示例:

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

0x01 建立與初始化矩陣

1.1 資料型別

建立矩陣必須要指定矩陣儲存的資料型別, 影象處理中常用的幾種資料型別如下 :

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

1.2 基本方法

可以通過載入影象來建立 Mat 型別矩陣, 也可以直接手動建立矩陣, 基本方法是指定矩陣尺寸和資料型別:

// 1.2 基本方法
    cv::Mat a(cv::Size(5,5), CV_8UC1);      // 單通道
    cv::Mat b = cv::Mat(cv::Size(5,5), CV_8UC3);        // 3 通道每個矩陣元素包含 3 個 uchar 值

    cout << "a = " << endl << a << endl << endl;
    cout << "b = "
<< endl << b << endl << endl; system("color A"); system("pause");

3 通道矩陣中, 一個矩陣元素包括 3 個變數。

1.3 初始化方法

可以看到上面的矩陣數值並沒有初始化, 避免這種情況, 使用 Mat 類的幾種初始化建立矩陣的方法 :

// 1.3 初始化方法
cv::Mat m_Zeros = cv::Mat::zeros(cv::Size(5,5), CV_8SC1);   // 全零矩陣
cv::Mat m_One = cv::Mat::ones(cv::Size(5
,5), CV_8UC1); // 全 1 矩陣 cv::Mat m_Eye = cv::Mat::eye(cv::Size(5,5), CV_32FC1); // 對角線為 1 的矩陣 cout << "m_Zeros = " << endl << m_Zeros << endl << endl ; cout << "m_One = " << endl << m_One << endl << endl ; cout << "m_Eye = " << endl << m_Eye << endl << endl ; system("color A"); system("pause");

0x02 矩陣的運算

2.1 基本概念

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

2.2 矩陣加減法

使用 + 或者 - 符號進行矩陣加減運算。

// 2.2 矩陣加減法
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;

cout << "a" << endl << a << endl << endl ;
cout << "b" << endl << b << endl << endl ;
cout << "c = a+b" << endl << c << endl << endl ;
cout << "d = a-b " << endl << d << endl << endl ;

system("color A");
system("pause");

2.3 矩陣乘法

矩陣與矩陣相乘, 必須滿足矩陣相乘的行列數對應規則。

// 2.3 矩陣乘法
Mat m1 = Mat::eye(2,3, CV_32F);
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+m2).*(m1+m3) = \n" << (m1+1).mul(m1+3) << endl;

// Matrix mutiplication
cout << "\nm1*m2 = \n" << m1*m2 << endl;

system("color A");
system("pause");

2.4 矩陣轉置

矩陣轉置是將矩陣的行與列順序對調, 將第幾行轉變為第幾列。OpenCV 通過 Mat 類的 t() 函式實現。

// 2.4 矩陣轉置
Mat m1 = Mat::eye(2,3, CV_32F);
Mat m1_t = m1.t();

cout << "m1 = " << endl << m1 << endl << endl;
cout << "m1t = " << endl << m1_t << endl << endl;

system("color A");
system("pause");

2.5 矩陣求逆

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

// 2.5 求逆矩陣
Mat me = Mat::eye(5,5, CV_32FC1);
Mat meinv = me.inv();

cout << "me = "<< endl << " "<< me << endl << endl;
cout << "meinv = "<< endl << " " << meinv << endl << endl;

// 單位矩陣的逆就是本身.
system("color A");
system("pause");

2.6 計算矩陣非零元素個數

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

Mat me = Mat::eye(6,6, CV_32FC1);
int nonZerosNum = countNonZero(me); // me 為輸入矩陣或者影象

cout << "me = " << endl << " " << me << endl << endl;
cout << "me 中非零元素的個數 =" << nonZerosNum << endl << endl;

system("color A");
system("pause");

2.7 均值和標準差

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

  • 引數一 src, 輸入矩陣或者影象
  • 引數二 mean, 均值, OutputArray
  • 引數三 stddev, 標準差, OutputArray
Mat me = Mat::eye(5,5, CV_32FC1);
Mat mean;
Mat stddev;

meanStdDev(me, mean, stddev); // me 為定義的對角矩陣
cout << "me = " << endl << " " << me << endl << endl;
cout << "mean = " << endl << " " << mean << endl << endl;
cout << "stddev = " << endl << " " << stddev << endl << endl;

system("color A");
system("pause");

單通道執行結果:

如果 src 是多通道影象或者多維矩陣, 則函式分別計算不同通道的均值與標準差, 因此返回值 mean 和 stddev 為對應維度的向量。

Mat mean3;
Mat stddev3;
Mat m3(cv::Size(5,5), CV_8UC3, Scalar(255,200,100));
cout << "m3 = " << endl << " " << m3 <<endl <<endl;

meanStdDev(m3, mean3, stddev3);
cout << "mean3 = " << endl << " " << mean3 << endl << endl;
cout << "stddev3 = " << endl << " " << stddev3 << endl << endl;

system("color A");
system("pause");

多通道執行結果 :

2.8 求最大值和最小值

求輸入矩陣的全域性最大值最小值及其位置, 可使用函式:

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

引數 :

  • src, 輸入單通道矩陣 (影象).
  • minVal, 指向最小值的指標, 如果未指定則使用 NULL.
  • maxVal, 指向最大值的指標, 如果未指定則使用 NULL.
  • minLoc, 指向最小值位置 (2 維情況) 的指標, 如果未指定則使用 NULL.
  • mask, 可選的蒙版, 用於選擇待處理區域.
// 求極值: 最大值、最小值及其位置
Mat img = imread("Lena.jpg",0);
imshow("original image", img);

ofstream fout("lena1.txt");     // 儲存資料的檔案

double minVal = 0, maxVal = 0;
cv::Point minPt, maxPt;
minMaxLoc(img, &minVal, &maxVal, &minPt, &maxPt);

cout << "min value = " << minVal << endl;
cout << "max value = " << maxVal << endl;
cout << "minPt = " << minPt << endl;
cout << "maxPt = " << maxPt << endl;

fout << "min value = " << minVal << endl;
fout << "max value = " << maxVal << endl;
fout << "minPt = " << minPt << endl;
fout << "maxPt = " << maxPt <<endl;

Rect rectMin(minPt.x - 10, minPt.y - 10, 20, 20);
Rect rectMax(maxPt.x - 10, maxPt.y - 10, 20, 20);

rectangle(img, rectMin, cv::Scalar(200,2));
rectangle(img, rectMax, cv::Scalar(255,2));

imshow("img with min max loction", img);

system("color A");
waitKey(0);

0x03 其他矩陣運算