Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/apps/interactive-calibration/main.cpp
16337 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html.
4
5
#include <opencv2/core.hpp>
6
#include <opencv2/calib3d.hpp>
7
#include <opencv2/cvconfig.h>
8
#include <opencv2/highgui.hpp>
9
10
#ifdef HAVE_OPENCV_ARUCO
11
#include <opencv2/aruco/charuco.hpp>
12
#endif
13
14
#include <string>
15
#include <vector>
16
#include <stdexcept>
17
#include <algorithm>
18
#include <iostream>
19
20
#include "calibCommon.hpp"
21
#include "calibPipeline.hpp"
22
#include "frameProcessor.hpp"
23
#include "calibController.hpp"
24
#include "parametersController.hpp"
25
#include "rotationConverters.hpp"
26
27
using namespace calib;
28
29
const std::string keys =
30
"{v | | Input from video file }"
31
"{ci | 0 | Default camera id }"
32
"{flip | false | Vertical flip of input frames }"
33
"{t | circles | Template for calibration (circles, chessboard, dualCircles, charuco) }"
34
"{sz | 16.3 | Distance between two nearest centers of circles or squares on calibration board}"
35
"{dst | 295 | Distance between white and black parts of daulCircles template}"
36
"{w | | Width of template (in corners or circles)}"
37
"{h | | Height of template (in corners or circles)}"
38
"{of | cameraParameters.xml | Output file name}"
39
"{ft | true | Auto tuning of calibration flags}"
40
"{vis | grid | Captured boards visualisation (grid, window)}"
41
"{d | 0.8 | Min delay between captures}"
42
"{pf | defaultConfig.xml| Advanced application parameters}"
43
"{help | | Print help}";
44
45
bool calib::showOverlayMessage(const std::string& message)
46
{
47
#ifdef HAVE_QT
48
cv::displayOverlay(mainWindowName, message, OVERLAY_DELAY);
49
return true;
50
#else
51
std::cout << message << std::endl;
52
return false;
53
#endif
54
}
55
56
static void deleteButton(int, void* data)
57
{
58
(static_cast<cv::Ptr<calibDataController>*>(data))->get()->deleteLastFrame();
59
calib::showOverlayMessage("Last frame deleted");
60
}
61
62
static void deleteAllButton(int, void* data)
63
{
64
(static_cast<cv::Ptr<calibDataController>*>(data))->get()->deleteAllData();
65
calib::showOverlayMessage("All frames deleted");
66
}
67
68
static void saveCurrentParamsButton(int, void* data)
69
{
70
if((static_cast<cv::Ptr<calibDataController>*>(data))->get()->saveCurrentCameraParameters())
71
calib::showOverlayMessage("Calibration parameters saved");
72
}
73
74
#ifdef HAVE_QT
75
static void switchVisualizationModeButton(int, void* data)
76
{
77
ShowProcessor* processor = static_cast<ShowProcessor*>(((cv::Ptr<FrameProcessor>*)data)->get());
78
processor->switchVisualizationMode();
79
}
80
81
static void undistortButton(int state, void* data)
82
{
83
ShowProcessor* processor = static_cast<ShowProcessor*>(((cv::Ptr<FrameProcessor>*)data)->get());
84
processor->setUndistort(static_cast<bool>(state));
85
calib::showOverlayMessage(std::string("Undistort is ") +
86
(static_cast<bool>(state) ? std::string("on") : std::string("off")));
87
}
88
#endif //HAVE_QT
89
90
int main(int argc, char** argv)
91
{
92
cv::CommandLineParser parser(argc, argv, keys);
93
if(parser.has("help")) {
94
parser.printMessage();
95
return 0;
96
}
97
std::cout << consoleHelp << std::endl;
98
parametersController paramsController;
99
100
if(!paramsController.loadFromParser(parser))
101
return 0;
102
103
captureParameters capParams = paramsController.getCaptureParameters();
104
internalParameters intParams = paramsController.getInternalParameters();
105
#ifndef HAVE_OPENCV_ARUCO
106
if(capParams.board == chAruco)
107
CV_Error(cv::Error::StsNotImplemented, "Aruco module is disabled in current build configuration."
108
" Consider usage of another calibration pattern\n");
109
#endif
110
111
cv::TermCriteria solverTermCrit = cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS,
112
intParams.solverMaxIters, intParams.solverEps);
113
cv::Ptr<calibrationData> globalData(new calibrationData);
114
if(!parser.has("v")) globalData->imageSize = capParams.cameraResolution;
115
116
int calibrationFlags = 0;
117
if(intParams.fastSolving) calibrationFlags |= cv::CALIB_USE_QR;
118
cv::Ptr<calibController> controller(new calibController(globalData, calibrationFlags,
119
parser.get<bool>("ft"), capParams.minFramesNum));
120
cv::Ptr<calibDataController> dataController(new calibDataController(globalData, capParams.maxFramesNum,
121
intParams.filterAlpha));
122
dataController->setParametersFileName(parser.get<std::string>("of"));
123
124
cv::Ptr<FrameProcessor> capProcessor, showProcessor;
125
capProcessor = cv::Ptr<FrameProcessor>(new CalibProcessor(globalData, capParams));
126
showProcessor = cv::Ptr<FrameProcessor>(new ShowProcessor(globalData, controller, capParams.board));
127
128
if(parser.get<std::string>("vis").find("window") == 0) {
129
static_cast<ShowProcessor*>(showProcessor.get())->setVisualizationMode(Window);
130
cv::namedWindow(gridWindowName);
131
cv::moveWindow(gridWindowName, 1280, 500);
132
}
133
134
cv::Ptr<CalibPipeline> pipeline(new CalibPipeline(capParams));
135
std::vector<cv::Ptr<FrameProcessor> > processors;
136
processors.push_back(capProcessor);
137
processors.push_back(showProcessor);
138
139
cv::namedWindow(mainWindowName);
140
cv::moveWindow(mainWindowName, 10, 10);
141
#ifdef HAVE_QT
142
cv::createButton("Delete last frame", deleteButton, &dataController,
143
cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR);
144
cv::createButton("Delete all frames", deleteAllButton, &dataController,
145
cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR);
146
cv::createButton("Undistort", undistortButton, &showProcessor,
147
cv::QT_CHECKBOX | cv::QT_NEW_BUTTONBAR, false);
148
cv::createButton("Save current parameters", saveCurrentParamsButton, &dataController,
149
cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR);
150
cv::createButton("Switch visualisation mode", switchVisualizationModeButton, &showProcessor,
151
cv::QT_PUSH_BUTTON | cv::QT_NEW_BUTTONBAR);
152
#endif //HAVE_QT
153
try {
154
bool pipelineFinished = false;
155
while(!pipelineFinished)
156
{
157
PipelineExitStatus exitStatus = pipeline->start(processors);
158
if (exitStatus == Finished) {
159
if(controller->getCommonCalibrationState())
160
saveCurrentParamsButton(0, &dataController);
161
pipelineFinished = true;
162
continue;
163
}
164
else if (exitStatus == Calibrate) {
165
166
dataController->rememberCurrentParameters();
167
globalData->imageSize = pipeline->getImageSize();
168
calibrationFlags = controller->getNewFlags();
169
170
if(capParams.board != chAruco) {
171
globalData->totalAvgErr =
172
cv::calibrateCamera(globalData->objectPoints, globalData->imagePoints,
173
globalData->imageSize, globalData->cameraMatrix,
174
globalData->distCoeffs, cv::noArray(), cv::noArray(),
175
globalData->stdDeviations, cv::noArray(), globalData->perViewErrors,
176
calibrationFlags, solverTermCrit);
177
}
178
else {
179
#ifdef HAVE_OPENCV_ARUCO
180
cv::Ptr<cv::aruco::Dictionary> dictionary =
181
cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(capParams.charucoDictName));
182
cv::Ptr<cv::aruco::CharucoBoard> charucoboard =
183
cv::aruco::CharucoBoard::create(capParams.boardSize.width, capParams.boardSize.height,
184
capParams.charucoSquareLenght, capParams.charucoMarkerSize, dictionary);
185
globalData->totalAvgErr =
186
cv::aruco::calibrateCameraCharuco(globalData->allCharucoCorners, globalData->allCharucoIds,
187
charucoboard, globalData->imageSize,
188
globalData->cameraMatrix, globalData->distCoeffs,
189
cv::noArray(), cv::noArray(), globalData->stdDeviations, cv::noArray(),
190
globalData->perViewErrors, calibrationFlags, solverTermCrit);
191
#endif
192
}
193
dataController->updateUndistortMap();
194
dataController->printParametersToConsole(std::cout);
195
controller->updateState();
196
for(int j = 0; j < capParams.calibrationStep; j++)
197
dataController->filterFrames();
198
static_cast<ShowProcessor*>(showProcessor.get())->updateBoardsView();
199
}
200
else if (exitStatus == DeleteLastFrame) {
201
deleteButton(0, &dataController);
202
static_cast<ShowProcessor*>(showProcessor.get())->updateBoardsView();
203
}
204
else if (exitStatus == DeleteAllFrames) {
205
deleteAllButton(0, &dataController);
206
static_cast<ShowProcessor*>(showProcessor.get())->updateBoardsView();
207
}
208
else if (exitStatus == SaveCurrentData) {
209
saveCurrentParamsButton(0, &dataController);
210
}
211
else if (exitStatus == SwitchUndistort)
212
static_cast<ShowProcessor*>(showProcessor.get())->switchUndistort();
213
else if (exitStatus == SwitchVisualisation)
214
static_cast<ShowProcessor*>(showProcessor.get())->switchVisualizationMode();
215
216
for (std::vector<cv::Ptr<FrameProcessor> >::iterator it = processors.begin(); it != processors.end(); ++it)
217
(*it)->resetState();
218
}
219
}
220
catch (const std::runtime_error& exp) {
221
std::cout << exp.what() << std::endl;
222
}
223
224
return 0;
225
}
226
227