HoviTron Video Pipeline
Config.cpp
1/* The copyright in this software is being made available under the BSD
2* License, included below. This software may be subject to other third party
3* and contributor rights, including patent rights, and no such rights are
4* granted under this license.
5*
6* Copyright (c) 2010-2018, ITU/ISO/IEC
7* All rights reserved.
8*
9* Redistribution and use in source and binary forms, with or without
10* modification, are permitted provided that the following conditions are met:
11*
12* * Redistributions of source code must retain the above copyright notice,
13* this list of conditions and the following disclaimer.
14* * Redistributions in binary form must reproduce the above copyright notice,
15* this list of conditions and the following disclaimer in the documentation
16* and/or other materials provided with the distribution.
17* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18* be used to endorse or promote products derived from this software without
19* specific prior written permission.
20*
21* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31* THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
34/*
35Original authors:
36
37Universite Libre de Bruxelles, Brussels, Belgium:
38 Sarah Fachada, Sarah.Fernandes.Pinto.Fachada@ulb.ac.be
39 Daniele Bonatto, Daniele.Bonatto@ulb.ac.be
40 Arnaud Schenkel, arnaud.schenkel@ulb.ac.be
41
42Koninklijke Philips N.V., Eindhoven, The Netherlands:
43 Bart Kroon, bart.kroon@philips.com
44 Bart Sonneveldt, bart.sonneveldt@philips.com
45*/
46
47#include "../include/Config.h"
48#include "../include/JsonParser.h"
49
50#include <fstream>
51#include <iostream>
52#include <sstream>
53#include <map>
54
55
56namespace rvs
57{
58 bool g_verbose = false;
59
60 namespace detail
61 {
62 float const defaultPrecision = 1.f;
63 ColorSpace const defaultColorSpace = ColorSpace::RGB;
64
65 float g_rescale = defaultPrecision;
66 ColorSpace g_color_space = defaultColorSpace;
67 }
68
69 bool g_with_opengl = true;
70
71
72 Config Config::loadFromFile(std::string const& filename, std::string const& dir)
73 {
74 if(g_verbose)
75 std::cout << '\n';
76 std::string path = filename;
77 if (!dir.empty()) {
78 path = dir + '/' + filename;
79 }
80 std::ifstream stream(path);
81
82 if (!stream.good()) {
83 std::ostringstream what;
84 what << "Failed to open configuration file \"" << dir + '/' + filename << "\" for reading: \n" << strerror(errno);
85 throw std::runtime_error(what.str());
86 }
87 auto root = json::Node::readFrom(stream);
88
89 Config config;
90
91 config.directory = dir;
92
93 config.setVersionFrom(root);
94 config.setInputCameraNamesFrom(root);
95 config.setVirtualCameraNamesFrom(root);
96 config.setInputCameraParameters(root);
97 config.setVirtualCameraParameters(root);
98 config.setInputFilepaths(root, "ViewImageNames", config.texture_names);
99 config.setInputFilepaths(root, "DepthMapNames", config.depth_names);
100 config.setOutputFilepaths(root, "OutputFiles", config.outfilenames);
101 config.setOutputFilepaths(root, "MaskedOutputFiles", config.outmaskedfilenames);
102 config.setOutputFilepaths(root, "OutputMasks", config.outmaskfilenames);
103 config.setOutputFilepaths(root, "DepthOutputFiles", config.outdepthfilenames);
104 config.setOutputFilepaths(root, "MaskedDepthOutputFiles", config.outmaskdepthfilenames);
105 config.setValidityThreshold(root);
106 config.setSynthesisMethod(root);
107 config.setBlendingMethod(root);
108 config.setBlendingFactor(root);
109 config.setBlendingLowFreqFactor(root);
110 config.setBlendingHighFreqFactor(root);
111 config.setStartFrame(root);
112 config.setNumberOfFrames(root);
113
114 setPrecision(root);
115 setColorSpace(root);
116
117 auto node = root.optional("VirtualPoseTraceName");
118 if (node) {
119 auto filepath = node.asString();
120 if(g_verbose)
121 std::cout << "VirtualPoseTraceName: " << filepath << '\n';
122 //config.loadPoseTraceFromFile(filepath);
123 }
124
125 config.setOverrideVirtualViewSetting(root);
126
127 return config;
128 }
129
130 void Config::setOverrideVirtualViewSetting(json::Node root)
131 {
132 auto node = root.optional("OverrideVirtualSetting");
133 if (node.type() == json::Node::Type::boolean) {
134 overrideVirtualViewSetting = node.asBool();
135 }
136 }
137
138 std::vector<Parameters> Config::loadCamerasParametersFromFile(std::string const& file, std::vector<std::string> names, json::Node overrides)
139 {
140 std::string const& filepath = this->directory + '/'+ file;
141 // Load the camera parameters
142 std::ifstream stream(filepath);
143 if (!stream.good()) {
144 std::ostringstream what;
145 what << "Failed to open camera parameters file \"" << filepath << "\" for reading \n" << strerror(errno) ;
146 throw std::runtime_error(what.str());
147 }
148 auto root = json::Node::readFrom(stream);
149 auto version_ = root.require("Version").asString();
150 if (version_.substr(0, 2) != "2." &&
151 version_.substr(0, 2) != "3.") {
152 throw std::runtime_error("Version of the camera parameters file is not compatible with this version of RVS");
153 }
154
155 // Load parameters (with overrides) and index by camera name
156 std::map<std::string, Parameters> index;
157 auto cameras = root.require("cameras");
158 for (auto i = 0u; i != cameras.size(); ++i) {
159 auto node = cameras.at(i);
160 auto name = node.require("Name").asString();
161 if (index.count(name)) {
162 std::ostringstream what;
163 what << "Camera parameters file has duplicate camera '" << name << "'";
164 throw std::runtime_error(what.str());
165 }
166 if (overrides) {
167 node.setOverrides(overrides);
168 }
169 index.emplace(name, Parameters::readFrom(node));
170 }
171
172 // Assign in the requested order
173 std::vector<Parameters> parameters;
174 for (auto name : names) {
175 try {
176 if (g_verbose)
177 {
178 std::cout << " * " << name << ": ";
179 index.at(name).printTo(std::cout);
180 std::cout << '\n';
181 }
182 parameters.push_back(index.at(name));
183 }
184 catch (std::out_of_range&) {
185 std::ostringstream what;
186 what << "Camera parameters file does not have camera '" << name << "'";
187 throw std::runtime_error(what.str());
188 }
189 }
190 return parameters;
191 }
192
193 /*
194 void Config::loadPoseTraceFromFile(std::string const& filepath)
195 {
196 if (!filepath.empty()) {
197 pose_trace = PoseTrace::loadFromFile(filepath);
198 if (static_cast<unsigned>(start_frame + number_of_frames) > pose_trace.size()) {
199 throw std::runtime_error("Error: Number of frames to process is larger then number of entries in pose trace file");
200 }
201 if (g_verbose)
202 std::cout << std::endl << "Using pose trace with " << pose_trace.size() << " entries" << std::endl;
203 }
204 }*/
205
206 void Config::setVersionFrom(json::Node root)
207 {
208 version = root.require("Version").asString();
209 if (version.substr(0, 2) != "2." &&
210 version.substr(0, 2) != "3.") {
211 throw std::runtime_error("Configuration file does not match the RVS version");
212 }
213 if (g_verbose)
214 std::cout << "Version: " << version << '\n';
215 }
216
217 void Config::setInputCameraNamesFrom(json::Node root)
218 {
219 auto node = root.require("InputCameraNames");
220 for (auto i = 0u; i != node.size(); ++i) {
221 InputCameraNames.push_back(node.at(i).asString());
222 }
223 if (g_verbose)
224 {
225 std::cout << "InputCameraNames:";
226 for (auto x : InputCameraNames) {
227 std::cout << ' ' << x;
228 }
229 std::cout << '\n';
230 }
231 }
232
233 void Config::setVirtualCameraNamesFrom(json::Node root)
234 {
235 auto node = root.require("VirtualCameraNames");
236 for (auto i = 0u; i != node.size(); ++i) {
237 VirtualCameraNames.push_back(node.at(i).asString());
238 }
239 if (g_verbose)
240 {
241 std::cout << "VirtualCameraNames:";
242 for (auto x : VirtualCameraNames) {
243 std::cout << ' ' << x;
244 }
245 std::cout << '\n';
246 }
247 }
248
249 void Config::setInputCameraParameters(json::Node root)
250 {
251 auto filepath = root.require("InputCameraParameterFile").asString();
252 if (g_verbose)
253 std::cout << "InputCameraParameterFile: " << filepath << '\n';
254 auto overrides = root.optional("InputOverrides");
255 if (overrides) {
256 if (g_verbose)
257 std::cout << "InputOverrides: " << overrides.size() << " keys\n";
258 }
259 params_real = loadCamerasParametersFromFile(filepath, InputCameraNames, overrides);
260 }
261
262 void Config::setVirtualCameraParameters(json::Node root)
263 {
264 auto filepath = root.require("VirtualCameraParameterFile").asString();
265 if (g_verbose)
266 std::cout << "VirtualCameraParameterFile: " << filepath << '\n';
267 auto overrides = root.optional("VirtualOverrides");
268 if (overrides) {
269 if (g_verbose)
270 std::cout << "VirtualOverrides: " << overrides.size() << " keys\n";
271 }
272 params_virtual = loadCamerasParametersFromFile(filepath, VirtualCameraNames, overrides);
273 }
274
275 void Config::setInputFilepaths(json::Node root, char const *name, std::vector<std::string>& filepaths)
276 {
277 auto node = root.require(name);
278 if (node.size() != InputCameraNames.size()) {
279 std::ostringstream what;
280 what << "Length of " << name << " should match with InputCameraNames";
281 throw std::runtime_error(what.str());
282 }
283 for (auto i = 0u; i != node.size(); ++i) {
284 filepaths.push_back(node.at(i).asString());
285 }
286 if (g_verbose)
287 {
288 std::cout << name << ':';
289 for (auto x : filepaths) {
290 std::cout << "\n * " << x;
291 }
292 std::cout << '\n';
293 }
294 }
295
296 void Config::setOutputFilepaths(json::Node root, char const *name, std::vector<std::string>& filepaths)
297 {
298 auto node = root.optional(name);
299 if (node) {
300 if (node.size() != VirtualCameraNames.size()) {
301 std::ostringstream what;
302 what << "Length of " << name << " should match with VirtualCameraNames";
303 throw std::runtime_error(what.str());
304 }
305 for (auto i = 0u; i != node.size(); ++i) {
306 filepaths.push_back(node.at(i).asString());
307 }
308 if (g_verbose)
309 {
310 std::cout << name << ':';
311 for (auto x : filepaths) {
312 std::cout << "\n * " << x;
313 }
314 std::cout << '\n';
315 }
316 }
317 }
318
319 void Config::setValidityThreshold(json::Node root)
320 {
321 auto node = root.optional("ValidityThreshold");
322 if (node) {
323 validity_threshold = static_cast<float>(node.asDouble());
324 if (g_verbose)
325 std::cout << "ValidityThreshold: " << validity_threshold << '\n';
326 }
327 }
328
329 void Config::setSynthesisMethod(json::Node root)
330 {
331 auto node = root.optional("ViewSynthesisMethod");
332 if (node) {
333 vs_method = node.asString();
334 }
335 }
336
337 void Config::setBlendingMethod(json::Node root)
338 {
339 auto node = root.optional("BlendingMethod");
340 if (node) {
341 blending_method = node.asString();
342 if (g_verbose)
343 std::cout << "BlendingMethod: " << blending_method << '\n';
344 }
345 }
346
347 void Config::setBlendingFactor(json::Node root)
348 {
349 auto node = root.optional("BlendingFactor");
350 if (node) {
351 blending_factor = static_cast<float>(node.asDouble());
352 if (g_verbose)
353 std::cout << "BlendingFactor: " << blending_factor << '\n';
354 }
355 }
356
357 void Config::setBlendingLowFreqFactor(json::Node root)
358 {
359 if (blending_method == BlendingMethod::multispectral) {
360 blending_low_freq_factor = static_cast<float>(root.require("BlendingLowFreqFactor").asDouble());
361 if (g_verbose)
362 std::cout << "BlendingLowFreqFactor: " << blending_low_freq_factor << '\n';
363 }
364 }
365
366 void Config::setBlendingHighFreqFactor(json::Node root)
367 {
368 if (blending_method == BlendingMethod::multispectral) {
369 blending_high_freq_factor = static_cast<float>(root.require("BlendingHighFreqFactor").asDouble());
370 if (g_verbose)
371 std::cout << "BlendingHighFreqFactor: " << blending_high_freq_factor << '\n';
372 }
373 }
374
375 void Config::setStartFrame(json::Node root)
376 {
377 auto node = root.optional("StartFrame");
378 if (node) {
379 start_frame = node.asInt();
380 if (g_verbose)
381 std::cout << "StartFrame: " << start_frame << '\n';
382 }
383 }
384
385 void Config::setNumberOfFrames(json::Node root)
386 {
387 auto node = root.optional("NumberOfFrames");
388 if (node) {
389 number_of_frames = node.asInt();
390 if (g_verbose)
391 std::cout << "NumberOfFrames: " << number_of_frames << '\n';
392 }
393 }
394
395 void Config::setPrecision(json::Node root)
396 {
397 auto node = root.optional("Precision");
398 if (node) {
399 detail::g_rescale = static_cast<float>(node.asDouble());
400 if (g_verbose)
401 std::cout << "Precision: " << detail::g_rescale << '\n';
402 }
403 else {
404 detail::g_rescale = detail::defaultPrecision;
405 }
406 }
407
408 void Config::setColorSpace(json::Node root)
409 {
410 auto node = root.optional("ColorSpace");
411 if (node) {
412 if (node.asString() == "YUV") {
413 detail::g_color_space = detail::ColorSpace::YUV;
414 if (g_verbose)
415 std::cout << "ColorSpace: YUV\n";
416 }
417 else if (node.asString() == "RGB") {
418 detail::g_color_space = detail::ColorSpace::RGB;
419 if (g_verbose)
420 std::cout << "ColorSpace: RGB\n";
421 }
422 else {
423 throw std::runtime_error("Unknown color space");
424 }
425 }
426 else {
427 detail::g_color_space = detail::defaultColorSpace;
428 }
429 }
430}
Node optional(std::string const &key) const
Definition: JsonParser.cpp:238
std::size_t size() const
Definition: JsonParser.cpp:277
std::string const & asString() const
Definition: JsonParser.cpp:314
double asDouble() const
Definition: JsonParser.cpp:290
Node require(std::string const &key) const
Definition: JsonParser.cpp:259
Node at(std::size_t index) const
Definition: JsonParser.cpp:269
static Node readFrom(std::istream &)
Definition: JsonParser.cpp:203
Configuration parameters.
Definition: Config.h:112
float blending_low_freq_factor
Definition: Config.h:163
std::vector< std::string > outdepthfilenames
Definition: Config.h:148
int number_of_frames
Definition: Config.h:175
static Config loadFromFile(std::string const &filename, std::string const &dir)
Definition: Config.cpp:72
std::vector< Parameters > params_real
Definition: Config.h:127
std::vector< std::string > outfilenames
Definition: Config.h:139
std::string directory
Definition: Config.h:181
float blending_high_freq_factor
Definition: Config.h:166
std::string vs_method
Definition: Config.h:157
std::vector< std::string > outmaskedfilenames
Definition: Config.h:142
float validity_threshold
Definition: Config.h:154
int start_frame
Definition: Config.h:172
std::vector< std::string > outmaskdepthfilenames
Definition: Config.h:151
std::vector< std::string > outmaskfilenames
Definition: Config.h:145
bool overrideVirtualViewSetting
Definition: Config.h:184
std::vector< std::string > VirtualCameraNames
Definition: Config.h:124
std::vector< std::string > InputCameraNames
Definition: Config.h:121
std::vector< std::string > depth_names
Definition: Config.h:136
std::vector< std::string > texture_names
Definition: Config.h:133
float blending_factor
Definition: Config.h:169
std::string version
Definition: Config.h:118
std::vector< Parameters > params_virtual
Definition: Config.h:130
std::string blending_method
Definition: Config.h:160
static Parameters readFrom(json::Node parameters)
Definition: Parameters.cpp:62