天天看點

OpenCV2.3.1學習筆記(1):用vec類型變量構造Mat

文章要說的内容如題:用vec類型變量構造Mat

在OpenCV2.3.1的英文版官方手冊的25頁有一段執行個體代碼:

std::vector<Point3f> vec;

...

Mat pointMat = Mat(vec).     // convert vector to Mat, O(1) operation

                         reshape(1). // make Nx3 1-channel matrix out of Nx1 3-channel.

                                               // Also, an O(1) operation

                         t();                 // finally, transpose the Nx3 matrix.

                                               // This involves copying all the elements

第一行,當我們利用Mat(vec)來構造了一個Mat類型的後,如果我們直接利用Mat中的Mat.at<float>(i,j)來輸出元素的時候,我發現它隻是輸出了Point3f一個三維空間點的第一個坐标值,那麼問題出在什麼地方呢?

讓我們在Mat pointMat = Mat(vec).    一行按F9插入斷點,然後按F11進入程式中去檢視真相:

程式進入到了mat.hpp檔案中如下圖中的位置:

OpenCV2.3.1學習筆記(1):用vec類型變量構造Mat

然後我們仔細分析代碼:

template<typename _Tp> inline Mat::Mat(const vector<_Tp>& vec, bool copyData)

    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),  //初始化清單

    dims(2), rows((int)vec.size()), cols(1), data(0), refcount(0),               //初始化清單

    datastart(0), dataend(0), allocator(0), size(&rows)                            //初始化清單

{

    if(vec.empty())

        return;

    if( !copyData )

    {

        step[0] = step[1] = sizeof(_Tp);

        data = datastart = (uchar*)&vec[0];

        datalimit = dataend = datastart + rows*step[0];

    }

    else

        Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);

}

如紅色部分顯示,原來我們構造的Mat類型資料的行數row等于vec.size()。那麼因為vec的元素類型是Point3f類型的,是以其實我們産生的Mat的行數就是1.自然當我們利用循環來顯示Mat資料時,就隻顯示出了一個元素,如果想顯示三個坐标:那麼我們隻能利用data(指向真實資料的char*類型指針來操作了)

如下:

 cout<<*((float*)pointMat.data)<<endl;

 cout<<*((float*)pointMat.data+1)<<endl;

 cout<<*((float*)pointMat.data+2)<<endl;

就可以顯示Point3f三個坐标系的值了。