2017-03-29 88 views
3

我想用我的自定義類型創建一個使用cv :: Mat的數組。這裏是我的代碼:在OpenCV中cv :: Mat的自定義類型

typedef struct{ 
    int x; 
    int y; 
    float prob; 
}CellXY; 

void main(){ 

    cv::Mat_<CellXY> map(10, 10); 

    std::cout << "Width = " << map.cols << ", Height = " << map.rows << std::endl; 
    std::cout << "### Assignment ###" << std::endl; 
    for (int j=0; j<map.rows; j++){ 
    for (int i=0; i<map.cols; i++){ 
     map.at<CellXY>(j, i).x = i; 
     map.at<CellXY>(j, i).y = j; 
     map.at<CellXY>(j, i).prob = (float)(i + j * map.cols); 

     std::cout << map.at<CellXY>(j, i).prob 
     << " (" << map.at<CellXY>(j, i).x 
     << "," << map.at<CellXY>(j, i).y 
     << ")\t"; 
    } 
    std::cout << std::endl; 
    } 

    std::cout << "### Display ###" << std::endl; 
    for (int j=0; j<map.rows; j++){ 
    for (int i=0; i<map.cols; i++){ 
     std::cout << map.at<CellXY>(j, i).prob 
     << " (" << map.at<CellXY>(j, i).x 
     << "," << map.at<CellXY>(j, i).y 
     << ")\t"; 
    } 
    std::cout << std::endl; 
    } 
    map.release(); 
} 

「分配」和「顯示」部分之間。然而結果是不一樣的:

如何使這些結果一樣嗎?

回答

1

這是因爲OpenCV不知道你班上的DataType。你需要一個專門爲它,像這樣:

typedef struct { 
    int x; 
    int y; 
    float prob; 
}CellXY; 


// Add this!!!!!! 
namespace cv { 
template<> class DataType<CellXY> 
{ 
public: 
    typedef CellXY  value_type; 
    typedef value_type work_type; 
    typedef value_type channel_type; 
    typedef value_type vec_type; 
    enum { generic_type = 0, 
     depth  = CV_32F, // Might cause problems... I'm saying it's all made of floats (and not 2 int a 1 float) 
     channels  = 3, 
     fmt   = (int)'p', 
     type   = CV_MAKETYPE(depth, channels) 
    }; 
}; 
} 

void main() { 
    ... 
} 

但是,在一般情況下,我認爲這是更好地避免這些執行細節搞亂了,並且只使用一個更好的數據結構。建議爲:僅對原始類型使用Mat。事實上,你不能在其他OpenCV函數無論如何使用它...

這裏有一些方法來解決你的問題:

  1. 使用另一種數據結構:例如一個std::vector<std::vector<CellXY>>「展開」std::vector<CellXY>
  2. 使類CellXYMatrix與存儲CellXY涉及:

    class CellXYMatrix 
    { 
        std::vector<CellXY> _mat; // your matrix of CellXY 
        int _r; // rows 
        int _c; // cols 
    
    public: 
        CellXYMatrix(int rows, int cols) : _r(rows), _c(cols), _mat(rows * cols) {}; 
    
        void set(int row, int col, const CellXY& cell) { 
         _mat[row * _c + col] = cell; 
        } 
        CellXY& get(int row, int col) { 
         return _mat[row * _c + col]; 
        } 
    } 
    

    最後,您可以重載operator()做出類似的OpenCV墊的訪問。

  3. 如果在CellXY中的xy字段指向矩陣位置,爲什麼需要它們?您可以簡單地爲您的概率設置Mat1f(又名Mat_<float>),x,y是矩陣中的位置。

+0

非常感謝您的幫助。我想你的解決方案中加入模板<>類數據類型但我得到這個錯誤: 錯誤:在不同的命名空間[-fpermissive]模板<>類數據類型「模板類品種::數據類型」的專業化 然而,我同意使用cv :: Mat原始類型如cv :: Point3f或cv :: Vec3f總是更好。 僅供參考:此外,我試圖修改「CellXY」結構中的數據類型,如下所示,它可以完美工作,無需添加模板DataType類。 typedef struct { float x; float y; float prob; } CellXY; – puwanan

+0

1)您需要將專業化放入'namespace cv'中...參閱編輯。 2)哦,不知道那個......但是那麼你可以使用'cv :: Vec3f';) – Miki

+0

我想使用cv :: Mat而不是std :: vector的原因是因爲我想動態地改變二維數組的大小。在OpenCV中,可以使用cv :: hconcat(B,A,result)或cv :: vconcat(B,A,result)輕鬆完成。因此,可以輕鬆地將新數組添加到原始數組的頂部,底部,左側或右側位置。 – puwanan