2017-03-29 114 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