From 533bb035cfac6b32d8cb94009202df0c13b65e09 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 8 Jun 2022 13:59:55 +0300 Subject: [PATCH] Save Frames option for interactive calibration tool The option to save all frames that contribute to final calibration result. Useful for dataset collection and further offline tuning. --- apps/interactive-calibration/calibCommon.hpp | 4 ++++ apps/interactive-calibration/calibController.cpp | 14 ++++++++++++++ apps/interactive-calibration/frameProcessor.cpp | 9 +++++++++ apps/interactive-calibration/frameProcessor.hpp | 1 + apps/interactive-calibration/main.cpp | 1 + .../parametersController.cpp | 1 + 6 files changed, 30 insertions(+) diff --git a/apps/interactive-calibration/calibCommon.hpp b/apps/interactive-calibration/calibCommon.hpp index f422ff0531..617c17dbcf 100644 --- a/apps/interactive-calibration/calibCommon.hpp +++ b/apps/interactive-calibration/calibCommon.hpp @@ -45,6 +45,8 @@ namespace calib double totalAvgErr; cv::Size imageSize; + std::vector allFrames; + std::vector > imagePoints; std::vector< std::vector > objectPoints; @@ -91,6 +93,7 @@ namespace calib cv::Size cameraResolution; int maxFramesNum; int minFramesNum; + bool saveFrames; captureParameters() { @@ -100,6 +103,7 @@ namespace calib minFramesNum = 10; fps = 30; cameraResolution = cv::Size(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT); + saveFrames = false; } }; diff --git a/apps/interactive-calibration/calibController.cpp b/apps/interactive-calibration/calibController.cpp index efe937bfd9..9efb9d054a 100644 --- a/apps/interactive-calibration/calibController.cpp +++ b/apps/interactive-calibration/calibController.cpp @@ -10,6 +10,7 @@ #include #include +#include double calib::calibController::estimateCoverageQuality() { @@ -212,6 +213,9 @@ void calib::calibDataController::filterFrames() } showOverlayMessage(cv::format("Frame %zu is worst", worstElemIndex + 1)); + if(mCalibData->allFrames.size()) + mCalibData->allFrames.erase(mCalibData->allFrames.begin() + worstElemIndex); + if(mCalibData->imagePoints.size()) { mCalibData->imagePoints.erase(mCalibData->imagePoints.begin() + worstElemIndex); mCalibData->objectPoints.erase(mCalibData->objectPoints.begin() + worstElemIndex); @@ -239,6 +243,11 @@ void calib::calibDataController::setParametersFileName(const std::string &name) void calib::calibDataController::deleteLastFrame() { + if(!mCalibData->allFrames.empty()) + { + mCalibData->allFrames.pop_back(); + } + if( !mCalibData->imagePoints.empty()) { mCalibData->imagePoints.pop_back(); mCalibData->objectPoints.pop_back(); @@ -269,6 +278,7 @@ void calib::calibDataController::rememberCurrentParameters() void calib::calibDataController::deleteAllData() { + mCalibData->allFrames.clear(); mCalibData->imagePoints.clear(); mCalibData->objectPoints.clear(); mCalibData->allCharucoCorners.clear(); @@ -280,6 +290,10 @@ void calib::calibDataController::deleteAllData() bool calib::calibDataController::saveCurrentCameraParameters() const { + + for(size_t i = 0; i < mCalibData->allFrames.size(); i++) + cv::imwrite(cv::format("calibration_%zu.png", i), mCalibData->allFrames[i]); + bool success = false; if(mCalibData->cameraMatrix.total()) { cv::FileStorage parametersWriter(mParamsFileName, cv::FileStorage::WRITE); diff --git a/apps/interactive-calibration/frameProcessor.cpp b/apps/interactive-calibration/frameProcessor.cpp index 90904a42cd..2c2a1cd5aa 100644 --- a/apps/interactive-calibration/frameProcessor.cpp +++ b/apps/interactive-calibration/frameProcessor.cpp @@ -266,6 +266,7 @@ CalibProcessor::CalibProcessor(cv::Ptr data, captureParameters static_cast(mCalibData->imageSize.width * mCalibData->imageSize.width)) / 20.0; mSquareSize = capParams.squareSize; mTemplDist = capParams.templDst; + mSaveFrames = capParams.saveFrames; switch(mBoardType) { @@ -291,10 +292,14 @@ CalibProcessor::CalibProcessor(cv::Ptr data, captureParameters cv::Mat CalibProcessor::processFrame(const cv::Mat &frame) { cv::Mat frameCopy; + cv::Mat frameCopyToSave; frame.copyTo(frameCopy); bool isTemplateFound = false; mCurrentImagePoints.clear(); + if(mSaveFrames) + frame.copyTo(frameCopyToSave); + switch(mBoardType) { case Chessboard: @@ -322,6 +327,10 @@ cv::Mat CalibProcessor::processFrame(const cv::Mat &frame) mCalibData->allCharucoCorners.size())); if(!showOverlayMessage(displayMessage)) showCaptureMessage(frame, displayMessage); + + if(mSaveFrames) + mCalibData->allFrames.push_back(frameCopyToSave); + mCapuredFrames++; } else { diff --git a/apps/interactive-calibration/frameProcessor.hpp b/apps/interactive-calibration/frameProcessor.hpp index 6fd788dc7f..88e87f7b98 100644 --- a/apps/interactive-calibration/frameProcessor.hpp +++ b/apps/interactive-calibration/frameProcessor.hpp @@ -50,6 +50,7 @@ protected: double mMaxTemplateOffset; float mSquareSize; float mTemplDist; + bool mSaveFrames; bool detectAndParseChessboard(const cv::Mat& frame); bool detectAndParseChAruco(const cv::Mat& frame); diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp index 6468c88ce7..b5c3642bb6 100644 --- a/apps/interactive-calibration/main.cpp +++ b/apps/interactive-calibration/main.cpp @@ -40,6 +40,7 @@ const std::string keys = "{vis | grid | Captured boards visualisation (grid, window)}" "{d | 0.8 | Min delay between captures}" "{pf | defaultConfig.xml| Advanced application parameters}" + "{save_frames | false | Save frames that contribute to final calibration}" "{help | | Print help}"; bool calib::showOverlayMessage(const std::string& message) diff --git a/apps/interactive-calibration/parametersController.cpp b/apps/interactive-calibration/parametersController.cpp index 3bcf5b86e9..5659b0e469 100644 --- a/apps/interactive-calibration/parametersController.cpp +++ b/apps/interactive-calibration/parametersController.cpp @@ -89,6 +89,7 @@ bool calib::parametersController::loadFromParser(cv::CommandLineParser &parser) mCapParams.captureDelay = parser.get("d"); mCapParams.squareSize = parser.get("sz"); mCapParams.templDst = parser.get("dst"); + mCapParams.saveFrames = parser.has("save_frames"); if(!checkAssertion(mCapParams.squareSize > 0, "Distance between corners or circles must be positive")) return false;