Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / samples / validation_app / VOCAnnotationParser.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <sstream>
6 #include <exception>
7 #include <string>
8 #include <list>
9
10 #include "VOCAnnotationParser.hpp"
11
12 #include "user_exception.hpp"
13
14 std::string VOCAnnotationParser::parseString(const pugi::xml_node& node, const std::string& def) {
15     if (node && node.child_value()) {
16         return node.child_value();
17     } else {
18         return def;
19     }
20 }
21
22 int VOCAnnotationParser::parseInt(const pugi::xml_node& node, const int def) {
23     if (!node) return def;
24     std::string val = parseString(node);
25     try {
26         return std::stoi(val);
27     } catch (const std::invalid_argument&) {
28         THROW_USER_EXCEPTION(1) << "Can't convert node <" << node.name()
29             << "> value \"" << val << "\" to integer";
30     }
31 }
32
33 bool VOCAnnotationParser::parseBool(const pugi::xml_node& node, bool def) {
34     if (!node) return def;
35     std::string val = parseString(node);
36     if (val == "1") return true;
37     if (val == "0") return false;
38
39     THROW_USER_EXCEPTION(1) << "Can't convert node <" << node.name()
40         << "> value \"" << val << "\" to boolean";
41 }
42
43
44 VOCAnnotation VOCAnnotationParser::parse(const std::string& filename) {
45     using namespace pugi;
46     xml_document doc;
47
48     xml_parse_result result = doc.load_file(filename.c_str());
49
50     if (result.status != pugi::status_ok) {
51         throw UserException(result.status)
52                 << "parsing failed at offset " << result.offset << ": " << result.description();
53     }
54
55     xml_node annNode = doc.child("annotation");
56     if (!annNode) {
57         THROW_USER_EXCEPTION(1) << "No root <annotation> tag";
58     }
59     VOCAnnotation ann;
60
61     try {
62         ann.filename = parseString(annNode.child("filename"));
63         ann.folder = parseString(annNode.child("folder"));
64         ann.segmented = parseBool(annNode.child("segmented"));
65
66         xml_node sizeNode = annNode.child("size");
67         ann.size.depth = parseInt(sizeNode.child("depth"));
68         ann.size.height = parseInt(sizeNode.child("height"));
69         ann.size.width = parseInt(sizeNode.child("width"));
70
71         xml_node sourceNode = annNode.child("source");
72         ann.source.annotation = parseString(sourceNode.child("annotation"));
73         ann.source.database = parseString(sourceNode.child("database"));
74         ann.source.image = parseString(sourceNode.child("image"));
75
76
77         for (xml_node objNode = annNode.child("object"); objNode; objNode = objNode.next_sibling("object")) {
78             VOCObject obj;
79             obj.name = parseString(objNode.child("name"));
80             obj.difficult = parseBool(objNode.child("difficult"));
81             obj.occluded = parseBool(objNode.child("occluded"));
82             obj.pose = parseString(objNode.child("pose"));
83             obj.truncated = parseBool(objNode.child("truncated"));
84
85             xml_node bndboxNode = objNode.child("bndbox");
86             obj.bndbox.xmin = parseInt(bndboxNode.child("xmin"));
87             obj.bndbox.xmax = parseInt(bndboxNode.child("xmax"));
88             obj.bndbox.ymin = parseInt(bndboxNode.child("ymin"));
89             obj.bndbox.ymax = parseInt(bndboxNode.child("ymax"));
90
91             ann.objects.push_back(obj);
92         }
93     }
94     catch (const std::invalid_argument& e) {
95         THROW_USER_EXCEPTION(1) << "conversion error: " << e.what();
96     }
97
98     return ann;
99 }
100
101 VOCAnnotationParser::~VOCAnnotationParser() {
102 }
103
104 inline bool ends_with(std::string const & value, std::string const & ending) {
105     if (ending.size() > value.size()) return false;
106     return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
107 }
108
109 VOCAnnotationCollector::VOCAnnotationCollector(const std::string& path) {
110     VOCAnnotationParser parser;
111     if (ends_with(path, ".xml")) {
112         // A single file
113         _annotations.push_back(parser.parse(path));
114     } else {
115         std::list<std::string> baseDirContents = getDirContents(path, true);
116         for (const auto& sub : baseDirContents) {
117             std::list<std::string> annotationDirContents = getDirContents(sub, true);
118             if (annotationDirContents.size() == 0 && ends_with(sub, ".xml")) {
119                 _annotations.push_back(parser.parse(sub));
120             } else {
121                 for (const auto& file : annotationDirContents) {
122                     if (ends_with(file, ".xml")) {
123                         _annotations.push_back(parser.parse(file));
124                     }
125                 }
126             }
127         }
128     }
129 }
130