main.cpp 10 KB

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