Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
vpXmlParserCamera.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * XML parser to load and save camera intrinsic parameters.
33  *
34  *****************************************************************************/
35 
42 #include <visp3/core/vpXmlParserCamera.h>
43 
44 #ifdef VISP_HAVE_PUGIXML
45 
46 #include <pugixml.hpp>
47 
48 #include <visp3/core/vpDebug.h>
49 /* --------------------------------------------------------------------------
50  */
51 /* --- LABEL XML ------------------------------------------------------------
52  */
53 /* --------------------------------------------------------------------------
54  */
55 
56 #define LABEL_XML_ROOT "root"
57 #define LABEL_XML_CAMERA "camera"
58 #define LABEL_XML_CAMERA_NAME "name"
59 #define LABEL_XML_WIDTH "image_width"
60 #define LABEL_XML_HEIGHT "image_height"
61 #define LABEL_XML_SUBSAMPLING_WIDTH "subsampling_width"
62 #define LABEL_XML_SUBSAMPLING_HEIGHT "subsampling_height"
63 #define LABEL_XML_FULL_WIDTH "full_width"
64 #define LABEL_XML_FULL_HEIGHT "full_height"
65 #define LABEL_XML_MODEL "model"
66 #define LABEL_XML_MODEL_TYPE "type"
67 #define LABEL_XML_U0 "u0"
68 #define LABEL_XML_V0 "v0"
69 #define LABEL_XML_PX "px"
70 #define LABEL_XML_PY "py"
71 #define LABEL_XML_KUD "kud"
72 #define LABEL_XML_KDU "kdu"
73 
74 #define LABEL_XML_MODEL_WITHOUT_DISTORTION "perspectiveProjWithoutDistortion"
75 #define LABEL_XML_MODEL_WITH_DISTORTION "perspectiveProjWithDistortion"
76 
77 #define LABEL_XML_ADDITIONAL_INFO "additional_information"
78 
79 #ifndef DOXYGEN_SHOULD_SKIP_THIS
80 class vpXmlParserCamera::Impl
81 {
82 private:
83  /* --- XML Code------------------------------------------------------------
84  */
85  enum vpXmlCodeType {
86  CODE_XML_BAD = -1,
87  CODE_XML_OTHER,
88  CODE_XML_CAMERA,
89  CODE_XML_CAMERA_NAME,
90  CODE_XML_HEIGHT,
91  CODE_XML_WIDTH,
92  CODE_XML_SUBSAMPLING_WIDTH,
93  CODE_XML_SUBSAMPLING_HEIGHT,
94  CODE_XML_FULL_HEIGHT,
95  CODE_XML_FULL_WIDTH,
96  CODE_XML_MODEL,
97  CODE_XML_MODEL_TYPE,
98  CODE_XML_U0,
99  CODE_XML_V0,
100  CODE_XML_PX,
101  CODE_XML_PY,
102  CODE_XML_KUD,
103  CODE_XML_KDU,
104  CODE_XML_ADDITIONAL_INFO
105  };
106 
107 public:
108  Impl() : camera(), camera_name(), image_width(0), image_height(0), subsampling_width(0),
109  subsampling_height(0), full_width(0), full_height(0)
110  {
111  }
112 
113  int parse(vpCameraParameters &cam, const std::string &filename, const std::string &cam_name,
115  unsigned int im_width, unsigned int im_height)
116  {
117  pugi::xml_document doc;
118  if (!doc.load_file(filename.c_str())) {
119  return SEQUENCE_ERROR;
120  }
121 
122  pugi::xml_node node = doc.document_element();
123  if (!node) {
124  return SEQUENCE_ERROR;
125  }
126 
127  int ret = read(node, cam_name, projModel, im_width, im_height);
128 
129  cam = camera;
130 
131  return ret;
132  }
133 
149  int read(const pugi::xml_node &node_, const std::string &cam_name,
151  unsigned int im_width, unsigned int im_height,
152  unsigned int subsampl_width=0, unsigned int subsampl_height=0)
153  {
154  vpXmlCodeType prop;
155 
157  unsigned int nbCamera = 0;
158 
159  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
160  if (node.type() != pugi::node_element)
161  continue;
162 
163  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
164  prop = CODE_XML_OTHER;
165  back = SEQUENCE_ERROR;
166  }
167  if (prop == CODE_XML_CAMERA) {
168  if (SEQUENCE_OK ==
169  read_camera(node, cam_name, projModel, im_width, im_height, subsampl_width, subsampl_height))
170  nbCamera++;
171  } else
172  back = SEQUENCE_ERROR;
173  }
174 
175  if (nbCamera == 0) {
176  back = SEQUENCE_ERROR;
177  vpCERROR << "No camera parameters is available" << std::endl << "with your specifications" << std::endl;
178  } else if (nbCamera > 1) {
179  back = SEQUENCE_ERROR;
180  vpCERROR << nbCamera << " sets of camera parameters are available" << std::endl
181  << "with your specifications : " << std::endl
182  << "precise your choice..." << std::endl;
183  }
184 
185  return back;
186  }
187 
203  int read_camera(const pugi::xml_node &node_, const std::string &cam_name,
205  unsigned int im_width, unsigned int im_height,
206  unsigned int subsampl_width, unsigned int subsampl_height)
207  {
208  vpXmlCodeType prop;
209  /* read value in the XML file. */
210  std::string camera_name_tmp = "";
211  unsigned int image_height_tmp = 0;
212  unsigned int image_width_tmp = 0;
213  unsigned int subsampling_width_tmp = 0;
214  unsigned int subsampling_height_tmp = 0;
215  vpCameraParameters cam_tmp;
216  vpCameraParameters cam_tmp_model;
217  bool projModelFound = false;
219 
220  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
221  if (node.type() != pugi::node_element)
222  continue;
223 
224  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
225  prop = CODE_XML_OTHER;
226  back = SEQUENCE_ERROR;
227  }
228 
229  switch (prop) {
230  case CODE_XML_CAMERA_NAME: {
231  camera_name_tmp = node.text().as_string();
232  std::cout << "Found camera with name: \"" << camera_name_tmp << "\"" << std::endl;
233  break;
234  }
235  case CODE_XML_WIDTH:
236  image_width_tmp = node.text().as_uint();
237  break;
238 
239  case CODE_XML_HEIGHT:
240  image_height_tmp = node.text().as_uint();
241  break;
242  case CODE_XML_SUBSAMPLING_WIDTH:
243  subsampling_width_tmp = node.text().as_uint();
244  break;
245  case CODE_XML_SUBSAMPLING_HEIGHT:
246  subsampling_height_tmp = node.text().as_uint();
247  break;
248 
249  case CODE_XML_MODEL:
250  back = read_camera_model(node, cam_tmp_model);
251  if (cam_tmp_model.get_projModel() == projModel) {
252  cam_tmp = cam_tmp_model;
253  projModelFound = true;
254  }
255  break;
256 
257  case CODE_XML_ADDITIONAL_INFO:
258  break;
259 
260  case CODE_XML_BAD:
261  case CODE_XML_OTHER:
262  case CODE_XML_CAMERA:
263  case CODE_XML_FULL_HEIGHT:
264  case CODE_XML_FULL_WIDTH:
265  case CODE_XML_MODEL_TYPE:
266  case CODE_XML_U0:
267  case CODE_XML_V0:
268  case CODE_XML_PX:
269  case CODE_XML_PY:
270  case CODE_XML_KUD:
271  case CODE_XML_KDU:
272  default:
273  back = SEQUENCE_ERROR;
274  break;
275  }
276  }
277  // Create a specific test for subsampling_width and subsampling_height to
278  // ensure that division by zero is not possible in the next test
279  bool test_subsampling_width = true;
280  bool test_subsampling_height = true;
281 
282  if (subsampling_width) {
283  test_subsampling_width = (abs((int)subsampl_width - (int)subsampling_width_tmp) <
284  (allowedPixelDiffOnImageSize * (int)(subsampling_width_tmp / subsampling_width)));
285  }
286  if (subsampling_height) {
287  test_subsampling_height = (abs((int)subsampl_height - (int)subsampling_height_tmp) <
288  (allowedPixelDiffOnImageSize * (int)(subsampling_height_tmp / subsampling_height)));
289  }
290  if (!((projModelFound == true) && (cam_name == camera_name_tmp) &&
291  (abs((int)im_width - (int)image_width_tmp) < allowedPixelDiffOnImageSize || im_width == 0) &&
292  (abs((int)im_height - (int)image_height_tmp) < allowedPixelDiffOnImageSize || im_height == 0) &&
293  (test_subsampling_width) && (test_subsampling_height))) {
294  back = SEQUENCE_ERROR;
295  } else {
296  camera = cam_tmp;
297  camera_name = camera_name_tmp;
298  image_width = image_width_tmp;
299  image_height = image_height_tmp;
300  subsampling_width = subsampling_width_tmp;
301  subsampling_height = subsampling_height_tmp;
302  full_width = subsampling_width_tmp * image_width_tmp;
303  full_height = subsampling_height_tmp * image_height_tmp;
304  }
305  return back;
306  }
307 
314  vpXmlCodeSequenceType read_camera_model(const pugi::xml_node &node_,
315  vpCameraParameters &cam_tmp)
316  {
317  // counter of the number of read parameters
318  int nb = 0;
319  vpXmlCodeType prop;
320  /* read value in the XML file. */
321 
322  std::string model_type = "";
323  double u0 = cam_tmp.get_u0();
324  double v0 = cam_tmp.get_v0();
325  double px = cam_tmp.get_px();
326  double py = cam_tmp.get_py();
327  double kud = cam_tmp.get_kud();
328  double kdu = cam_tmp.get_kdu();
330  int validation = 0;
331 
332  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
333  // vpDEBUG_TRACE (15, "Carac : %s.", node ->name);
334  if (node.type() != pugi::node_element)
335  continue;
336 
337  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
338  prop = CODE_XML_OTHER;
339  back = SEQUENCE_ERROR;
340  }
341 
342  switch (prop) {
343  case CODE_XML_MODEL_TYPE: {
344  model_type = node.text().as_string();
345  nb++;
346  validation = validation | 0x01;
347  } break;
348  case CODE_XML_U0:
349  u0 = node.text().as_double();
350  nb++;
351  validation = validation | 0x02;
352  break;
353  case CODE_XML_V0:
354  v0 = node.text().as_double();
355  nb++;
356  validation = validation | 0x04;
357  break;
358  case CODE_XML_PX:
359  px = node.text().as_double();
360  nb++;
361  validation = validation | 0x08;
362  break;
363  case CODE_XML_PY:
364  py = node.text().as_double();
365  nb++;
366  validation = validation | 0x10;
367  break;
368  case CODE_XML_KUD:
369  kud = node.text().as_double();
370  nb++;
371  validation = validation | 0x20;
372  break;
373  case CODE_XML_KDU:
374  kdu = node.text().as_double();
375  nb++;
376  validation = validation | 0x40;
377  break;
378  case CODE_XML_BAD:
379  case CODE_XML_OTHER:
380  case CODE_XML_CAMERA:
381  case CODE_XML_CAMERA_NAME:
382  case CODE_XML_HEIGHT:
383  case CODE_XML_WIDTH:
384  case CODE_XML_SUBSAMPLING_WIDTH:
385  case CODE_XML_SUBSAMPLING_HEIGHT:
386  case CODE_XML_FULL_HEIGHT:
387  case CODE_XML_FULL_WIDTH:
388  case CODE_XML_MODEL:
389  case CODE_XML_ADDITIONAL_INFO:
390  default:
391  back = SEQUENCE_ERROR;
392  break;
393  }
394  }
395 
396  if (model_type.empty()) {
397  vpERROR_TRACE("projection model type doesn't match with any known model !");
398  return SEQUENCE_ERROR;
399  }
400 
401  if (!strcmp(model_type.c_str(), LABEL_XML_MODEL_WITHOUT_DISTORTION)) {
402  if (nb != 5 || validation != 0x1F) {
403  vpCERROR << "ERROR in 'model' field:\n";
404  vpCERROR << "it must contain 5 parameters\n";
405 
406  return SEQUENCE_ERROR;
407  }
408  cam_tmp.initPersProjWithoutDistortion(px, py, u0, v0);
409  } else if (!strcmp(model_type.c_str(), LABEL_XML_MODEL_WITH_DISTORTION)) {
410  if (nb != 7 || validation != 0x7F) {
411  vpCERROR << "ERROR in 'model' field:\n";
412  vpCERROR << "it must contain 7 parameters\n";
413 
414  return SEQUENCE_ERROR;
415  }
416  cam_tmp.initPersProjWithDistortion(px, py, u0, v0, kud, kdu);
417  } else {
418  vpERROR_TRACE("projection model type doesn't match with any known model !");
419 
420  return SEQUENCE_ERROR;
421  }
422 
423  return back;
424  }
425 
426  int save(const vpCameraParameters &cam, const std::string &filename, const std::string &cam_name,
427  unsigned int im_width, unsigned int im_height,
428  const std::string &additionalInfo)
429  {
430  pugi::xml_document doc;
431  pugi::xml_node node;
432 
433  if (!doc.load_file(filename.c_str(), pugi::parse_default | pugi::parse_comments)) {
434  node = doc.append_child(pugi::node_declaration);
435  node.append_attribute("version") = "1.0";
436  node = doc.append_child(LABEL_XML_ROOT);
437  pugi::xml_node nodeComment = node.append_child(pugi::node_comment);
438  nodeComment.set_value("This file stores intrinsic camera parameters used\n"
439  " in the vpCameraParameters Class of ViSP available\n"
440  " at https://visp.inria.fr/download/ .\n"
441  " It can be read with the parse method of\n"
442  " the vpXmlParserCamera class.");
443  }
444 
445  node = doc.document_element();
446  if (!node) {
447  return SEQUENCE_ERROR;
448  }
449 
450  camera = cam;
451 
452  int nbCamera = count(node, cam_name, cam.get_projModel(), im_width, im_height);
453  if (nbCamera) {
454  return SEQUENCE_ERROR;
455  }
456 
457  pugi::xml_node nodeCamera = find_camera(node, cam_name, im_width, im_height);
458  if (!nodeCamera) {
459  write(node, cam_name, im_width, im_height);
460  } else {
461  write_camera(nodeCamera);
462  }
463 
464  if (!additionalInfo.empty()) {
465  // Get camera node pointer
466  nodeCamera = find_camera(node, cam_name, im_width, im_height);
467 
468  // Additional information provided by the user
469  pugi::xml_node nodeAdditionalInfo = find_additional_info(nodeCamera);
470 
471  if (!nodeAdditionalInfo) {
472  // Create the additional information node
473  pugi::xml_node node_comment = nodeCamera.append_child(pugi::node_comment);
474  node_comment.set_value("Additional information");
475 
476  nodeAdditionalInfo = nodeCamera.append_child(LABEL_XML_ADDITIONAL_INFO);
477  }
478 
479  if (nodeAdditionalInfo) {
480  // Add the information in this specific node
481  pugi::xml_document tmpDoc;
482  if (tmpDoc.load_string(additionalInfo.c_str())) {
483  for (node = tmpDoc.first_child(); node; node = node.next_sibling()) {
484  nodeAdditionalInfo.append_copy(node);
485  }
486  }
487  }
488  }
489 
490  doc.save_file(filename.c_str(), PUGIXML_TEXT(" "));
491 
492  return SEQUENCE_OK;
493  }
494 
511  int count(const pugi::xml_node &node_, const std::string &cam_name,
513  unsigned int im_width, unsigned int im_height,
514  unsigned int subsampl_width=0, unsigned int subsampl_height=0)
515  {
516  vpXmlCodeType prop;
517  int nbCamera = 0;
518 
519  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
520  if (node.type() != pugi::node_element)
521  continue;
522 
523  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
524  prop = CODE_XML_OTHER;
525  }
526 
527  if (prop == CODE_XML_CAMERA) {
528  if (SEQUENCE_OK ==
529  read_camera(node, cam_name, projModel, im_width, im_height, subsampl_width, subsampl_height))
530  nbCamera++;
531  }
532  }
533 
534  return nbCamera;
535  }
536 
553  pugi::xml_node find_camera(const pugi::xml_node &node_, const std::string &cam_name,
554  unsigned int im_width, unsigned int im_height,
555  unsigned int subsampl_width=0, unsigned int subsampl_height=0)
556  {
557  vpXmlCodeType prop;
558 
559  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
560  if (node.type() != pugi::node_element)
561  continue;
562 
563  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
564  prop = CODE_XML_OTHER;
565  }
566  if (prop == CODE_XML_CAMERA) {
567  if (SEQUENCE_OK == read_camera_header(node, cam_name, im_width, im_height, subsampl_width, subsampl_height)) {
568  return node;
569  }
570  }
571  }
572  return pugi::xml_node();
573  }
574 
590  int read_camera_header(const pugi::xml_node &node_, const std::string &cam_name,
591  unsigned int im_width, unsigned int im_height,
592  unsigned int subsampl_width=0, unsigned int subsampl_height=0)
593  {
594  vpXmlCodeType prop;
595  /* read value in the XML file. */
596  std::string camera_name_tmp = "";
597  unsigned int image_height_tmp = 0;
598  unsigned int image_width_tmp = 0;
599  unsigned int subsampling_width_tmp = 0;
600  unsigned int subsampling_height_tmp = 0;
602 
603  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
604  if (node.type() != pugi::node_element)
605  continue;
606  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
607  prop = CODE_XML_OTHER;
608  back = SEQUENCE_ERROR;
609  }
610 
611  switch (prop) {
612  case CODE_XML_CAMERA_NAME:
613  camera_name_tmp = node.text().as_string();
614  break;
615 
616  case CODE_XML_WIDTH:
617  image_width_tmp = node.text().as_uint();
618  break;
619 
620  case CODE_XML_HEIGHT:
621  image_height_tmp = node.text().as_uint();
622  break;
623 
624  case CODE_XML_SUBSAMPLING_WIDTH:
625  subsampling_width_tmp = node.text().as_uint();
626  break;
627 
628  case CODE_XML_SUBSAMPLING_HEIGHT:
629  subsampling_height_tmp = node.text().as_uint();
630  break;
631 
632  case CODE_XML_MODEL:
633  break;
634 
635  case CODE_XML_ADDITIONAL_INFO:
636  break;
637 
638  case CODE_XML_BAD:
639  case CODE_XML_OTHER:
640  case CODE_XML_CAMERA:
641  case CODE_XML_FULL_HEIGHT:
642  case CODE_XML_FULL_WIDTH:
643  case CODE_XML_MODEL_TYPE:
644  case CODE_XML_U0:
645  case CODE_XML_V0:
646  case CODE_XML_PX:
647  case CODE_XML_PY:
648  case CODE_XML_KUD:
649  case CODE_XML_KDU:
650  default:
651  back = SEQUENCE_ERROR;
652  break;
653  }
654  }
655  if (!((cam_name == camera_name_tmp) && (im_width == image_width_tmp || im_width == 0) &&
656  (im_height == image_height_tmp || im_height == 0) &&
657  (subsampl_width == subsampling_width_tmp || subsampl_width == 0) &&
658  (subsampl_height == subsampling_height_tmp || subsampl_height == 0))) {
659  back = SEQUENCE_ERROR;
660  }
661  return back;
662  }
663 
679  int write(pugi::xml_node &node, const std::string &cam_name, unsigned int im_width,
680  unsigned int im_height, unsigned int subsampl_width=0,
681  unsigned int subsampl_height=0)
682  {
683  int back = SEQUENCE_OK;
684 
685  // <camera>
686  pugi::xml_node node_camera = node.append_child(LABEL_XML_CAMERA);
687 
688  pugi::xml_node node_tmp;
689  {
690  //<name>
691  if (!cam_name.empty()) {
692  node_tmp = node_camera.append_child(pugi::node_comment);
693  node_tmp.set_value("Name of the camera");
694  node_tmp = node_camera.append_child(LABEL_XML_CAMERA_NAME);
695  node_tmp.append_child(pugi::node_pcdata).set_value(cam_name.c_str());
696  }
697 
698  if (im_width != 0 || im_height != 0) {
699  node_tmp = node_camera.append_child(pugi::node_comment);
700  node_tmp.set_value("Size of the image on which camera "
701  "calibration was performed");
702 
703  //<image_width>
704  node_tmp = node_camera.append_child(LABEL_XML_WIDTH);
705  node_tmp.append_child(pugi::node_pcdata).text() = im_width;
706 
707  //<image_height>
708  node_tmp = node_camera.append_child(LABEL_XML_HEIGHT);
709  node_tmp.append_child(pugi::node_pcdata).text() = im_height;
710  if (subsampling_width != 0 || subsampling_height != 0) {
711  node_tmp = node_camera.append_child(pugi::node_comment);
712  node_tmp.set_value("Subsampling used to obtain the "
713  "current size of the image.");
714 
715  //<subsampling_width>
716  node_tmp = node_camera.append_child(LABEL_XML_SUBSAMPLING_WIDTH);
717  node_tmp.append_child(pugi::node_pcdata).text() = subsampl_width;
718  //<subsampling_height>
719  node_tmp = node_camera.append_child(LABEL_XML_SUBSAMPLING_HEIGHT);
720  node_tmp.append_child(pugi::node_pcdata).text() = subsampl_height;
721  node_tmp = node_camera.append_child(pugi::node_comment);
722  node_tmp.set_value("The full size is the sensor size actually used to "
723  "grab the image. full_width = subsampling_width * "
724  "image_width");
725 
726  //<full_width>
727  node_tmp = node_camera.append_child(LABEL_XML_FULL_WIDTH);
728  node_tmp.append_child(pugi::node_pcdata).text() = im_width * subsampl_width;
729  //<full_height>
730  node_tmp = node_camera.append_child(LABEL_XML_FULL_HEIGHT);
731  node_tmp.append_child(pugi::node_pcdata).text() = im_height * subsampl_height;
732  }
733  }
734 
735  node_tmp = node_camera.append_child(pugi::node_comment);
736  node_tmp.set_value("Intrinsic camera parameters "
737  "computed for each projection model");
738 
739  back = write_camera(node_camera);
740  }
741  return back;
742  }
743 
749  int write_camera(pugi::xml_node &node_camera)
750  {
751  pugi::xml_node node_model;
752  pugi::xml_node node_tmp;
753 
754  int back = SEQUENCE_OK;
755  switch (camera.get_projModel()) {
757  //<model>
758  node_model = node_camera.append_child(LABEL_XML_MODEL);
759  {
760  node_tmp = node_model.append_child(pugi::node_comment);
761  node_tmp.set_value("Projection model type");
762 
763  //<type>without_distortion</type>
764  node_tmp = node_model.append_child(LABEL_XML_MODEL_TYPE);
765  node_tmp.append_child(pugi::node_pcdata).set_value(LABEL_XML_MODEL_WITHOUT_DISTORTION);
766 
767  node_tmp = node_model.append_child(pugi::node_comment);
768  node_tmp.set_value("Pixel ratio");
769  //<px>
770  node_tmp = node_model.append_child(LABEL_XML_PX);
771  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_px();
772  //<py>
773  node_tmp = node_model.append_child(LABEL_XML_PY);
774  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_py();
775 
776  node_tmp = node_model.append_child(pugi::node_comment);
777  node_tmp.set_value("Principal point");
778 
779  //<u0>
780  node_tmp = node_model.append_child(LABEL_XML_U0);
781  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_u0();
782  //<v0>
783  node_tmp = node_model.append_child(LABEL_XML_V0);
784  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_v0();
785  }
786  break;
787 
789  //<model>
790  node_model = node_camera.append_child(LABEL_XML_MODEL);
791  {
792  node_tmp = node_model.append_child(pugi::node_comment);
793  node_tmp.set_value("Projection model type");
794  //<type>with_distortion</type>
795  node_tmp = node_model.append_child(LABEL_XML_MODEL_TYPE);
796  node_tmp.append_child(pugi::node_pcdata).set_value(LABEL_XML_MODEL_WITH_DISTORTION);
797 
798  node_tmp = node_model.append_child(pugi::node_comment);
799  node_tmp.set_value("Pixel ratio");
800  //<px>
801  node_tmp = node_model.append_child(LABEL_XML_PX);
802  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_px();
803  //<py>
804  node_tmp = node_model.append_child(LABEL_XML_PY);
805  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_py();
806 
807  node_tmp = node_model.append_child(pugi::node_comment);
808  node_tmp.set_value("Principal point");
809  //<u0>
810  node_tmp = node_model.append_child(LABEL_XML_U0);
811  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_u0();
812  //<v0>
813  node_tmp = node_model.append_child(LABEL_XML_V0);
814  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_v0();
815 
816  //<kud>
817  node_tmp = node_model.append_child(pugi::node_comment);
818  node_tmp.set_value("Undistorted to distorted distortion parameter");
819  node_tmp = node_model.append_child(LABEL_XML_KUD);
820  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_kud();
821 
822  //<kud>
823  node_tmp = node_model.append_child(pugi::node_comment);
824  node_tmp.set_value("Distorted to undistorted distortion parameter");
825  node_tmp = node_model.append_child(LABEL_XML_KDU);
826  node_tmp.append_child(pugi::node_pcdata).text() = camera.get_kdu();
827  }
828  break;
829  }
830  return back;
831  }
832 
839  pugi::xml_node find_additional_info(const pugi::xml_node &node_)
840  {
841  vpXmlCodeType prop;
842 
843  for (pugi::xml_node node = node_.first_child(); node; node = node.next_sibling()) {
844  if (node.type() != pugi::node_element) {
845  continue;
846  }
847 
848  if (SEQUENCE_OK != str2xmlcode(node.name(), prop)) {
849  prop = CODE_XML_OTHER;
850  }
851 
852  if (prop == CODE_XML_ADDITIONAL_INFO) {
853  // We found the node
854  return node;
855  }
856  }
857 
858  return pugi::xml_node();
859  }
860 
861 
868  vpXmlCodeSequenceType str2xmlcode(const char *str, vpXmlCodeType &res)
869  {
870  vpXmlCodeType val_int = CODE_XML_BAD;
872 
873  if (!strcmp(str, LABEL_XML_CAMERA)) {
874  val_int = CODE_XML_CAMERA;
875  } else if (!strcmp(str, LABEL_XML_CAMERA_NAME)) {
876  val_int = CODE_XML_CAMERA_NAME;
877  } else if (!strcmp(str, LABEL_XML_MODEL)) {
878  val_int = CODE_XML_MODEL;
879  } else if (!strcmp(str, LABEL_XML_MODEL_TYPE)) {
880  val_int = CODE_XML_MODEL_TYPE;
881  } else if (!strcmp(str, LABEL_XML_WIDTH)) {
882  val_int = CODE_XML_WIDTH;
883  } else if (!strcmp(str, LABEL_XML_HEIGHT)) {
884  val_int = CODE_XML_HEIGHT;
885  } else if (!strcmp(str, LABEL_XML_SUBSAMPLING_WIDTH)) {
886  val_int = CODE_XML_SUBSAMPLING_WIDTH;
887  } else if (!strcmp(str, LABEL_XML_SUBSAMPLING_HEIGHT)) {
888  val_int = CODE_XML_SUBSAMPLING_HEIGHT;
889  } else if (!strcmp(str, LABEL_XML_FULL_WIDTH)) {
890  val_int = CODE_XML_FULL_WIDTH;
891  } else if (!strcmp(str, LABEL_XML_FULL_HEIGHT)) {
892  val_int = CODE_XML_FULL_HEIGHT;
893  } else if (!strcmp(str, LABEL_XML_U0)) {
894  val_int = CODE_XML_U0;
895  } else if (!strcmp(str, LABEL_XML_V0)) {
896  val_int = CODE_XML_V0;
897  } else if (!strcmp(str, LABEL_XML_PX)) {
898  val_int = CODE_XML_PX;
899  } else if (!strcmp(str, LABEL_XML_PY)) {
900  val_int = CODE_XML_PY;
901  } else if (!strcmp(str, LABEL_XML_KUD)) {
902  val_int = CODE_XML_KUD;
903  } else if (!strcmp(str, LABEL_XML_KDU)) {
904  val_int = CODE_XML_KDU;
905  } else if (!strcmp(str, LABEL_XML_ADDITIONAL_INFO)) {
906  val_int = CODE_XML_ADDITIONAL_INFO;
907  } else {
908  val_int = CODE_XML_OTHER;
909  }
910  res = val_int;
911 
912  return back;
913  }
914 
915  std::string getCameraName() const { return camera_name; }
916  vpCameraParameters getCameraParameters() const { return camera; }
917  unsigned int getHeight() const { return image_height; }
918  unsigned int getSubsampling_width() const { return subsampling_width; }
919  unsigned int getSubsampling_height() const { return subsampling_height; }
920  unsigned int getWidth() const { return image_width; }
921 
922  void setCameraName(const std::string &name) { camera_name = name; }
923  void setHeight(unsigned int height) { image_height = height; }
924  void setSubsampling_width(unsigned int subsampling) { subsampling_width = subsampling; }
925  void setSubsampling_height(unsigned int subsampling) { subsampling_height = subsampling; }
926  void setWidth(unsigned int width) { image_width = width; }
927 
928 private:
929  vpCameraParameters camera;
930  std::string camera_name;
931  unsigned int image_width;
932  unsigned int image_height;
933  unsigned int subsampling_width;
934  unsigned int subsampling_height;
935  unsigned int full_width;
936  unsigned int full_height;
937 
940  static const int allowedPixelDiffOnImageSize = 15;
941 };
942 #endif // DOXYGEN_SHOULD_SKIP_THIS
943 
945 {
946 }
947 
949 {
950  delete m_impl;
951 }
952 
967 int vpXmlParserCamera::parse(vpCameraParameters &cam, const std::string &filename, const std::string &cam_name,
969  unsigned int im_width, unsigned int im_height)
970 {
971  return m_impl->parse(cam, filename, cam_name, projModel, im_width, im_height);
972 }
973 
1017 int vpXmlParserCamera::save(const vpCameraParameters &cam, const std::string &filename, const std::string &cam_name,
1018  unsigned int im_width, unsigned int im_height,
1019  const std::string &additionalInfo)
1020 {
1021  return m_impl->save(cam, filename, cam_name, im_width, im_height, additionalInfo);
1022 }
1023 
1025 {
1026  return m_impl->getCameraName();
1027 }
1028 
1030 {
1031  return m_impl->getCameraParameters();
1032 }
1033 
1034 unsigned int vpXmlParserCamera::getHeight() const
1035 {
1036  return m_impl->getHeight();
1037 }
1038 
1040 {
1041  return m_impl->getSubsampling_width();
1042 }
1043 
1045 {
1046  return m_impl->getSubsampling_height();
1047 }
1048 
1049 unsigned int vpXmlParserCamera::getWidth() const
1050 {
1051  return m_impl->getWidth();
1052 }
1053 
1054 void vpXmlParserCamera::setCameraName(const std::string &name)
1055 {
1056  m_impl->setCameraName(name);
1057 }
1058 
1059 void vpXmlParserCamera::setHeight(unsigned int height)
1060 {
1061  m_impl->setHeight(height);
1062 }
1063 
1064 void vpXmlParserCamera::setSubsampling_width(unsigned int subsampling)
1065 {
1066  m_impl->setSubsampling_width(subsampling);
1067 }
1068 
1069 void vpXmlParserCamera::setSubsampling_height(unsigned int subsampling)
1070 {
1071  m_impl->setSubsampling_height(subsampling);
1072 }
1073 
1074 void vpXmlParserCamera::setWidth(unsigned int width)
1075 {
1076  m_impl->setWidth(width);
1077 }
1078 
1079 #elif !defined(VISP_BUILD_SHARED_LIBS)
1080 // Work arround to avoid warning: libvisp_core.a(vpXmlParserCamera.cpp.o) has
1081 // no symbols
1082 void dummy_vpXmlParserCamera(){};
1083 #endif // VISP_HAVE_PUGIXML
unsigned int getWidth() const
unsigned int getSubsampling_height() const
double get_kdu() const
vpCameraParametersProjType get_projModel() const
#define vpCERROR
Definition: vpDebug.h:365
#define vpERROR_TRACE
Definition: vpDebug.h:393
void setHeight(unsigned int height)
void setWidth(unsigned int width)
void setCameraName(const std::string &name)
vpCameraParameters getCameraParameters() const
void setSubsampling_height(unsigned int subsampling)
void initPersProjWithDistortion(double px, double py, double u0, double v0, double kud, double kdu)
Generic class defining intrinsic camera parameters.
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, unsigned int image_width=0, unsigned int image_height=0)
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
int save(const vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, unsigned int image_width=0, unsigned int image_height=0, const std::string &additionalInfo="")
std::string getCameraName() const
double get_kud() const
void setSubsampling_width(unsigned int subsampling)
unsigned int getSubsampling_width() const
unsigned int getHeight() const