OpenCV中cv :: Mat的自定义类型

时间:2017-03-29 09:11:28

标签: c++ 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();
}

但是&#34;分配&#34;之间的结果;和&#34;显示&#34;部分不一样:

如何使这些结果相同?

1 个答案:

答案 0 :(得分: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 Mats。

  3. 如果x中的yCellXY字段指的是矩阵位置,为什么还需要它们?您可以简单地为您的概率设置Mat1f(又名Mat_<float>),x,y是矩阵中的位置。