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