En essayant d'analyser la sortie OpenCV YAML avec yaml-cpp
-
28-09-2019 - |
Question
J'ai une série de OpenCV fichiers générés YAML et souhaite les analyser avec YAML-cpp
Je vais bien sur des choses simples, mais la représentation matricielle se révèle difficile.
# Center of table
tableCenter: !!opencv-matrix
rows: 1
cols: 2
dt: f
data: [ 240, 240]
Ceci devrait la carte dans le vecteur
240
240
avec le type float . Mon code ressemble à:
#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;
}
Mais je reçois
terminate called after throwing an instance of 'YAML::BadDereference'
what(): yaml-cpp: error at line 0, column 0: bad dereference
Abort trap
Je cherchai autour de la documentation pour yaml-cpp, mais il ne semble pas y avoir, en dehors d'un court exemple d'introduction sur l'analyse syntaxique et d'émettre. Malheureusement, aucun de ces deux aide dans ce cas particulier.
Si je comprends bien, le !! indique que c'est un type défini par l'utilisateur, mais je ne vois pas yaml-cpp comment analyser cela.
La solution
Vous devez dire yaml-cpp
comment analyser ce type. Puisque C ++ n'est pas typé dynamiquement, il ne peut pas détecter quel type de données que vous voulez et créer à partir de zéro - il faut le dire directement. Le marquage d'un noeud est vraiment seulement pour vous-même, pas pour l'analyseur (il vous reste plus qu'à conserver fidèlement pour vous).
Je ne suis pas sûr de savoir comment une matrice de OpenCV est stockée, mais si elle est quelque chose comme ceci:
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;
};
vous pouvez écrire quelque chose comme
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);
}
Modifier Il semble que vous êtes ok jusqu'à ici; mais vous manquez l'étape où l'analyseur charge les informations dans le YAML::Node
. Au lieu de cela, il tilisez comme:
std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc); // <-- this line was missing!
Matrix m;
doc["tableCenter"] >> m;
Note: Je devine que des moyens de dt: f
"type de données est float". Si tel est le cas, ça va vraiment dépendre de la façon dont les poignées de classe Matrix
cela. Si vous avez une classe différente pour chaque type de données (ou une classe templated), vous devrez lire ce champ premier , puis choisissez le type d'instancier. (Si vous connaissez il sera toujours flottant, qui va vous rendre la vie plus facile, bien sûr.)