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.
This commit is contained in:
Alexander Smorkalov 2022-06-08 13:59:55 +03:00
parent 14754deb21
commit 533bb035cf
6 changed files with 30 additions and 0 deletions

View File

@ -45,6 +45,8 @@ namespace calib
double totalAvgErr; double totalAvgErr;
cv::Size imageSize; cv::Size imageSize;
std::vector<cv::Mat> allFrames;
std::vector<std::vector<cv::Point2f> > imagePoints; std::vector<std::vector<cv::Point2f> > imagePoints;
std::vector< std::vector<cv::Point3f> > objectPoints; std::vector< std::vector<cv::Point3f> > objectPoints;
@ -91,6 +93,7 @@ namespace calib
cv::Size cameraResolution; cv::Size cameraResolution;
int maxFramesNum; int maxFramesNum;
int minFramesNum; int minFramesNum;
bool saveFrames;
captureParameters() captureParameters()
{ {
@ -100,6 +103,7 @@ namespace calib
minFramesNum = 10; minFramesNum = 10;
fps = 30; fps = 30;
cameraResolution = cv::Size(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT); cameraResolution = cv::Size(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT);
saveFrames = false;
} }
}; };

View File

@ -10,6 +10,7 @@
#include <opencv2/calib3d.hpp> #include <opencv2/calib3d.hpp>
#include <opencv2/imgproc.hpp> #include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
double calib::calibController::estimateCoverageQuality() double calib::calibController::estimateCoverageQuality()
{ {
@ -212,6 +213,9 @@ void calib::calibDataController::filterFrames()
} }
showOverlayMessage(cv::format("Frame %zu is worst", worstElemIndex + 1)); showOverlayMessage(cv::format("Frame %zu is worst", worstElemIndex + 1));
if(mCalibData->allFrames.size())
mCalibData->allFrames.erase(mCalibData->allFrames.begin() + worstElemIndex);
if(mCalibData->imagePoints.size()) { if(mCalibData->imagePoints.size()) {
mCalibData->imagePoints.erase(mCalibData->imagePoints.begin() + worstElemIndex); mCalibData->imagePoints.erase(mCalibData->imagePoints.begin() + worstElemIndex);
mCalibData->objectPoints.erase(mCalibData->objectPoints.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() void calib::calibDataController::deleteLastFrame()
{ {
if(!mCalibData->allFrames.empty())
{
mCalibData->allFrames.pop_back();
}
if( !mCalibData->imagePoints.empty()) { if( !mCalibData->imagePoints.empty()) {
mCalibData->imagePoints.pop_back(); mCalibData->imagePoints.pop_back();
mCalibData->objectPoints.pop_back(); mCalibData->objectPoints.pop_back();
@ -269,6 +278,7 @@ void calib::calibDataController::rememberCurrentParameters()
void calib::calibDataController::deleteAllData() void calib::calibDataController::deleteAllData()
{ {
mCalibData->allFrames.clear();
mCalibData->imagePoints.clear(); mCalibData->imagePoints.clear();
mCalibData->objectPoints.clear(); mCalibData->objectPoints.clear();
mCalibData->allCharucoCorners.clear(); mCalibData->allCharucoCorners.clear();
@ -280,6 +290,10 @@ void calib::calibDataController::deleteAllData()
bool calib::calibDataController::saveCurrentCameraParameters() const 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; bool success = false;
if(mCalibData->cameraMatrix.total()) { if(mCalibData->cameraMatrix.total()) {
cv::FileStorage parametersWriter(mParamsFileName, cv::FileStorage::WRITE); cv::FileStorage parametersWriter(mParamsFileName, cv::FileStorage::WRITE);

View File

@ -266,6 +266,7 @@ CalibProcessor::CalibProcessor(cv::Ptr<calibrationData> data, captureParameters
static_cast<float>(mCalibData->imageSize.width * mCalibData->imageSize.width)) / 20.0; static_cast<float>(mCalibData->imageSize.width * mCalibData->imageSize.width)) / 20.0;
mSquareSize = capParams.squareSize; mSquareSize = capParams.squareSize;
mTemplDist = capParams.templDst; mTemplDist = capParams.templDst;
mSaveFrames = capParams.saveFrames;
switch(mBoardType) switch(mBoardType)
{ {
@ -291,10 +292,14 @@ CalibProcessor::CalibProcessor(cv::Ptr<calibrationData> data, captureParameters
cv::Mat CalibProcessor::processFrame(const cv::Mat &frame) cv::Mat CalibProcessor::processFrame(const cv::Mat &frame)
{ {
cv::Mat frameCopy; cv::Mat frameCopy;
cv::Mat frameCopyToSave;
frame.copyTo(frameCopy); frame.copyTo(frameCopy);
bool isTemplateFound = false; bool isTemplateFound = false;
mCurrentImagePoints.clear(); mCurrentImagePoints.clear();
if(mSaveFrames)
frame.copyTo(frameCopyToSave);
switch(mBoardType) switch(mBoardType)
{ {
case Chessboard: case Chessboard:
@ -322,6 +327,10 @@ cv::Mat CalibProcessor::processFrame(const cv::Mat &frame)
mCalibData->allCharucoCorners.size())); mCalibData->allCharucoCorners.size()));
if(!showOverlayMessage(displayMessage)) if(!showOverlayMessage(displayMessage))
showCaptureMessage(frame, displayMessage); showCaptureMessage(frame, displayMessage);
if(mSaveFrames)
mCalibData->allFrames.push_back(frameCopyToSave);
mCapuredFrames++; mCapuredFrames++;
} }
else { else {

View File

@ -50,6 +50,7 @@ protected:
double mMaxTemplateOffset; double mMaxTemplateOffset;
float mSquareSize; float mSquareSize;
float mTemplDist; float mTemplDist;
bool mSaveFrames;
bool detectAndParseChessboard(const cv::Mat& frame); bool detectAndParseChessboard(const cv::Mat& frame);
bool detectAndParseChAruco(const cv::Mat& frame); bool detectAndParseChAruco(const cv::Mat& frame);

View File

@ -40,6 +40,7 @@ const std::string keys =
"{vis | grid | Captured boards visualisation (grid, window)}" "{vis | grid | Captured boards visualisation (grid, window)}"
"{d | 0.8 | Min delay between captures}" "{d | 0.8 | Min delay between captures}"
"{pf | defaultConfig.xml| Advanced application parameters}" "{pf | defaultConfig.xml| Advanced application parameters}"
"{save_frames | false | Save frames that contribute to final calibration}"
"{help | | Print help}"; "{help | | Print help}";
bool calib::showOverlayMessage(const std::string& message) bool calib::showOverlayMessage(const std::string& message)

View File

@ -89,6 +89,7 @@ bool calib::parametersController::loadFromParser(cv::CommandLineParser &parser)
mCapParams.captureDelay = parser.get<float>("d"); mCapParams.captureDelay = parser.get<float>("d");
mCapParams.squareSize = parser.get<float>("sz"); mCapParams.squareSize = parser.get<float>("sz");
mCapParams.templDst = parser.get<float>("dst"); mCapParams.templDst = parser.get<float>("dst");
mCapParams.saveFrames = parser.has("save_frames");
if(!checkAssertion(mCapParams.squareSize > 0, "Distance between corners or circles must be positive")) if(!checkAssertion(mCapParams.squareSize > 0, "Distance between corners or circles must be positive"))
return false; return false;