OpenCV入門教程(5)-Mat類之Mat_類
阿新 • • 發佈:2019-02-01
Mat_類是對 Mat 類的一個包裝,其定義如下:
template<typename _Tp> class Mat_ : public Mat
{
public:
//只定義了幾個方法
//沒有定義新的屬性
};
這是一個非常輕量級的包裝,既然已經有 Mat 類,為何還要定義一個 Mat_?下面我們看這段程式碼:
Mat M(600, 800, CV_8UC1);
for( int i = 0; i < M.rows; ++i)
{
uchar * p = M.ptr<uchar>(i);
for( int j = 0; j < M.cols; ++j )
{
double d1 = (double) ((i+j)%255);
M.at<uchar>(i,j) = d1;
double d2 = M.at<double>(i,j);//此行有錯
}
}
在讀取矩陣元素時,以及獲取矩陣某行的地址時,需要指定資料型別。這樣首先需要不停地寫“”,讓人感覺很繁瑣,在繁瑣和煩躁中容易犯錯,如上面程式碼中的錯誤,用 at()獲取矩陣元素時錯誤的使用了 double 型別。這種錯誤不是語法錯誤,因此在編譯時編譯器不會提醒。在程式執行時,at()函式獲取到的不是期望的(i,j)位置處的元素,資料已經越界,但是執行時也未必會報錯。這樣的錯誤使得你的程式忽而看上去正常,忽而彈出“段錯誤”,特別是在程式碼規模很大時,難以查錯。
如果使用 Mat_類,那麼就可以在變數宣告時確定元素的型別,訪問元素時不再需要指定元素型別,即使得程式碼簡潔,又減少了出錯的可能性。上面程式碼可以用 Mat_實現,實現程式碼如下面例程裡的第二個雙重 for 迴圈。
#include <iostream>
#include "opencv2/opencv.hpp"
#include <stdio.h>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
Mat M(600, 800, CV_8UC1);
for( int i = 0; i < M.rows; ++i)
{
//獲取指標時需要指定型別
uchar * p = M.ptr<uchar>(i);
for ( int j = 0; j < M.cols; ++j )
{
double d1 = (double) ((i+j)%255);
//用 at()讀寫畫素時,需要指定型別
M.at<uchar>(i,j) = d1;
//下面程式碼錯誤,應該使用 at<uchar>()
//但編譯時不會提醒錯誤
//執行結果不正確,d2 不等於 d1
double d2 = M.at<double>(i,j);
}
}
//在變數宣告時指定矩陣元素型別
Mat_<uchar> M1 = (Mat_<uchar>&)M;
for( int i = 0; i < M1.rows; ++i)
{
//不需指定元素型別,語句簡潔
uchar * p = M1.ptr(i);
for( int j = 0; j < M1.cols; ++j )
{
double d1 = (double) ((i+j)%255);
//直接使用 Matlab 風格的矩陣元素讀寫,簡潔
M1(i,j) = d1;
double d2 = M1(i,j);
}
}
return 0;
}