Cercando di analizzare l'output OpenCV YAML con yaml-cpp
-
28-09-2019 - |
Domanda
Ho un serie di OpenCV genera file YAML e vorrebbe analizzare loro con YAML-cpp
che sto facendo bene su cose semplici, ma la rappresentazione di matrice si sta rivelando difficile.
# Center of table
tableCenter: !!opencv-matrix
rows: 1
cols: 2
dt: f
data: [ 240, 240]
Questo dovrebbe mappare nel vettore
240
240
di tipo float . I miei sguardi codice come:
#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;
}
Ma ottengo
terminate called after throwing an instance of 'YAML::BadDereference'
what(): yaml-cpp: error at line 0, column 0: bad dereference
Abort trap
Ho cercato in giro per un po 'di documentazione per YAML-cpp, ma non sembra essere qualsiasi, a parte un breve esempio introduttivo sul parsing ed emettendo. Purtroppo, nessuno di questi due aiuto in questa particolare circostanza.
Per quanto ho capito, il !! indica che si tratta di un tipo definito dall'utente, ma non vedo con YAML-cpp come analizzare questo.
Soluzione
Devi dire yaml-cpp
come analizzare questo tipo. Dal momento che C ++ non è digitato in modo dinamico, non è in grado di rilevare il tipo di dati che si desidera e creare da zero - si deve dire direttamente. Tagging un nodo è in realtà solo per te stesso, non per il parser (sarà solo fedelmente conservarlo per voi).
Non sono davvero sicuro di come una matrice OpenCV è memorizzato, ma se si tratta di qualcosa di simile:
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;
};
allora si può scrivere qualcosa come
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);
}
Modifica Sembra che stai bene fino a qui; ma ti manca il passaggio in cui il parser carica le informazioni nel YAML::Node
. Invece, SE piace:
std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc); // <-- this line was missing!
Matrix m;
doc["tableCenter"] >> m;
Nota: Sto indovinando mezzi dt: f
"tipo di dati è float". Se questo è il caso, sarà davvero dipenderà da come le maniglie di classe Matrix
questo. Se si dispone di una classe diversa per ciascun tipo di dati (o di una classe su modelli), si dovrà leggere quel campo prima , e poi scegliere quale tipo di istanziare. (Se sa che sarà sempre galleggiante, che farà la vita più facile, ovviamente.)