Попытка разобрать вывод OpenCV YAML с помощью yaml-cpp

У меня есть серия файлов YAML, сгенерированных OpenCv, и я хотел бы проанализировать их с помощью yaml-cpp.

Я хорошо справляюсь с простыми вещами, но матричное представление оказывается сложным.

# Center of table
tableCenter: !!opencv-matrix
   rows: 1
   cols: 2
   dt: f
   data: [ 240,    240]

Это должно отображаться в вектор

240
240

с типом float. Мой код выглядит так:

#include "yaml.h"
#include <fstream>
#include <string>

struct Matrix {
    int x;
};

void operator >> (const YAML::Node& node, Matrix& matrix) {
   unsigned rows;
   node["rows"] >> rows;
}

int main()
{
   std::ifstream fin("monsters.yaml");
   YAML::Parser parser(fin);
   YAML::Node doc;

    Matrix m;
    doc["tableCenter"] >> m;

   return 0;
}

Но я получаю

terminate called after throwing an instance of 'YAML::BadDereference'
  what():  yaml-cpp: error at line 0, column 0: bad dereference
Abort trap

Я искал некоторую документацию для yaml-cpp, но, похоже, ее не было, кроме короткого вводного примера по синтаксическому анализу и генерированию. К сожалению, ни один из этих двух не помогает в данном конкретном случае.

Как я понимаю, !! указывает, что это определяемый пользователем тип, но я не вижу, как yaml-cpp его анализировать.


person Kenn Sebesta    schedule 20.04.2010    source источник


Ответы (1)


Вы должны сообщить yaml-cpp, как анализировать этот тип. Поскольку C++ не имеет динамической типизации, он не может определить, какой тип данных вам нужен, и создать его с нуля — вы должны указать это напрямую. Пометка узла действительно предназначена только для вас, а не для синтаксического анализатора (он просто сохранит его для вас).

Я не совсем уверен, как хранится матрица OpenCV, но если это что-то вроде этого:

class Matrix {
public:
   Matrix(unsigned r, unsigned c, const std::vector<float>& d): rows(r), cols(c), data(d) { /* init */ }
   Matrix(const Matrix&) { /* copy */ }
   ~Matrix() { /* delete */ }
   Matrix& operator = (const Matrix&) { /* assign */ }

private:
   unsigned rows, cols;
   std::vector<float> data;
};

тогда вы можете написать что-то вроде

void operator >> (const YAML::Node& node, Matrix& matrix) {
   unsigned rows, cols;
   std::vector<float> data;
   node["rows"] >> rows;
   node["cols"] >> cols;
   node["data"] >> data;
   matrix = Matrix(rows, cols, data);
}

Изменить Похоже, что до сих пор все в порядке; но вы пропустили шаг, на котором синтаксический анализатор загружает информацию в файл YAML::Node. Вместо этого используйте его как:

std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc); // <-- this line was missing!

Matrix m;
doc["tableCenter"] >> m;

Примечание. Я предполагаю, что dt: f означает «тип данных с плавающей запятой». Если это так, это действительно будет зависеть от того, как класс Matrix справится с этим. Если у вас есть разные классы для каждого типа данных (или шаблонный класс), вам придется сначала прочитать это поле, а затем выбрать тип для создания экземпляра. (Если вы знаете, что это всегда будет число с плавающей запятой, это, конечно, облегчит вам жизнь.)

person Jesse Beder    schedule 20.04.2010