1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm
#include "calibrationOnlineAlgorithm.hpp"
#include "calibration.hpp"
#include "cvImage.hpp"
#include "calibrationProgress.hpp"
#include "core/controllerInputFrames.hpp"
#include "util/registeredAlgo.hpp"
#include "cuda/memory.hpp"
#include "gpu/surface.hpp"
#include "libvideostitch/logging.hpp"
#include "libvideostitch/parse.hpp"
#include "libvideostitch/rigDef.hpp"
#include <memory>
#include <functional>
namespace VideoStitch {
namespace Calibration {
namespace {
Util::RegisteredAlgo<CalibrationOnlineAlgorithm, true> registeredOnline("calibration");
}
const char* CalibrationOnlineAlgorithm::docString =
"An algorithm that calibrates a panoramic multi-camera system using overlap zones between images\n";
CalibrationOnlineAlgorithm::CalibrationOnlineAlgorithm(const Ptv::Value* config) : CalibrationAlgorithmBase(config) {}
CalibrationOnlineAlgorithm::~CalibrationOnlineAlgorithm() {}
Status CalibrationOnlineAlgorithm::retrieveImages(
RigCvImages& rig, const Core::PanoDefinition& pano,
const std::vector<std::pair<videoreaderid_t, GPU::Surface&>>& frames) const {
/*Create rig of n list*/
rig.clear();
rig.resize(pano.numVideoInputs());
/* With non-video inputs, assume we can have gaps between camid and inputid */
auto videoInputs = pano.getVideoInputs();
for (auto it = frames.begin(); it != frames.end(); ++it) {
int camid = it->first;
if (camid >= (int)pano.numInputs() || camid >= (int)videoInputs.size()) {
return {Origin::CalibrationAlgorithm, ErrType::InvalidConfiguration,
"Invalid input configuration, could not retrieve calibration frames"};
}
std::shared_ptr<CvImage> cvinput;
// Get the size of the current image
const Core::InputDefinition& idef = videoInputs[camid];
const int width = (int)idef.getWidth();
const int height = (int)idef.getHeight();
FAIL_RETURN(loadInputImage(cvinput, it->second, width, height));
rig[camid].push_back(cvinput);
}
return Status::OK();
}
Potential<Ptv::Value> CalibrationOnlineAlgorithm::onFrame(
Core::PanoDefinition& pano, std::vector<std::pair<videoreaderid_t, GPU::Surface&>>& frames, mtime_t /*date*/,
FrameRate /*frameRate*/, Util::OpaquePtr** ctx) {
/*Validate configuration*/
if (!calibConfig.isValid()) {
// TODOLATERSTATUS get output from CalibrationConfig parsing
return {Origin::CalibrationAlgorithm, ErrType::InvalidConfiguration, "Invalid calibration configuration"};
}
if (calibConfig.getRigPreset()->getRigCameraDefinitionCount() != (size_t)pano.numVideoInputs()) {
return {Origin::CalibrationAlgorithm, ErrType::InvalidConfiguration,
"Calibration camera presets not matching the number of video inputs"};
}
/*
* Retrieve the control point manager, passed as an opaque pointer from the client
* or create a new one if no cp manager was passed
*/
CalibrationProgress calibProgress(nullptr, getProgressUnits(pano.numVideoInputs(), 1));
/*Perform calibration*/
std::unique_ptr<Calibration, std::function<void(Calibration*)>> calibrationAlgorithm;
if (ctx == nullptr) {
calibrationAlgorithm = std::unique_ptr<Calibration, std::function<void(Calibration*)>>(
new Calibration(calibConfig, calibProgress), [](Calibration* data) { delete data; });
} else {
if (*ctx == nullptr) {
*ctx = new Calibration(calibConfig, calibProgress);
}
calibrationAlgorithm = std::unique_ptr<Calibration, std::function<void(Calibration*)>>(
dynamic_cast<Calibration*>(*ctx), [](Calibration*) {});
}
RigCvImages rig;
if (!calibConfig.isApplyingPresetsOnly()) {
/*Load images onto cpu*/
FAIL_RETURN(retrieveImages(rig, pano, frames));
}
return calibrationAlgorithm->process(pano, rig);
}
} // namespace Calibration
} // namespace VideoStitch