From 5a0c04409bfcd15bb5f481aef049362bc81b6e8e Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Fri, 8 Apr 2016 16:30:56 +0300 Subject: [PATCH] Add interactive calibration app --- apps/CMakeLists.txt | 1 + apps/interactive-calibration/CMakeLists.txt | 48 + apps/interactive-calibration/calibCommon.hpp | 118 +++ .../calibController.cpp | 327 +++++++ .../calibController.hpp | 64 ++ .../interactive-calibration/calibPipeline.cpp | 91 ++ .../interactive-calibration/calibPipeline.hpp | 39 + .../cvCalibrationFork.cpp | 824 ++++++++++++++++++ .../cvCalibrationFork.hpp | 56 ++ .../interactive-calibration/defaultConfig.xml | 14 + .../frameProcessor.cpp | 518 +++++++++++ .../frameProcessor.hpp | 95 ++ apps/interactive-calibration/linalg.cpp | 491 +++++++++++ apps/interactive-calibration/linalg.hpp | 13 + apps/interactive-calibration/main.cpp | 210 +++++ .../parametersController.cpp | 138 +++ .../parametersController.hpp | 29 + .../rotationConverters.cpp | 121 +++ .../rotationConverters.hpp | 16 + .../images/charuco_board.png | Bin 0 -> 10393 bytes .../images/dualCircles.jpg | Bin 0 -> 71938 bytes .../images/screen_charuco.jpg | Bin 0 -> 85753 bytes .../images/screen_finish.jpg | Bin 0 -> 79577 bytes .../interactive_calibration.markdown | 198 +++++ .../calib3d/table_of_content_calib3d.markdown | 11 + 25 files changed, 3422 insertions(+) create mode 100644 apps/interactive-calibration/CMakeLists.txt create mode 100644 apps/interactive-calibration/calibCommon.hpp create mode 100644 apps/interactive-calibration/calibController.cpp create mode 100644 apps/interactive-calibration/calibController.hpp create mode 100644 apps/interactive-calibration/calibPipeline.cpp create mode 100644 apps/interactive-calibration/calibPipeline.hpp create mode 100644 apps/interactive-calibration/cvCalibrationFork.cpp create mode 100644 apps/interactive-calibration/cvCalibrationFork.hpp create mode 100644 apps/interactive-calibration/defaultConfig.xml create mode 100644 apps/interactive-calibration/frameProcessor.cpp create mode 100644 apps/interactive-calibration/frameProcessor.hpp create mode 100644 apps/interactive-calibration/linalg.cpp create mode 100644 apps/interactive-calibration/linalg.hpp create mode 100644 apps/interactive-calibration/main.cpp create mode 100644 apps/interactive-calibration/parametersController.cpp create mode 100644 apps/interactive-calibration/parametersController.hpp create mode 100644 apps/interactive-calibration/rotationConverters.cpp create mode 100644 apps/interactive-calibration/rotationConverters.hpp create mode 100644 doc/tutorials/calib3d/interactive_calibration/images/charuco_board.png create mode 100644 doc/tutorials/calib3d/interactive_calibration/images/dualCircles.jpg create mode 100644 doc/tutorials/calib3d/interactive_calibration/images/screen_charuco.jpg create mode 100644 doc/tutorials/calib3d/interactive_calibration/images/screen_finish.jpg create mode 100644 doc/tutorials/calib3d/interactive_calibration/interactive_calibration.markdown diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 095c7fc23f..79667dbd26 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -4,3 +4,4 @@ link_libraries(${OPENCV_LINKER_LIBS}) add_subdirectory(traincascade) add_subdirectory(createsamples) add_subdirectory(annotation) +add_subdirectory(interactive-calibration) diff --git a/apps/interactive-calibration/CMakeLists.txt b/apps/interactive-calibration/CMakeLists.txt new file mode 100644 index 0000000000..8174c40734 --- /dev/null +++ b/apps/interactive-calibration/CMakeLists.txt @@ -0,0 +1,48 @@ +set(OPENCV_INTERACTIVECALIBRATION_DEPS opencv_core opencv_aruco opencv_highgui opencv_calib3d opencv_videoio) +ocv_check_dependencies(${OPENCV_INTERACTIVECALIBRATION_DEPS}) + +if(NOT OCV_DEPENDENCIES_FOUND) + return() +endif() + +find_package(LAPACK) +if(LAPACK_FOUND) + find_file(LAPACK_HEADER "lapacke.h") + if(LAPACK_HEADER) + add_definitions(-DUSE_LAPACK) + link_libraries(${LAPACK_LIBRARIES}) + endif() +endif() + +project(interactive-calibration) +set(the_target opencv_interactive-calibration) + +ocv_target_include_directories(${the_target} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" "${OpenCV_SOURCE_DIR}/include/opencv") +ocv_target_include_modules_recurse(${the_target} ${OPENCV_INTERACTIVECALIBRATION_DEPS}) + +file(GLOB SRCS *.cpp) +file(GLOB HDRS *.h*) + +set(interactive-calibration_files ${SRCS} ${HDRS}) + +ocv_add_executable(${the_target} ${interactive-calibration_files}) +ocv_target_link_libraries(${the_target} ${OPENCV_INTERACTIVECALIBRATION_DEPS}) + +set_target_properties(${the_target} PROPERTIES + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} + RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} + INSTALL_NAME_DIR lib + OUTPUT_NAME "opencv_interactive-calibration") + +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${the_target} PROPERTIES FOLDER "applications") +endif() + +if(INSTALL_CREATE_DISTRIB) + if(BUILD_SHARED_LIBS) + install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT dev) + endif() +else() + install(TARGETS ${the_target} OPTIONAL RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev) +endif() diff --git a/apps/interactive-calibration/calibCommon.hpp b/apps/interactive-calibration/calibCommon.hpp new file mode 100644 index 0000000000..4580a302c4 --- /dev/null +++ b/apps/interactive-calibration/calibCommon.hpp @@ -0,0 +1,118 @@ +#ifndef CALIB_COMMON_HPP +#define CALIB_COMMON_HPP + +#include +#include +#include +#include + +namespace calib +{ + #define OVERLAY_DELAY 1000 + #define IMAGE_MAX_WIDTH 1280 + #define IMAGE_MAX_HEIGHT 960 + + bool showOverlayMessage(const std::string& message); + + enum InputType { Video, Pictures }; + enum InputVideoSource { Camera, File }; + enum TemplateType { AcirclesGrid, Chessboard, chAruco, DoubleAcirclesGrid }; + + static const std::string mainWindowName = "Calibration"; + static const std::string gridWindowName = "Board locations"; + static const std::string consoleHelp = "Hot keys:\nesc - exit application\n" + "s - save current data to .xml file\n" + "r - delete last frame\n" + "u - enable/disable applying undistortion" + "d - delete all frames\n" + "v - switch visualization"; + + static const double sigmaMult = 1.96; + + struct calibrationData + { + cv::Mat cameraMatrix; + cv::Mat distCoeffs; + cv::Mat stdDeviations; + cv::Mat perViewErrors; + std::vector rvecs; + std::vector tvecs; + double totalAvgErr; + cv::Size imageSize; + + std::vector > imagePoints; + std::vector< std::vector > objectPoints; + + std::vector allCharucoCorners; + std::vector allCharucoIds; + + cv::Mat undistMap1, undistMap2; + + calibrationData() + { + imageSize = cv::Size(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT); + } + }; + + struct cameraParameters + { + cv::Mat cameraMatrix; + cv::Mat distCoeffs; + cv::Mat stdDeviations; + double avgError; + + cameraParameters(){} + cameraParameters(cv::Mat& _cameraMatrix, cv::Mat& _distCoeffs, cv::Mat& _stdDeviations, double _avgError = 0) : + cameraMatrix(_cameraMatrix), distCoeffs(_distCoeffs), stdDeviations(_stdDeviations), avgError(_avgError) + {} + }; + + struct captureParameters + { + InputType captureMethod; + InputVideoSource source; + TemplateType board; + cv::Size boardSize; + int charucoDictName; + int calibrationStep; + float charucoSquareLenght, charucoMarkerSize; + float captureDelay; + float squareSize; + float templDst; + std::string videoFileName; + bool flipVertical; + int camID; + int fps; + cv::Size cameraResolution; + int maxFramesNum; + int minFramesNum; + + captureParameters() + { + calibrationStep = 1; + captureDelay = 500.f; + maxFramesNum = 30; + minFramesNum = 10; + fps = 30; + cameraResolution = cv::Size(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT); + } + }; + + struct internalParameters + { + double solverEps; + int solverMaxIters; + bool fastSolving; + double filterAlpha; + + internalParameters() + { + solverEps = 1e-7; + solverMaxIters = 30; + fastSolving = false; + filterAlpha = 0.1; + } + }; +} + +#endif diff --git a/apps/interactive-calibration/calibController.cpp b/apps/interactive-calibration/calibController.cpp new file mode 100644 index 0000000000..186d373aca --- /dev/null +++ b/apps/interactive-calibration/calibController.cpp @@ -0,0 +1,327 @@ +#include "calibController.hpp" + +#include +#include +#include +#include +#include + +double calib::calibController::estimateCoverageQuality() +{ + int gridSize = 10; + int xGridStep = mCalibData->imageSize.width / gridSize; + int yGridStep = mCalibData->imageSize.height / gridSize; + std::vector pointsInCell(gridSize*gridSize); + + std::fill(pointsInCell.begin(), pointsInCell.end(), 0); + + for(std::vector >::iterator it = mCalibData->imagePoints.begin(); it != mCalibData->imagePoints.end(); ++it) + for(std::vector::iterator pointIt = (*it).begin(); pointIt != (*it).end(); ++pointIt) { + int i = (int)((*pointIt).x / xGridStep); + int j = (int)((*pointIt).y / yGridStep); + pointsInCell[i*gridSize + j]++; + } + + for(std::vector::iterator it = mCalibData->allCharucoCorners.begin(); it != mCalibData->allCharucoCorners.end(); ++it) + for(int l = 0; l < (*it).size[0]; l++) { + int i = (int)((*it).at(l, 0) / xGridStep); + int j = (int)((*it).at(l, 1) / yGridStep); + pointsInCell[i*gridSize + j]++; + } + + cv::Mat mean, stdDev; + cv::meanStdDev(pointsInCell, mean, stdDev); + + return mean.at(0) / (stdDev.at(0) + 1e-7); +} + +calib::calibController::calibController() +{ + mCalibFlags = 0; +} + +calib::calibController::calibController(cv::Ptr data, int initialFlags, bool autoTuning, int minFramesNum) : + mCalibData(data) +{ + mCalibFlags = initialFlags; + mNeedTuning = autoTuning; + mMinFramesNum = minFramesNum; + mConfIntervalsState = false; + mCoverageQualityState = false; +} + +void calib::calibController::updateState() +{ + if(mCalibData->cameraMatrix.total()) { + const double relErrEps = 0.05; + bool fConfState = false, cConfState = false, dConfState = true; + if(sigmaMult*mCalibData->stdDeviations.at(0) / mCalibData->cameraMatrix.at(0,0) < relErrEps && + sigmaMult*mCalibData->stdDeviations.at(1) / mCalibData->cameraMatrix.at(1,1) < relErrEps) + fConfState = true; + if(sigmaMult*mCalibData->stdDeviations.at(2) / mCalibData->cameraMatrix.at(0,2) < relErrEps && + sigmaMult*mCalibData->stdDeviations.at(3) / mCalibData->cameraMatrix.at(1,2) < relErrEps) + cConfState = true; + + for(int i = 0; i < 5; i++) + if(mCalibData->stdDeviations.at(4+i) / fabs(mCalibData->distCoeffs.at(i)) > 1) + dConfState = false; + + mConfIntervalsState = fConfState && cConfState && dConfState; + } + + if(getFramesNumberState()) + mCoverageQualityState = estimateCoverageQuality() > 1.8 ? true : false; + + if (getFramesNumberState() && mNeedTuning) { + if( !(mCalibFlags & cv::CALIB_FIX_ASPECT_RATIO) && + mCalibData->cameraMatrix.total()) { + double fDiff = fabs(mCalibData->cameraMatrix.at(0,0) - + mCalibData->cameraMatrix.at(1,1)); + + if (fDiff < 3*mCalibData->stdDeviations.at(0) && + fDiff < 3*mCalibData->stdDeviations.at(1)) { + mCalibFlags |= cv::CALIB_FIX_ASPECT_RATIO; + mCalibData->cameraMatrix.at(0,0) = + mCalibData->cameraMatrix.at(1,1); + } + } + + if(!(mCalibFlags & cv::CALIB_ZERO_TANGENT_DIST)) { + const double eps = 0.005; + if(fabs(mCalibData->distCoeffs.at(2)) < eps && + fabs(mCalibData->distCoeffs.at(3)) < eps) + mCalibFlags |= cv::CALIB_ZERO_TANGENT_DIST; + } + + if(!(mCalibFlags & cv::CALIB_FIX_K1)) { + const double eps = 0.005; + if(fabs(mCalibData->distCoeffs.at(0)) < eps) + mCalibFlags |= cv::CALIB_FIX_K1; + } + + if(!(mCalibFlags & cv::CALIB_FIX_K2)) { + const double eps = 0.005; + if(fabs(mCalibData->distCoeffs.at(1)) < eps) + mCalibFlags |= cv::CALIB_FIX_K2; + } + + if(!(mCalibFlags & cv::CALIB_FIX_K3)) { + const double eps = 0.005; + if(fabs(mCalibData->distCoeffs.at(4)) < eps) + mCalibFlags |= cv::CALIB_FIX_K3; + } + + } +} + +bool calib::calibController::getCommonCalibrationState() const +{ + int rating = (int)getFramesNumberState() + (int)getConfidenceIntrervalsState() + + (int)getRMSState() + (int)mCoverageQualityState; + return rating == 4; +} + +bool calib::calibController::getFramesNumberState() const +{ + return std::max(mCalibData->imagePoints.size(), mCalibData->allCharucoCorners.size()) > mMinFramesNum; +} + +bool calib::calibController::getConfidenceIntrervalsState() const +{ + return mConfIntervalsState; +} + +bool calib::calibController::getRMSState() const +{ + return mCalibData->totalAvgErr < 0.5; +} + +int calib::calibController::getNewFlags() const +{ + return mCalibFlags; +} + + +//////////////////// calibDataController + +double calib::calibDataController::estimateGridSubsetQuality(size_t excludedIndex) +{ + { + int gridSize = 10; + int xGridStep = mCalibData->imageSize.width / gridSize; + int yGridStep = mCalibData->imageSize.height / gridSize; + std::vector pointsInCell(gridSize*gridSize); + + std::fill(pointsInCell.begin(), pointsInCell.end(), 0); + + for(size_t k = 0; k < mCalibData->imagePoints.size(); k++) + if(k != excludedIndex) + for(std::vector::iterator pointIt = mCalibData->imagePoints[k].begin(); pointIt != mCalibData->imagePoints[k].end(); ++pointIt) { + int i = (int)((*pointIt).x / xGridStep); + int j = (int)((*pointIt).y / yGridStep); + pointsInCell[i*gridSize + j]++; + } + + for(size_t k = 0; k < mCalibData->allCharucoCorners.size(); k++) + if(k != excludedIndex) + for(int l = 0; l < mCalibData->allCharucoCorners[k].size[0]; l++) { + int i = (int)(mCalibData->allCharucoCorners[k].at(l, 0) / xGridStep); + int j = (int)(mCalibData->allCharucoCorners[k].at(l, 1) / yGridStep); + pointsInCell[i*gridSize + j]++; + } + + cv::Mat mean, stdDev; + cv::meanStdDev(pointsInCell, mean, stdDev); + + return mean.at(0) / (stdDev.at(0) + 1e-7); + } +} + +calib::calibDataController::calibDataController(cv::Ptr data, int maxFrames, double convParameter) : + mCalibData(data), mParamsFileName("CamParams.xml") +{ + mMaxFramesNum = maxFrames; + mAlpha = convParameter; +} + +calib::calibDataController::calibDataController() +{ + +} + +void calib::calibDataController::filterFrames() +{ + size_t numberOfFrames = std::max(mCalibData->allCharucoIds.size(), mCalibData->imagePoints.size()); + CV_Assert(numberOfFrames == mCalibData->perViewErrors.total()); + if(numberOfFrames >= mMaxFramesNum) { + + double worstValue = -HUGE_VAL, maxQuality = estimateGridSubsetQuality(numberOfFrames); + size_t worstElemIndex = 0; + for(size_t i = 0; i < numberOfFrames; i++) { + double gridQDelta = estimateGridSubsetQuality(i) - maxQuality; + double currentValue = mCalibData->perViewErrors.at((int)i)*mAlpha + gridQDelta*(1. - mAlpha); + if(currentValue > worstValue) { + worstValue = currentValue; + worstElemIndex = i; + } + } + showOverlayMessage(cv::format("Frame %d is worst", worstElemIndex + 1)); + + if(mCalibData->imagePoints.size()) { + mCalibData->imagePoints.erase(mCalibData->imagePoints.begin() + worstElemIndex); + mCalibData->objectPoints.erase(mCalibData->objectPoints.begin() + worstElemIndex); + } + else { + mCalibData->allCharucoCorners.erase(mCalibData->allCharucoCorners.begin() + worstElemIndex); + mCalibData->allCharucoIds.erase(mCalibData->allCharucoIds.begin() + worstElemIndex); + } + + cv::Mat newErrorsVec = cv::Mat((int)numberOfFrames - 1, 1, CV_64F); + std::copy(mCalibData->perViewErrors.ptr(0), + mCalibData->perViewErrors.ptr((int)worstElemIndex), newErrorsVec.ptr(0)); + std::copy(mCalibData->perViewErrors.ptr((int)worstElemIndex + 1), mCalibData->perViewErrors.ptr((int)numberOfFrames), + newErrorsVec.ptr((int)worstElemIndex)); + mCalibData->perViewErrors = newErrorsVec; + } +} + +void calib::calibDataController::setParametersFileName(const std::string &name) +{ + mParamsFileName = name; +} + +void calib::calibDataController::deleteLastFrame() +{ + if( !mCalibData->imagePoints.empty()) { + mCalibData->imagePoints.pop_back(); + mCalibData->objectPoints.pop_back(); + } + + if (!mCalibData->allCharucoCorners.empty()) { + mCalibData->allCharucoCorners.pop_back(); + mCalibData->allCharucoIds.pop_back(); + } + + if(!mParamsStack.empty()) { + mCalibData->cameraMatrix = (mParamsStack.top()).cameraMatrix; + mCalibData->distCoeffs = (mParamsStack.top()).distCoeffs; + mCalibData->stdDeviations = (mParamsStack.top()).stdDeviations; + mCalibData->totalAvgErr = (mParamsStack.top()).avgError; + mParamsStack.pop(); + } +} + +void calib::calibDataController::rememberCurrentParameters() +{ + cv::Mat oldCameraMat, oldDistcoeefs, oldStdDevs; + mCalibData->cameraMatrix.copyTo(oldCameraMat); + mCalibData->distCoeffs.copyTo(oldDistcoeefs); + mCalibData->stdDeviations.copyTo(oldStdDevs); + mParamsStack.push(cameraParameters(oldCameraMat, oldDistcoeefs, oldStdDevs, mCalibData->totalAvgErr)); +} + +void calib::calibDataController::deleteAllData() +{ + mCalibData->imagePoints.clear(); + mCalibData->objectPoints.clear(); + mCalibData->allCharucoCorners.clear(); + mCalibData->allCharucoIds.clear(); + mCalibData->cameraMatrix = mCalibData->distCoeffs = cv::Mat(); + mParamsStack = std::stack(); + rememberCurrentParameters(); +} + +bool calib::calibDataController::saveCurrentCameraParameters() const +{ + bool success = false; + if(mCalibData->cameraMatrix.total()) { + cv::FileStorage parametersWriter(mParamsFileName, cv::FileStorage::WRITE); + if(parametersWriter.isOpened()) { + time_t rawtime; + time(&rawtime); + char buf[256]; + strftime(buf, sizeof(buf)-1, "%c", localtime(&rawtime)); + + parametersWriter << "calibrationDate" << buf; + parametersWriter << "framesCount" << std::max((int)mCalibData->objectPoints.size(), (int)mCalibData->allCharucoCorners.size()); + parametersWriter << "cameraResolution" << mCalibData->imageSize; + parametersWriter << "cameraMatrix" << mCalibData->cameraMatrix; + parametersWriter << "cameraMatrix_std_dev" << mCalibData->stdDeviations.rowRange(cv::Range(0, 4)); + parametersWriter << "dist_coeffs" << mCalibData->distCoeffs; + parametersWriter << "dist_coeffs_std_dev" << mCalibData->stdDeviations.rowRange(cv::Range(4, 9)); + parametersWriter << "avg_reprojection_error" << mCalibData->totalAvgErr; + + parametersWriter.release(); + success = true; + } + } + return success; +} + +void calib::calibDataController::printParametersToConsole(std::ostream &output) const +{ + const char* border = "---------------------------------------------------"; + output << border << std::endl; + output << "Frames used for calibration: " << std::max(mCalibData->objectPoints.size(), mCalibData->allCharucoCorners.size()) + << " \t RMS = " << mCalibData->totalAvgErr << std::endl; + if(mCalibData->cameraMatrix.at(0,0) == mCalibData->cameraMatrix.at(1,1)) + output << "F = " << mCalibData->cameraMatrix.at(1,1) << " +- " << sigmaMult*mCalibData->stdDeviations.at(1) << std::endl; + else + output << "Fx = " << mCalibData->cameraMatrix.at(0,0) << " +- " << sigmaMult*mCalibData->stdDeviations.at(0) << " \t " + << "Fy = " << mCalibData->cameraMatrix.at(1,1) << " +- " << sigmaMult*mCalibData->stdDeviations.at(1) << std::endl; + output << "Cx = " << mCalibData->cameraMatrix.at(0,2) << " +- " << sigmaMult*mCalibData->stdDeviations.at(2) << " \t" + << "Cy = " << mCalibData->cameraMatrix.at(1,2) << " +- " << sigmaMult*mCalibData->stdDeviations.at(3) << std::endl; + output << "K1 = " << mCalibData->distCoeffs.at(0) << " +- " << sigmaMult*mCalibData->stdDeviations.at(4) << std::endl; + output << "K2 = " << mCalibData->distCoeffs.at(1) << " +- " << sigmaMult*mCalibData->stdDeviations.at(5) << std::endl; + output << "K3 = " << mCalibData->distCoeffs.at(4) << " +- " << sigmaMult*mCalibData->stdDeviations.at(8) << std::endl; + output << "TD1 = " << mCalibData->distCoeffs.at(2) << " +- " << sigmaMult*mCalibData->stdDeviations.at(6) << std::endl; + output << "TD2 = " << mCalibData->distCoeffs.at(3) << " +- " << sigmaMult*mCalibData->stdDeviations.at(7) << std::endl; +} + +void calib::calibDataController::updateUndistortMap() +{ + cv::initUndistortRectifyMap(mCalibData->cameraMatrix, mCalibData->distCoeffs, cv::noArray(), + cv::getOptimalNewCameraMatrix(mCalibData->cameraMatrix, mCalibData->distCoeffs, mCalibData->imageSize, 0.0, mCalibData->imageSize), + mCalibData->imageSize, CV_16SC2, mCalibData->undistMap1, mCalibData->undistMap2); + +} diff --git a/apps/interactive-calibration/calibController.hpp b/apps/interactive-calibration/calibController.hpp new file mode 100644 index 0000000000..170a80a954 --- /dev/null +++ b/apps/interactive-calibration/calibController.hpp @@ -0,0 +1,64 @@ +#ifndef CALIB_CONTROLLER_HPP +#define CALIB_CONTROLLER_HPP + +#include "calibCommon.hpp" +#include +#include +#include + +namespace calib { + + class calibController + { + protected: + cv::Ptr mCalibData; + int mCalibFlags; + unsigned mMinFramesNum; + bool mNeedTuning; + bool mConfIntervalsState; + bool mCoverageQualityState; + + double estimateCoverageQuality(); + public: + calibController(); + calibController(cv::Ptr data, int initialFlags, bool autoTuning, + int minFramesNum); + + void updateState(); + + bool getCommonCalibrationState() const; + + bool getFramesNumberState() const; + bool getConfidenceIntrervalsState() const; + bool getRMSState() const; + bool getPointsCoverageState() const; + int getNewFlags() const; + }; + + class calibDataController + { + protected: + cv::Ptr mCalibData; + std::stack mParamsStack; + std::string mParamsFileName; + unsigned mMaxFramesNum; + double mAlpha; + + double estimateGridSubsetQuality(size_t excludedIndex); + public: + calibDataController(cv::Ptr data, int maxFrames, double convParameter); + calibDataController(); + + void filterFrames(); + void setParametersFileName(const std::string& name); + void deleteLastFrame(); + void rememberCurrentParameters(); + void deleteAllData(); + bool saveCurrentCameraParameters() const; + void printParametersToConsole(std::ostream &output) const; + void updateUndistortMap(); + }; + +} + +#endif diff --git a/apps/interactive-calibration/calibPipeline.cpp b/apps/interactive-calibration/calibPipeline.cpp new file mode 100644 index 0000000000..4575a7024a --- /dev/null +++ b/apps/interactive-calibration/calibPipeline.cpp @@ -0,0 +1,91 @@ +#include "calibPipeline.hpp" +#include +#include + +using namespace calib; + +#define CAP_DELAY 10 + +cv::Size CalibPipeline::getCameraResolution() +{ + mCapture.set(cv::CAP_PROP_FRAME_WIDTH, 10000); + mCapture.set(cv::CAP_PROP_FRAME_HEIGHT, 10000); + int w = (int)mCapture.get(cv::CAP_PROP_FRAME_WIDTH); + int h = (int)mCapture.get(cv::CAP_PROP_FRAME_HEIGHT); + return cv::Size(w,h); +} + +CalibPipeline::CalibPipeline(captureParameters params) : + mCaptureParams(params) +{ + +} + +PipelineExitStatus CalibPipeline::start(std::vector > processors) +{ + if(mCaptureParams.source == Camera && !mCapture.isOpened()) + { + mCapture.open(mCaptureParams.camID); + cv::Size maxRes = getCameraResolution(); + cv::Size neededRes = mCaptureParams.cameraResolution; + + if(maxRes.width < neededRes.width) { + double aR = (double)maxRes.width / maxRes.height; + mCapture.set(cv::CAP_PROP_FRAME_WIDTH, neededRes.width); + mCapture.set(cv::CAP_PROP_FRAME_HEIGHT, neededRes.width/aR); + } + else if(maxRes.height < neededRes.height) { + double aR = (double)maxRes.width / maxRes.height; + mCapture.set(cv::CAP_PROP_FRAME_HEIGHT, neededRes.height); + mCapture.set(cv::CAP_PROP_FRAME_WIDTH, neededRes.height*aR); + } + else { + mCapture.set(cv::CAP_PROP_FRAME_HEIGHT, neededRes.height); + mCapture.set(cv::CAP_PROP_FRAME_WIDTH, neededRes.width); + } + mCapture.set(cv::CAP_PROP_AUTOFOCUS, 0); + } + else if (mCaptureParams.source == File && !mCapture.isOpened()) + mCapture.open(mCaptureParams.videoFileName); + mImageSize = cv::Size((int)mCapture.get(cv::CAP_PROP_FRAME_WIDTH), (int)mCapture.get(cv::CAP_PROP_FRAME_HEIGHT)); + + if(!mCapture.isOpened()) + throw std::runtime_error("Unable to open video source"); + + cv::Mat frame, processedFrame; + while(mCapture.grab()) { + mCapture.retrieve(frame); + if(mCaptureParams.flipVertical) + cv::flip(frame, frame, -1); + + frame.copyTo(processedFrame); + for (std::vector >::iterator it = processors.begin(); it != processors.end(); ++it) + processedFrame = (*it)->processFrame(processedFrame); + cv::imshow(mainWindowName, processedFrame); + int key = cv::waitKey(CAP_DELAY); + + if(key == 27) // esc + return Finished; + else if (key == 114) // r + return DeleteLastFrame; + else if (key == 100) // d + return DeleteAllFrames; + else if (key == 115) // s + return SaveCurrentData; + else if (key == 117) // u + return SwitchUndistort; + else if (key == 118) // v + return SwitchVisualisation; + + for (std::vector >::iterator it = processors.begin(); it != processors.end(); ++it) + if((*it)->isProcessed()) + return Calibrate; + } + + return Finished; +} + +cv::Size CalibPipeline::getImageSize() const +{ + return mImageSize; +} diff --git a/apps/interactive-calibration/calibPipeline.hpp b/apps/interactive-calibration/calibPipeline.hpp new file mode 100644 index 0000000000..b5d311e17f --- /dev/null +++ b/apps/interactive-calibration/calibPipeline.hpp @@ -0,0 +1,39 @@ +#ifndef CALIB_PIPELINE_HPP +#define CALIB_PIPELINE_HPP + +#include +#include + +#include "calibCommon.hpp" +#include "frameProcessor.hpp" + +namespace calib +{ + +enum PipelineExitStatus { Finished, + DeleteLastFrame, + Calibrate, + DeleteAllFrames, + SaveCurrentData, + SwitchUndistort, + SwitchVisualisation + }; + +class CalibPipeline +{ +protected: + captureParameters mCaptureParams; + cv::Size mImageSize; + cv::VideoCapture mCapture; + + cv::Size getCameraResolution(); + +public: + CalibPipeline(captureParameters params); + PipelineExitStatus start(std::vector > processors); + cv::Size getImageSize() const; +}; + +} + +#endif diff --git a/apps/interactive-calibration/cvCalibrationFork.cpp b/apps/interactive-calibration/cvCalibrationFork.cpp new file mode 100644 index 0000000000..c603dbeb87 --- /dev/null +++ b/apps/interactive-calibration/cvCalibrationFork.cpp @@ -0,0 +1,824 @@ +#include +#include "linalg.hpp" +#include "cvCalibrationFork.hpp" + +using namespace cv; + +static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, + const std::vector& rows); +static const char* cvDistCoeffErr = "Distortion coefficients must be 1x4, 4x1, 1x5, 5x1, 1x8, 8x1, 1x12, 12x1, 1x14 or 14x1 floating-point vector"; + +static void cvEvaluateJtJ2(CvMat* _JtJ, + const CvMat* camera_matrix, + const CvMat* distortion_coeffs, + const CvMat* object_points, + const CvMat* param, + const CvMat* npoints, + int flags, int NINTRINSIC, double aspectRatio) +{ + int i, pos, ni, total = 0, npstep = 0, maxPoints = 0; + + npstep = npoints->rows == 1 ? 1 : npoints->step/CV_ELEM_SIZE(npoints->type); + int nimages = npoints->rows*npoints->cols; + for( i = 0; i < nimages; i++ ) + { + ni = npoints->data.i[i*npstep]; + if( ni < 4 ) + { + CV_Error_( CV_StsOutOfRange, ("The number of points in the view #%d is < 4", i)); + } + maxPoints = MAX( maxPoints, ni ); + total += ni; + } + + Mat _Ji( maxPoints*2, NINTRINSIC, CV_64FC1, Scalar(0)); + Mat _Je( maxPoints*2, 6, CV_64FC1 ); + Mat _err( maxPoints*2, 1, CV_64FC1 ); + Mat _m( 1, total, CV_64FC2 ); + const Mat matM = cvarrToMat(object_points); + + cvZero(_JtJ); + for(i = 0, pos = 0; i < nimages; i++, pos += ni ) + { + CvMat _ri, _ti; + ni = npoints->data.i[i*npstep]; + + cvGetRows( param, &_ri, NINTRINSIC + i*6, NINTRINSIC + i*6 + 3 ); + cvGetRows( param, &_ti, NINTRINSIC + i*6 + 3, NINTRINSIC + i*6 + 6 ); + + CvMat _Mi(matM.colRange(pos, pos + ni)); + CvMat _mi(_m.colRange(pos, pos + ni)); + + _Je.resize(ni*2); _Ji.resize(ni*2); _err.resize(ni*2); + CvMat _dpdr(_Je.colRange(0, 3)); + CvMat _dpdt(_Je.colRange(3, 6)); + CvMat _dpdf(_Ji.colRange(0, 2)); + CvMat _dpdc(_Ji.colRange(2, 4)); + CvMat _dpdk(_Ji.colRange(4, NINTRINSIC)); + CvMat _mp(_err.reshape(2, 1)); + + cvProjectPoints2( &_Mi, &_ri, &_ti, camera_matrix, distortion_coeffs, &_mp, &_dpdr, &_dpdt, + (flags & CALIB_FIX_FOCAL_LENGTH) ? 0 : &_dpdf, + (flags & CALIB_FIX_PRINCIPAL_POINT) ? 0 : &_dpdc, &_dpdk, + (flags & CALIB_FIX_ASPECT_RATIO) ? aspectRatio : 0); + cvSub( &_mp, &_mi, &_mp ); + Mat JtJ(cvarrToMat(_JtJ)); + // see HZ: (A6.14) for details on the structure of the Jacobian + JtJ(Rect(0, 0, NINTRINSIC, NINTRINSIC)) += _Ji.t() * _Ji; + JtJ(Rect(NINTRINSIC + i * 6, NINTRINSIC + i * 6, 6, 6)) = _Je.t() * _Je; + JtJ(Rect(NINTRINSIC + i * 6, 0, 6, NINTRINSIC)) = _Ji.t() * _Je; + } +} + +double cvfork::cvCalibrateCamera2( const CvMat* objectPoints, + const CvMat* imagePoints, const CvMat* npoints, + CvSize imageSize, CvMat* cameraMatrix, CvMat* distCoeffs, + CvMat* rvecs, CvMat* tvecs, CvMat* stdDevs, CvMat* perViewErrors, int flags, CvTermCriteria termCrit ) +{ + { + const int NINTRINSIC = CV_CALIB_NINTRINSIC; + double reprojErr = 0; + + Matx33d A; + double k[14] = {0}; + CvMat matA = cvMat(3, 3, CV_64F, A.val), _k; + int i, nimages, maxPoints = 0, ni = 0, pos, total = 0, nparams, npstep, cn; + double aspectRatio = 0.; + + // 0. check the parameters & allocate buffers + if( !CV_IS_MAT(objectPoints) || !CV_IS_MAT(imagePoints) || + !CV_IS_MAT(npoints) || !CV_IS_MAT(cameraMatrix) || !CV_IS_MAT(distCoeffs) ) + CV_Error( CV_StsBadArg, "One of required vector arguments is not a valid matrix" ); + + if( imageSize.width <= 0 || imageSize.height <= 0 ) + CV_Error( CV_StsOutOfRange, "image width and height must be positive" ); + + if( CV_MAT_TYPE(npoints->type) != CV_32SC1 || + (npoints->rows != 1 && npoints->cols != 1) ) + CV_Error( CV_StsUnsupportedFormat, + "the array of point counters must be 1-dimensional integer vector" ); + if(flags & CV_CALIB_TILTED_MODEL) + { + //when the tilted sensor model is used the distortion coefficients matrix must have 14 parameters + if (distCoeffs->cols*distCoeffs->rows != 14) + CV_Error( CV_StsBadArg, "The tilted sensor model must have 14 parameters in the distortion matrix" ); + } + else + { + //when the thin prism model is used the distortion coefficients matrix must have 12 parameters + if(flags & CV_CALIB_THIN_PRISM_MODEL) + if (distCoeffs->cols*distCoeffs->rows != 12) + CV_Error( CV_StsBadArg, "Thin prism model must have 12 parameters in the distortion matrix" ); + } + + nimages = npoints->rows*npoints->cols; + npstep = npoints->rows == 1 ? 1 : npoints->step/CV_ELEM_SIZE(npoints->type); + + if( rvecs ) + { + cn = CV_MAT_CN(rvecs->type); + if( !CV_IS_MAT(rvecs) || + (CV_MAT_DEPTH(rvecs->type) != CV_32F && CV_MAT_DEPTH(rvecs->type) != CV_64F) || + ((rvecs->rows != nimages || (rvecs->cols*cn != 3 && rvecs->cols*cn != 9)) && + (rvecs->rows != 1 || rvecs->cols != nimages || cn != 3)) ) + CV_Error( CV_StsBadArg, "the output array of rotation vectors must be 3-channel " + "1xn or nx1 array or 1-channel nx3 or nx9 array, where n is the number of views" ); + } + + if( tvecs ) + { + cn = CV_MAT_CN(tvecs->type); + if( !CV_IS_MAT(tvecs) || + (CV_MAT_DEPTH(tvecs->type) != CV_32F && CV_MAT_DEPTH(tvecs->type) != CV_64F) || + ((tvecs->rows != nimages || tvecs->cols*cn != 3) && + (tvecs->rows != 1 || tvecs->cols != nimages || cn != 3)) ) + CV_Error( CV_StsBadArg, "the output array of translation vectors must be 3-channel " + "1xn or nx1 array or 1-channel nx3 array, where n is the number of views" ); + } + + if( stdDevs ) + { + cn = CV_MAT_CN(stdDevs->type); + if( !CV_IS_MAT(stdDevs) || + (CV_MAT_DEPTH(stdDevs->type) != CV_32F && CV_MAT_DEPTH(stdDevs->type) != CV_64F) || + ((stdDevs->rows != (nimages*6 + NINTRINSIC) || stdDevs->cols*cn != 1) && + (stdDevs->rows != 1 || stdDevs->cols != (nimages*6 + NINTRINSIC) || cn != 1)) ) + CV_Error( CV_StsBadArg, "the output array of standard deviations vectors must be 1-channel " + "1x(n*6 + NINTRINSIC) or (n*6 + NINTRINSIC)x1 array, where n is the number of views" ); + } + + if( (CV_MAT_TYPE(cameraMatrix->type) != CV_32FC1 && + CV_MAT_TYPE(cameraMatrix->type) != CV_64FC1) || + cameraMatrix->rows != 3 || cameraMatrix->cols != 3 ) + CV_Error( CV_StsBadArg, + "Intrinsic parameters must be 3x3 floating-point matrix" ); + + if( (CV_MAT_TYPE(distCoeffs->type) != CV_32FC1 && + CV_MAT_TYPE(distCoeffs->type) != CV_64FC1) || + (distCoeffs->cols != 1 && distCoeffs->rows != 1) || + (distCoeffs->cols*distCoeffs->rows != 4 && + distCoeffs->cols*distCoeffs->rows != 5 && + distCoeffs->cols*distCoeffs->rows != 8 && + distCoeffs->cols*distCoeffs->rows != 12 && + distCoeffs->cols*distCoeffs->rows != 14) ) + CV_Error( CV_StsBadArg, cvDistCoeffErr ); + + for( i = 0; i < nimages; i++ ) + { + ni = npoints->data.i[i*npstep]; + if( ni < 4 ) + { + CV_Error_( CV_StsOutOfRange, ("The number of points in the view #%d is < 4", i)); + } + maxPoints = MAX( maxPoints, ni ); + total += ni; + } + + Mat matM( 1, total, CV_64FC3 ); + Mat _m( 1, total, CV_64FC2 ); + + if(CV_MAT_CN(objectPoints->type) == 3) { + cvarrToMat(objectPoints).convertTo(matM, CV_64F); + } else { + convertPointsHomogeneous(cvarrToMat(objectPoints), matM); + } + + if(CV_MAT_CN(imagePoints->type) == 2) { + cvarrToMat(imagePoints).convertTo(_m, CV_64F); + } else { + convertPointsHomogeneous(cvarrToMat(imagePoints), _m); + } + + nparams = NINTRINSIC + nimages*6; + Mat _Ji( maxPoints*2, NINTRINSIC, CV_64FC1, Scalar(0)); + Mat _Je( maxPoints*2, 6, CV_64FC1 ); + Mat _err( maxPoints*2, 1, CV_64FC1 ); + + _k = cvMat( distCoeffs->rows, distCoeffs->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(distCoeffs->type)), k); + if( distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) < 8 ) + { + if( distCoeffs->rows*distCoeffs->cols*CV_MAT_CN(distCoeffs->type) < 5 ) + flags |= CALIB_FIX_K3; + flags |= CALIB_FIX_K4 | CALIB_FIX_K5 | CALIB_FIX_K6; + } + const double minValidAspectRatio = 0.01; + const double maxValidAspectRatio = 100.0; + + // 1. initialize intrinsic parameters & LM solver + if( flags & CALIB_USE_INTRINSIC_GUESS ) + { + cvConvert( cameraMatrix, &matA ); + if( A(0, 0) <= 0 || A(1, 1) <= 0 ) + CV_Error( CV_StsOutOfRange, "Focal length (fx and fy) must be positive" ); + if( A(0, 2) < 0 || A(0, 2) >= imageSize.width || + A(1, 2) < 0 || A(1, 2) >= imageSize.height ) + CV_Error( CV_StsOutOfRange, "Principal point must be within the image" ); + if( fabs(A(0, 1)) > 1e-5 ) + CV_Error( CV_StsOutOfRange, "Non-zero skew is not supported by the function" ); + if( fabs(A(1, 0)) > 1e-5 || fabs(A(2, 0)) > 1e-5 || + fabs(A(2, 1)) > 1e-5 || fabs(A(2,2)-1) > 1e-5 ) + CV_Error( CV_StsOutOfRange, + "The intrinsic matrix must have [fx 0 cx; 0 fy cy; 0 0 1] shape" ); + A(0, 1) = A(1, 0) = A(2, 0) = A(2, 1) = 0.; + A(2, 2) = 1.; + + if( flags & CALIB_FIX_ASPECT_RATIO ) + { + aspectRatio = A(0, 0)/A(1, 1); + + if( aspectRatio < minValidAspectRatio || aspectRatio > maxValidAspectRatio ) + CV_Error( CV_StsOutOfRange, + "The specified aspect ratio (= cameraMatrix[0][0] / cameraMatrix[1][1]) is incorrect" ); + } + cvConvert( distCoeffs, &_k ); + } + else + { + Scalar mean, sdv; + meanStdDev(matM, mean, sdv); + if( fabs(mean[2]) > 1e-5 || fabs(sdv[2]) > 1e-5 ) + CV_Error( CV_StsBadArg, + "For non-planar calibration rigs the initial intrinsic matrix must be specified" ); + for( i = 0; i < total; i++ ) + matM.at(i).z = 0.; + + if( flags & CALIB_FIX_ASPECT_RATIO ) + { + aspectRatio = cvmGet(cameraMatrix,0,0); + aspectRatio /= cvmGet(cameraMatrix,1,1); + if( aspectRatio < minValidAspectRatio || aspectRatio > maxValidAspectRatio ) + CV_Error( CV_StsOutOfRange, + "The specified aspect ratio (= cameraMatrix[0][0] / cameraMatrix[1][1]) is incorrect" ); + } + CvMat _matM(matM), m(_m); + cvInitIntrinsicParams2D( &_matM, &m, npoints, imageSize, &matA, aspectRatio ); + } + + //CvLevMarq solver( nparams, 0, termCrit ); + cvfork::CvLevMarqFork solver( nparams, 0, termCrit ); + Mat allErrors(1, total, CV_64FC2); + + if(flags & CALIB_USE_LU) { + solver.solveMethod = DECOMP_LU; + } + else if(flags & CALIB_USE_QR) + solver.solveMethod = DECOMP_QR; + + { + double* param = solver.param->data.db; + uchar* mask = solver.mask->data.ptr; + + param[0] = A(0, 0); param[1] = A(1, 1); param[2] = A(0, 2); param[3] = A(1, 2); + std::copy(k, k + 14, param + 4); + + if( flags & CV_CALIB_FIX_FOCAL_LENGTH ) + mask[0] = mask[1] = 0; + if( flags & CV_CALIB_FIX_PRINCIPAL_POINT ) + mask[2] = mask[3] = 0; + if( flags & CV_CALIB_ZERO_TANGENT_DIST ) + { + param[6] = param[7] = 0; + mask[6] = mask[7] = 0; + } + if( !(flags & CALIB_RATIONAL_MODEL) ) + flags |= CALIB_FIX_K4 + CALIB_FIX_K5 + CALIB_FIX_K6; + if( !(flags & CV_CALIB_THIN_PRISM_MODEL)) + flags |= CALIB_FIX_S1_S2_S3_S4; + if( !(flags & CV_CALIB_TILTED_MODEL)) + flags |= CALIB_FIX_TAUX_TAUY; + + mask[ 4] = !(flags & CALIB_FIX_K1); + mask[ 5] = !(flags & CALIB_FIX_K2); + mask[ 8] = !(flags & CALIB_FIX_K3); + mask[ 9] = !(flags & CALIB_FIX_K4); + mask[10] = !(flags & CALIB_FIX_K5); + mask[11] = !(flags & CALIB_FIX_K6); + + if(flags & CALIB_FIX_S1_S2_S3_S4) + { + mask[12] = 0; + mask[13] = 0; + mask[14] = 0; + mask[15] = 0; + } + if(flags & CALIB_FIX_TAUX_TAUY) + { + mask[16] = 0; + mask[17] = 0; + } + } + + // 2. initialize extrinsic parameters + for( i = 0, pos = 0; i < nimages; i++, pos += ni ) + { + CvMat _ri, _ti; + ni = npoints->data.i[i*npstep]; + + cvGetRows( solver.param, &_ri, NINTRINSIC + i*6, NINTRINSIC + i*6 + 3 ); + cvGetRows( solver.param, &_ti, NINTRINSIC + i*6 + 3, NINTRINSIC + i*6 + 6 ); + + CvMat _Mi(matM.colRange(pos, pos + ni)); + CvMat _mi(_m.colRange(pos, pos + ni)); + + cvFindExtrinsicCameraParams2( &_Mi, &_mi, &matA, &_k, &_ri, &_ti ); + } + + // 3. run the optimization + for(;;) + { + const CvMat* _param = 0; + CvMat *_JtJ = 0, *_JtErr = 0; + double* _errNorm = 0; + bool proceed = solver.updateAlt( _param, _JtJ, _JtErr, _errNorm ); + double *param = solver.param->data.db, *pparam = solver.prevParam->data.db; + + if( flags & CALIB_FIX_ASPECT_RATIO ) + { + param[0] = param[1]*aspectRatio; + pparam[0] = pparam[1]*aspectRatio; + } + + A(0, 0) = param[0]; A(1, 1) = param[1]; A(0, 2) = param[2]; A(1, 2) = param[3]; + std::copy(param + 4, param + 4 + 14, k); + + if( !proceed ) { + //do errors estimation + if(stdDevs) { + Ptr JtJ(cvCreateMat(nparams, nparams, CV_64F)); + CvMat cvMatM(matM); + cvEvaluateJtJ2(JtJ, &matA, &_k, &cvMatM, solver.param, npoints, flags, NINTRINSIC, aspectRatio); + + Mat mask = cvarrToMat(solver.mask); + int nparams_nz = countNonZero(mask); + Mat JtJinv, JtJN; + JtJN.create(nparams_nz, nparams_nz, CV_64F); + subMatrix(cvarrToMat(JtJ), JtJN, mask, mask); + completeSymm(JtJN, false); + #ifndef USE_LAPACK + cv::invert(JtJN, JtJinv, DECOMP_SVD); + #else + cvfork::invert(JtJN, JtJinv, DECOMP_SVD); + #endif + double sigma2 = norm(allErrors, NORM_L2SQR) / (total - nparams_nz); + Mat stdDevsM = cvarrToMat(stdDevs); + int j = 0; + for (int s = 0; s < nparams; s++) + if(mask.data[s]) { + stdDevsM.at(s) = std::sqrt(JtJinv.at(j,j)*sigma2); + j++; + } + else + stdDevsM.at(s) = 0; + } + break; + } + + reprojErr = 0; + + for( i = 0, pos = 0; i < nimages; i++, pos += ni ) + { + CvMat _ri, _ti; + ni = npoints->data.i[i*npstep]; + + cvGetRows( solver.param, &_ri, NINTRINSIC + i*6, NINTRINSIC + i*6 + 3 ); + cvGetRows( solver.param, &_ti, NINTRINSIC + i*6 + 3, NINTRINSIC + i*6 + 6 ); + + CvMat _Mi(matM.colRange(pos, pos + ni)); + CvMat _mi(_m.colRange(pos, pos + ni)); + CvMat _me(allErrors.colRange(pos, pos + ni)); + + _Je.resize(ni*2); _Ji.resize(ni*2); _err.resize(ni*2); + CvMat _dpdr(_Je.colRange(0, 3)); + CvMat _dpdt(_Je.colRange(3, 6)); + CvMat _dpdf(_Ji.colRange(0, 2)); + CvMat _dpdc(_Ji.colRange(2, 4)); + CvMat _dpdk(_Ji.colRange(4, NINTRINSIC)); + CvMat _mp(_err.reshape(2, 1)); + + if( solver.state == CvLevMarq::CALC_J ) + { + cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp, &_dpdr, &_dpdt, + (flags & CALIB_FIX_FOCAL_LENGTH) ? 0 : &_dpdf, + (flags & CALIB_FIX_PRINCIPAL_POINT) ? 0 : &_dpdc, &_dpdk, + (flags & CALIB_FIX_ASPECT_RATIO) ? aspectRatio : 0); + } + else + cvProjectPoints2( &_Mi, &_ri, &_ti, &matA, &_k, &_mp ); + + cvSub( &_mp, &_mi, &_mp ); + + if( solver.state == CvLevMarq::CALC_J ) + { + Mat JtJ(cvarrToMat(_JtJ)), JtErr(cvarrToMat(_JtErr)); + + // see HZ: (A6.14) for details on the structure of the Jacobian + JtJ(Rect(0, 0, NINTRINSIC, NINTRINSIC)) += _Ji.t() * _Ji; + JtJ(Rect(NINTRINSIC + i * 6, NINTRINSIC + i * 6, 6, 6)) = _Je.t() * _Je; + JtJ(Rect(NINTRINSIC + i * 6, 0, 6, NINTRINSIC)) = _Ji.t() * _Je; + + JtErr.rowRange(0, NINTRINSIC) += _Ji.t() * _err; + JtErr.rowRange(NINTRINSIC + i * 6, NINTRINSIC + (i + 1) * 6) = _Je.t() * _err; + + } + if (stdDevs || perViewErrors) + cvCopy(&_mp, &_me); + reprojErr += norm(_err, NORM_L2SQR); + } + + if( _errNorm ) + *_errNorm = reprojErr; + } + + // 4. store the results + cvConvert( &matA, cameraMatrix ); + cvConvert( &_k, distCoeffs ); + + for( i = 0, pos = 0; i < nimages; i++) + { + CvMat src, dst; + if( perViewErrors ) + { + ni = npoints->data.i[i*npstep]; + perViewErrors->data.db[i] = std::sqrt(cv::norm(allErrors.colRange(pos, pos + ni), NORM_L2SQR) / ni); + pos+=ni; + } + + if( rvecs ) + { + src = cvMat( 3, 1, CV_64F, solver.param->data.db + NINTRINSIC + i*6 ); + if( rvecs->rows == nimages && rvecs->cols*CV_MAT_CN(rvecs->type) == 9 ) + { + dst = cvMat( 3, 3, CV_MAT_DEPTH(rvecs->type), + rvecs->data.ptr + rvecs->step*i ); + cvRodrigues2( &src, &matA ); + cvConvert( &matA, &dst ); + } + else + { + dst = cvMat( 3, 1, CV_MAT_DEPTH(rvecs->type), rvecs->rows == 1 ? + rvecs->data.ptr + i*CV_ELEM_SIZE(rvecs->type) : + rvecs->data.ptr + rvecs->step*i ); + cvConvert( &src, &dst ); + } + } + if( tvecs ) + { + src = cvMat( 3, 1, CV_64F, solver.param->data.db + NINTRINSIC + i*6 + 3 ); + dst = cvMat( 3, 1, CV_MAT_DEPTH(tvecs->type), tvecs->rows == 1 ? + tvecs->data.ptr + i*CV_ELEM_SIZE(tvecs->type) : + tvecs->data.ptr + tvecs->step*i ); + cvConvert( &src, &dst ); + } + } + + return std::sqrt(reprojErr/total); + } +} + + +static Mat prepareCameraMatrix(Mat& cameraMatrix0, int rtype) +{ + Mat cameraMatrix = Mat::eye(3, 3, rtype); + if( cameraMatrix0.size() == cameraMatrix.size() ) + cameraMatrix0.convertTo(cameraMatrix, rtype); + return cameraMatrix; +} + +static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype) +{ + Mat distCoeffs = Mat::zeros(distCoeffs0.cols == 1 ? Size(1, 14) : Size(14, 1), rtype); + if( distCoeffs0.size() == Size(1, 4) || + distCoeffs0.size() == Size(1, 5) || + distCoeffs0.size() == Size(1, 8) || + distCoeffs0.size() == Size(1, 12) || + distCoeffs0.size() == Size(1, 14) || + distCoeffs0.size() == Size(4, 1) || + distCoeffs0.size() == Size(5, 1) || + distCoeffs0.size() == Size(8, 1) || + distCoeffs0.size() == Size(12, 1) || + distCoeffs0.size() == Size(14, 1) ) + { + Mat dstCoeffs(distCoeffs, Rect(0, 0, distCoeffs0.cols, distCoeffs0.rows)); + distCoeffs0.convertTo(dstCoeffs, rtype); + } + return distCoeffs; +} + +static void collectCalibrationData( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints1, + InputArrayOfArrays imagePoints2, + Mat& objPtMat, Mat& imgPtMat1, Mat* imgPtMat2, + Mat& npoints ) +{ + int nimages = (int)objectPoints.total(); + int i, j = 0, ni = 0, total = 0; + CV_Assert(nimages > 0 && nimages == (int)imagePoints1.total() && + (!imgPtMat2 || nimages == (int)imagePoints2.total())); + + for( i = 0; i < nimages; i++ ) + { + ni = objectPoints.getMat(i).checkVector(3, CV_32F); + if( ni <= 0 ) + CV_Error(CV_StsUnsupportedFormat, "objectPoints should contain vector of vectors of points of type Point3f"); + int ni1 = imagePoints1.getMat(i).checkVector(2, CV_32F); + if( ni1 <= 0 ) + CV_Error(CV_StsUnsupportedFormat, "imagePoints1 should contain vector of vectors of points of type Point2f"); + CV_Assert( ni == ni1 ); + + total += ni; + } + + npoints.create(1, (int)nimages, CV_32S); + objPtMat.create(1, (int)total, CV_32FC3); + imgPtMat1.create(1, (int)total, CV_32FC2); + Point2f* imgPtData2 = 0; + + if( imgPtMat2 ) + { + imgPtMat2->create(1, (int)total, CV_32FC2); + imgPtData2 = imgPtMat2->ptr(); + } + + Point3f* objPtData = objPtMat.ptr(); + Point2f* imgPtData1 = imgPtMat1.ptr(); + + for( i = 0; i < nimages; i++, j += ni ) + { + Mat objpt = objectPoints.getMat(i); + Mat imgpt1 = imagePoints1.getMat(i); + ni = objpt.checkVector(3, CV_32F); + npoints.at(i) = ni; + memcpy( objPtData + j, objpt.ptr(), ni*sizeof(objPtData[0]) ); + memcpy( imgPtData1 + j, imgpt1.ptr(), ni*sizeof(imgPtData1[0]) ); + + if( imgPtData2 ) + { + Mat imgpt2 = imagePoints2.getMat(i); + int ni2 = imgpt2.checkVector(2, CV_32F); + CV_Assert( ni == ni2 ); + memcpy( imgPtData2 + j, imgpt2.ptr(), ni*sizeof(imgPtData2[0]) ); + } + } +} + +double cvfork::calibrateCamera(InputArrayOfArrays _objectPoints, + InputArrayOfArrays _imagePoints, + Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, OutputArray _stdDeviations, OutputArray _perViewErrors, int flags, TermCriteria criteria ) +{ + int rtype = CV_64F; + Mat cameraMatrix = _cameraMatrix.getMat(); + cameraMatrix = prepareCameraMatrix(cameraMatrix, rtype); + Mat distCoeffs = _distCoeffs.getMat(); + distCoeffs = prepareDistCoeffs(distCoeffs, rtype); + if( !(flags & CALIB_RATIONAL_MODEL) && + (!(flags & CALIB_THIN_PRISM_MODEL)) && + (!(flags & CALIB_TILTED_MODEL))) + distCoeffs = distCoeffs.rows == 1 ? distCoeffs.colRange(0, 5) : distCoeffs.rowRange(0, 5); + + int nimages = int(_objectPoints.total()); + CV_Assert( nimages > 0 ); + Mat objPt, imgPt, npoints, rvecM, tvecM, stdDeviationsM, errorsM; + + bool rvecs_needed = _rvecs.needed(), tvecs_needed = _tvecs.needed(), + stddev_needed = _stdDeviations.needed(), errors_needed = _perViewErrors.needed(); + + bool rvecs_mat_vec = _rvecs.isMatVector(); + bool tvecs_mat_vec = _tvecs.isMatVector(); + + if( rvecs_needed ) { + _rvecs.create(nimages, 1, CV_64FC3); + + if(rvecs_mat_vec) + rvecM.create(nimages, 3, CV_64F); + else + rvecM = _rvecs.getMat(); + } + + if( tvecs_needed ) { + _tvecs.create(nimages, 1, CV_64FC3); + + if(tvecs_mat_vec) + tvecM.create(nimages, 3, CV_64F); + else + tvecM = _tvecs.getMat(); + } + + if( stddev_needed ) { + _stdDeviations.create(nimages*6 + CV_CALIB_NINTRINSIC, 1, CV_64F); + stdDeviationsM = _stdDeviations.getMat(); + } + + if( errors_needed) { + _perViewErrors.create(nimages, 1, CV_64F); + errorsM = _perViewErrors.getMat(); + } + + collectCalibrationData( _objectPoints, _imagePoints, noArray(), + objPt, imgPt, 0, npoints ); + CvMat c_objPt = objPt, c_imgPt = imgPt, c_npoints = npoints; + CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs; + CvMat c_rvecM = rvecM, c_tvecM = tvecM, c_stdDev = stdDeviationsM, c_errors = errorsM; + + double reprojErr = cvfork::cvCalibrateCamera2(&c_objPt, &c_imgPt, &c_npoints, imageSize, + &c_cameraMatrix, &c_distCoeffs, + rvecs_needed ? &c_rvecM : NULL, + tvecs_needed ? &c_tvecM : NULL, + stddev_needed ? &c_stdDev : NULL, + errors_needed ? &c_errors : NULL, flags, criteria ); + + // overly complicated and inefficient rvec/ tvec handling to support vector + for(int i = 0; i < nimages; i++ ) + { + if( rvecs_needed && rvecs_mat_vec) + { + _rvecs.create(3, 1, CV_64F, i, true); + Mat rv = _rvecs.getMat(i); + memcpy(rv.ptr(), rvecM.ptr(i), 3*sizeof(double)); + } + if( tvecs_needed && tvecs_mat_vec) + { + _tvecs.create(3, 1, CV_64F, i, true); + Mat tv = _tvecs.getMat(i); + memcpy(tv.ptr(), tvecM.ptr(i), 3*sizeof(double)); + } + } + + cameraMatrix.copyTo(_cameraMatrix); + distCoeffs.copyTo(_distCoeffs); + + return reprojErr; +} + +double cvfork::calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfArrays _charucoIds, + Ptr &_board, Size imageSize, + InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, OutputArray _stdDeviations, OutputArray _perViewErrors, + int flags, TermCriteria criteria) { + + CV_Assert(_charucoIds.total() > 0 && (_charucoIds.total() == _charucoCorners.total())); + + // Join object points of charuco corners in a single vector for calibrateCamera() function + std::vector< std::vector< Point3f > > allObjPoints; + allObjPoints.resize(_charucoIds.total()); + for(unsigned int i = 0; i < _charucoIds.total(); i++) { + unsigned int nCorners = (unsigned int)_charucoIds.getMat(i).total(); + CV_Assert(nCorners > 0 && nCorners == _charucoCorners.getMat(i).total()); //actually nCorners must be > 3 for calibration + allObjPoints[i].reserve(nCorners); + + for(unsigned int j = 0; j < nCorners; j++) { + int pointId = _charucoIds.getMat(i).ptr< int >(0)[j]; + CV_Assert(pointId >= 0 && pointId < (int)_board->chessboardCorners.size()); + allObjPoints[i].push_back(_board->chessboardCorners[pointId]); + } + } + + return cvfork::calibrateCamera(allObjPoints, _charucoCorners, imageSize, _cameraMatrix, _distCoeffs, + _rvecs, _tvecs, _stdDeviations, _perViewErrors, flags, criteria); +} + + +static void subMatrix(const cv::Mat& src, cv::Mat& dst, const std::vector& cols, + const std::vector& rows) { + int nonzeros_cols = cv::countNonZero(cols); + cv::Mat tmp(src.rows, nonzeros_cols, CV_64FC1); + + for (int i = 0, j = 0; i < (int)cols.size(); i++) + { + if (cols[i]) + { + src.col(i).copyTo(tmp.col(j++)); + } + } + + int nonzeros_rows = cv::countNonZero(rows); + dst.create(nonzeros_rows, nonzeros_cols, CV_64FC1); + for (int i = 0, j = 0; i < (int)rows.size(); i++) + { + if (rows[i]) + { + tmp.row(i).copyTo(dst.row(j++)); + } + } +} + +void cvfork::CvLevMarqFork::step() +{ + using namespace cv; + const double LOG10 = log(10.); + double lambda = exp(lambdaLg10*LOG10); + int nparams = param->rows; + + Mat _JtJ = cvarrToMat(JtJ); + Mat _mask = cvarrToMat(mask); + + int nparams_nz = countNonZero(_mask); + if(!JtJN || JtJN->rows != nparams_nz) { + // prevent re-allocation in every step + JtJN.reset(cvCreateMat( nparams_nz, nparams_nz, CV_64F )); + JtJV.reset(cvCreateMat( nparams_nz, 1, CV_64F )); + JtJW.reset(cvCreateMat( nparams_nz, 1, CV_64F )); + } + + Mat _JtJN = cvarrToMat(JtJN); + Mat _JtErr = cvarrToMat(JtJV); + Mat_ nonzero_param = cvarrToMat(JtJW); + + subMatrix(cvarrToMat(JtErr), _JtErr, std::vector(1, 1), _mask); + subMatrix(_JtJ, _JtJN, _mask, _mask); + + if( !err ) + completeSymm( _JtJN, completeSymmFlag ); +#if 1 + _JtJN.diag() *= 1. + lambda; +#else + _JtJN.diag() += lambda; +#endif +#ifndef USE_LAPACK + cv::solve(_JtJN, _JtErr, nonzero_param, solveMethod); +#else + cvfork::solve(_JtJN, _JtErr, nonzero_param, solveMethod); +#endif + + int j = 0; + for( int i = 0; i < nparams; i++ ) + param->data.db[i] = prevParam->data.db[i] - (mask->data.ptr[i] ? nonzero_param(j++) : 0); +} + +cvfork::CvLevMarqFork::CvLevMarqFork(int nparams, int nerrs, CvTermCriteria criteria0, bool _completeSymmFlag) +{ + init(nparams, nerrs, criteria0, _completeSymmFlag); +} + +cvfork::CvLevMarqFork::~CvLevMarqFork() +{ + clear(); +} + +bool cvfork::CvLevMarqFork::updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, double*& _errNorm ) +{ + CV_Assert( !err ); + if( state == DONE ) + { + _param = param; + return false; + } + + if( state == STARTED ) + { + _param = param; + cvZero( JtJ ); + cvZero( JtErr ); + errNorm = 0; + _JtJ = JtJ; + _JtErr = JtErr; + _errNorm = &errNorm; + state = CALC_J; + return true; + } + + if( state == CALC_J ) + { + cvCopy( param, prevParam ); + step(); + _param = param; + prevErrNorm = errNorm; + errNorm = 0; + _errNorm = &errNorm; + state = CHECK_ERR; + return true; + } + + assert( state == CHECK_ERR ); + if( errNorm > prevErrNorm ) + { + if( ++lambdaLg10 <= 16 ) + { + step(); + _param = param; + errNorm = 0; + _errNorm = &errNorm; + state = CHECK_ERR; + return true; + } + } + + lambdaLg10 = MAX(lambdaLg10-1, -16); + if( ++iters >= criteria.max_iter || + cvNorm(param, prevParam, CV_RELATIVE_L2) < criteria.epsilon ) + { + //printf("iters %i\n", iters); + _param = param; + state = DONE; + return false; + } + + prevErrNorm = errNorm; + cvZero( JtJ ); + cvZero( JtErr ); + _param = param; + _JtJ = JtJ; + _JtErr = JtErr; + state = CALC_J; + return true; +} diff --git a/apps/interactive-calibration/cvCalibrationFork.hpp b/apps/interactive-calibration/cvCalibrationFork.hpp new file mode 100644 index 0000000000..075f251ef5 --- /dev/null +++ b/apps/interactive-calibration/cvCalibrationFork.hpp @@ -0,0 +1,56 @@ +#ifndef CV_CALIBRATION_FORK_HPP +#define CV_CALIBRATION_FORK_HPP + +#include +#include +#include +#include + +namespace cvfork +{ +using namespace cv; + +#define CV_CALIB_NINTRINSIC 18 +#define CALIB_USE_QR (1 << 18) + +double calibrateCamera(InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, OutputArray stdDeviations, + OutputArray perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +double cvCalibrateCamera2( const CvMat* object_points, + const CvMat* image_points, + const CvMat* point_counts, + CvSize image_size, + CvMat* camera_matrix, + CvMat* distortion_coeffs, + CvMat* rotation_vectors CV_DEFAULT(NULL), + CvMat* translation_vectors CV_DEFAULT(NULL), + CvMat* stdDeviations_vector CV_DEFAULT(NULL), + CvMat* perViewErrors_vector CV_DEFAULT(NULL), + int flags CV_DEFAULT(0), + CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( + CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); + +double calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfArrays _charucoIds, + Ptr &_board, Size imageSize, + InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, OutputArray _stdDeviations, OutputArray _perViewErrors, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +class CvLevMarqFork : public CvLevMarq +{ +public: + CvLevMarqFork( int nparams, int nerrs, CvTermCriteria criteria= + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); + bool updateAlt( const CvMat*& _param, CvMat*& _JtJ, CvMat*& _JtErr, double*& _errNorm ); + void step(); + ~CvLevMarqFork(); +}; +} + +#endif diff --git a/apps/interactive-calibration/defaultConfig.xml b/apps/interactive-calibration/defaultConfig.xml new file mode 100644 index 0000000000..d14ba865d3 --- /dev/null +++ b/apps/interactive-calibration/defaultConfig.xml @@ -0,0 +1,14 @@ + + +0 +200 +100 +1 +30 +10 +1e-7 +30 +0 +0.1 +800 600 + \ No newline at end of file diff --git a/apps/interactive-calibration/frameProcessor.cpp b/apps/interactive-calibration/frameProcessor.cpp new file mode 100644 index 0000000000..bef130ef3b --- /dev/null +++ b/apps/interactive-calibration/frameProcessor.cpp @@ -0,0 +1,518 @@ +#include "frameProcessor.hpp" +#include "rotationConverters.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace calib; + +#define VIDEO_TEXT_SIZE 4 +#define POINT_SIZE 5 + +static cv::SimpleBlobDetector::Params getDetectorParams() +{ + cv::SimpleBlobDetector::Params detectorParams; + + detectorParams.thresholdStep = 40; + detectorParams.minThreshold = 20; + detectorParams.maxThreshold = 500; + detectorParams.minRepeatability = 2; + detectorParams.minDistBetweenBlobs = 5; + + detectorParams.filterByColor = true; + detectorParams.blobColor = 0; + + detectorParams.filterByArea = true; + detectorParams.minArea = 5; + detectorParams.maxArea = 5000; + + detectorParams.filterByCircularity = false; + detectorParams.minCircularity = 0.8f; + detectorParams.maxCircularity = std::numeric_limits::max(); + + detectorParams.filterByInertia = true; + detectorParams.minInertiaRatio = 0.1f; + detectorParams.maxInertiaRatio = std::numeric_limits::max(); + + detectorParams.filterByConvexity = true; + detectorParams.minConvexity = 0.8f; + detectorParams.maxConvexity = std::numeric_limits::max(); + + return detectorParams; +} + +FrameProcessor::~FrameProcessor() +{ + +} + +bool CalibProcessor::detectAndParseChessboard(const cv::Mat &frame) +{ + int chessBoardFlags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE | cv::CALIB_CB_FAST_CHECK; + bool isTemplateFound = cv::findChessboardCorners(frame, mBoardSize, mCurrentImagePoints, chessBoardFlags); + + if (isTemplateFound) { + cv::Mat viewGray; + cv::cvtColor(frame, viewGray, cv::COLOR_BGR2GRAY); + cv::cornerSubPix(viewGray, mCurrentImagePoints, cv::Size(11,11), + cv::Size(-1,-1), cv::TermCriteria( cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 30, 0.1 )); + cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isTemplateFound); + mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); + } + return isTemplateFound; +} + +bool CalibProcessor::detectAndParseChAruco(const cv::Mat &frame) +{ + cv::Ptr board = mCharucoBoard.staticCast(); + + std::vector > corners, rejected; + std::vector ids; + cv::aruco::detectMarkers(frame, mArucoDictionary, corners, ids, cv::aruco::DetectorParameters::create(), rejected); + cv::aruco::refineDetectedMarkers(frame, board, corners, ids, rejected); + cv::Mat currentCharucoCorners, currentCharucoIds; + if(ids.size() > 0) + cv::aruco::interpolateCornersCharuco(corners, ids, frame, mCharucoBoard, currentCharucoCorners, + currentCharucoIds); + if(ids.size() > 0) cv::aruco::drawDetectedMarkers(frame, corners); + + if(currentCharucoCorners.total() > 3) { + float centerX = 0, centerY = 0; + for (int i = 0; i < currentCharucoCorners.size[0]; i++) { + centerX += currentCharucoCorners.at(i, 0); + centerY += currentCharucoCorners.at(i, 1); + } + centerX /= currentCharucoCorners.size[0]; + centerY /= currentCharucoCorners.size[0]; + //cv::circle(frame, cv::Point2f(centerX, centerY), 10, cv::Scalar(0, 255, 0), 10); + mTemplateLocations.insert(mTemplateLocations.begin(), cv::Point2f(centerX, centerY)); + cv::aruco::drawDetectedCornersCharuco(frame, currentCharucoCorners, currentCharucoIds); + mCurrentCharucoCorners = currentCharucoCorners; + mCurrentCharucoIds = currentCharucoIds; + return true; + } + + return false; +} + +bool CalibProcessor::detectAndParseACircles(const cv::Mat &frame) +{ + bool isTemplateFound = findCirclesGrid(frame, mBoardSize, mCurrentImagePoints, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); + if(isTemplateFound) { + mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); + cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isTemplateFound); + } + return isTemplateFound; +} + +bool CalibProcessor::detectAndParseDualACircles(const cv::Mat &frame) +{ + std::vector blackPointbuf; + + cv::Mat invertedView; + cv::bitwise_not(frame, invertedView); + bool isWhiteGridFound = cv::findCirclesGrid(frame, mBoardSize, mCurrentImagePoints, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); + if(!isWhiteGridFound) + return false; + bool isBlackGridFound = cv::findCirclesGrid(invertedView, mBoardSize, blackPointbuf, cv::CALIB_CB_ASYMMETRIC_GRID, mBlobDetectorPtr); + + if(!isBlackGridFound) + { + mCurrentImagePoints.clear(); + return false; + } + cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isWhiteGridFound); + cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(blackPointbuf), isBlackGridFound); + mCurrentImagePoints.insert(mCurrentImagePoints.end(), blackPointbuf.begin(), blackPointbuf.end()); + mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]); + + return true; +} + +void CalibProcessor::saveFrameData() +{ + std::vector objectPoints; + + switch(mBoardType) + { + case Chessboard: + objectPoints.reserve(mBoardSize.height*mBoardSize.width); + for( int i = 0; i < mBoardSize.height; ++i ) + for( int j = 0; j < mBoardSize.width; ++j ) + objectPoints.push_back(cv::Point3f(j*mSquareSize, i*mSquareSize, 0)); + mCalibData->imagePoints.push_back(mCurrentImagePoints); + mCalibData->objectPoints.push_back(objectPoints); + break; + case chAruco: + mCalibData->allCharucoCorners.push_back(mCurrentCharucoCorners); + mCalibData->allCharucoIds.push_back(mCurrentCharucoIds); + break; + case AcirclesGrid: + objectPoints.reserve(mBoardSize.height*mBoardSize.width); + for( int i = 0; i < mBoardSize.height; i++ ) + for( int j = 0; j < mBoardSize.width; j++ ) + objectPoints.push_back(cv::Point3f((2*j + i % 2)*mSquareSize, i*mSquareSize, 0)); + mCalibData->imagePoints.push_back(mCurrentImagePoints); + mCalibData->objectPoints.push_back(objectPoints); + break; + case DoubleAcirclesGrid: + { + float gridCenterX = (2*((float)mBoardSize.width - 1) + 1)*mSquareSize + mTemplDist / 2; + float gridCenterY = (mBoardSize.height - 1)*mSquareSize / 2; + objectPoints.reserve(2*mBoardSize.height*mBoardSize.width); + + //white part + for( int i = 0; i < mBoardSize.height; i++ ) + for( int j = 0; j < mBoardSize.width; j++ ) + objectPoints.push_back( + cv::Point3f(-float((2*j + i % 2)*mSquareSize + mTemplDist + + (2*(mBoardSize.width - 1) + 1)*mSquareSize - gridCenterX), + -float(i*mSquareSize) - gridCenterY, + 0)); + //black part + for( int i = 0; i < mBoardSize.height; i++ ) + for( int j = 0; j < mBoardSize.width; j++ ) + objectPoints.push_back(cv::Point3f(-float((2*j + i % 2)*mSquareSize - gridCenterX), + -float(i*mSquareSize) - gridCenterY, 0)); + + mCalibData->imagePoints.push_back(mCurrentImagePoints); + mCalibData->objectPoints.push_back(objectPoints); + } + break; + } +} + +void CalibProcessor::showCaptureMessage(const cv::Mat& frame, const std::string &message) +{ + cv::Point textOrigin(100, 100); + double textSize = VIDEO_TEXT_SIZE * frame.cols / (double) IMAGE_MAX_WIDTH; + cv::bitwise_not(frame, frame); + cv::putText(frame, message, textOrigin, 1, textSize, cv::Scalar(0,0,255), 2, cv::LINE_AA); + cv::imshow(mainWindowName, frame); + cv::waitKey(300); +} + +bool CalibProcessor::checkLastFrame() +{ + bool isFrameBad = false; + cv::Mat tmpCamMatrix; + const double badAngleThresh = 40; + + if(!mCalibData->cameraMatrix.total()) { + tmpCamMatrix = cv::Mat::eye(3, 3, CV_64F); + tmpCamMatrix.at(0,0) = 20000; + tmpCamMatrix.at(1,1) = 20000; + tmpCamMatrix.at(0,2) = mCalibData->imageSize.height/2; + tmpCamMatrix.at(1,2) = mCalibData->imageSize.width/2; + } + else + mCalibData->cameraMatrix.copyTo(tmpCamMatrix); + + if(mBoardType != chAruco) { + cv::Mat r, t, angles; + cv::solvePnP(mCalibData->objectPoints.back(), mCurrentImagePoints, tmpCamMatrix, mCalibData->distCoeffs, r, t); + RodriguesToEuler(r, angles, CALIB_DEGREES); + + if(fabs(angles.at(0)) > badAngleThresh || fabs(angles.at(1)) > badAngleThresh) { + mCalibData->objectPoints.pop_back(); + mCalibData->imagePoints.pop_back(); + isFrameBad = true; + } + } + else { + cv::Mat r, t, angles; + std::vector allObjPoints; + allObjPoints.reserve(mCurrentCharucoIds.total()); + for(size_t i = 0; i < mCurrentCharucoIds.total(); i++) { + int pointID = mCurrentCharucoIds.at((int)i); + CV_Assert(pointID >= 0 && pointID < (int)mCharucoBoard->chessboardCorners.size()); + allObjPoints.push_back(mCharucoBoard->chessboardCorners[pointID]); + } + + cv::solvePnP(allObjPoints, mCurrentCharucoCorners, tmpCamMatrix, mCalibData->distCoeffs, r, t); + RodriguesToEuler(r, angles, CALIB_DEGREES); + + if(180.0 - fabs(angles.at(0)) > badAngleThresh || fabs(angles.at(1)) > badAngleThresh) { + isFrameBad = true; + mCalibData->allCharucoCorners.pop_back(); + mCalibData->allCharucoIds.pop_back(); + } + } + return isFrameBad; +} + +CalibProcessor::CalibProcessor(cv::Ptr data, captureParameters &capParams) : + mCalibData(data), mBoardType(capParams.board), mBoardSize(capParams.boardSize) +{ + mCapuredFrames = 0; + mNeededFramesNum = capParams.calibrationStep; + mDelayBetweenCaptures = static_cast(capParams.captureDelay * capParams.fps); + mMaxTemplateOffset = std::sqrt(std::pow(mCalibData->imageSize.height, 2) + + std::pow(mCalibData->imageSize.width, 2)) / 20.0; + mSquareSize = capParams.squareSize; + mTemplDist = capParams.templDst; + + switch(mBoardType) + { + case chAruco: + mArucoDictionary = cv::aruco::getPredefinedDictionary( + cv::aruco::PREDEFINED_DICTIONARY_NAME(capParams.charucoDictName)); + mCharucoBoard = cv::aruco::CharucoBoard::create(mBoardSize.width, mBoardSize.height, capParams.charucoSquareLenght, + capParams.charucoMarkerSize, mArucoDictionary); + break; + case AcirclesGrid: + mBlobDetectorPtr = cv::SimpleBlobDetector::create(); + break; + case DoubleAcirclesGrid: + mBlobDetectorPtr = cv::SimpleBlobDetector::create(getDetectorParams()); + break; + case Chessboard: + break; + } +} + +cv::Mat CalibProcessor::processFrame(const cv::Mat &frame) +{ + cv::Mat frameCopy; + frame.copyTo(frameCopy); + bool isTemplateFound = false; + mCurrentImagePoints.clear(); + + switch(mBoardType) + { + case Chessboard: + isTemplateFound = detectAndParseChessboard(frameCopy); + break; + case chAruco: + isTemplateFound = detectAndParseChAruco(frameCopy); + break; + case AcirclesGrid: + isTemplateFound = detectAndParseACircles(frameCopy); + break; + case DoubleAcirclesGrid: + isTemplateFound = detectAndParseDualACircles(frameCopy); + break; + } + + if(mTemplateLocations.size() > mDelayBetweenCaptures) + mTemplateLocations.pop_back(); + if(mTemplateLocations.size() == mDelayBetweenCaptures && isTemplateFound) { + if(cv::norm(mTemplateLocations.front() - mTemplateLocations.back()) < mMaxTemplateOffset) { + saveFrameData(); + bool isFrameBad = checkLastFrame(); + if (!isFrameBad) { + std::string displayMessage = cv::format("Frame # %d captured", std::max(mCalibData->imagePoints.size(), + mCalibData->allCharucoCorners.size())); + if(!showOverlayMessage(displayMessage)) + showCaptureMessage(frame, displayMessage); + mCapuredFrames++; + } + else { + std::string displayMessage = "Frame rejected"; + if(!showOverlayMessage(displayMessage)) + showCaptureMessage(frame, displayMessage); + } + mTemplateLocations.clear(); + mTemplateLocations.reserve(mDelayBetweenCaptures); + } + } + + return frameCopy; +} + +bool CalibProcessor::isProcessed() const +{ + if(mCapuredFrames < mNeededFramesNum) + return false; + else + return true; +} + +void CalibProcessor::resetState() +{ + mCapuredFrames = 0; + mTemplateLocations.clear(); +} + +CalibProcessor::~CalibProcessor() +{ + +} + +//////////////////////////////////////////// + +void ShowProcessor::drawBoard(cv::Mat &img, cv::InputArray points) +{ + cv::Mat tmpView = cv::Mat::zeros(img.rows, img.cols, CV_8UC3); + std::vector templateHull; + std::vector poly; + cv::convexHull(points, templateHull); + poly.resize(templateHull.size()); + for(size_t i=0; i >::iterator it = mCalibdata->imagePoints.begin(); it != mCalibdata->imagePoints.end(); ++it) + for(std::vector::iterator pointIt = (*it).begin(); pointIt != (*it).end(); ++pointIt) + cv::circle(frame, *pointIt, POINT_SIZE, cv::Scalar(0, 255, 0), 1, cv::LINE_AA); + else + for(std::vector::iterator it = mCalibdata->allCharucoCorners.begin(); it != mCalibdata->allCharucoCorners.end(); ++it) + for(int i = 0; i < (*it).size[0]; i++) + cv::circle(frame, cv::Point((int)(*it).at(i, 0), (int)(*it).at(i, 1)), + POINT_SIZE, cv::Scalar(0, 255, 0), 1, cv::LINE_AA); +} + +ShowProcessor::ShowProcessor(cv::Ptr data, cv::Ptr controller, TemplateType board) : + mCalibdata(data), mController(controller), mBoardType(board) +{ + mNeedUndistort = true; + mVisMode = Grid; + mGridViewScale = 0.5; + mTextSize = VIDEO_TEXT_SIZE; +} + +cv::Mat ShowProcessor::processFrame(const cv::Mat &frame) +{ + if(mCalibdata->cameraMatrix.size[0] && mCalibdata->distCoeffs.size[0]) { + mTextSize = VIDEO_TEXT_SIZE * (double) frame.cols / IMAGE_MAX_WIDTH; + cv::Scalar textColor = cv::Scalar(0,0,255); + cv::Mat frameCopy; + + if (mNeedUndistort && mController->getFramesNumberState()) { + if(mVisMode == Grid) + drawGridPoints(frame); + cv::remap(frame, frameCopy, mCalibdata->undistMap1, mCalibdata->undistMap2, cv::INTER_LINEAR); + int baseLine = 100; + cv::Size textSize = cv::getTextSize("Undistorted view", 1, mTextSize, 2, &baseLine); + cv::Point textOrigin(baseLine, frame.rows - (int)(2.5*textSize.height)); + cv::putText(frameCopy, "Undistorted view", textOrigin, 1, mTextSize, textColor, 2, cv::LINE_AA); + } + else { + frame.copyTo(frameCopy); + if(mVisMode == Grid) + drawGridPoints(frameCopy); + } + std::string displayMessage; + if(mCalibdata->stdDeviations.at(0) == 0) + displayMessage = cv::format("F = %d RMS = %.3f", (int)mCalibdata->cameraMatrix.at(0,0), mCalibdata->totalAvgErr); + else + displayMessage = cv::format("Fx = %d Fy = %d RMS = %.3f", (int)mCalibdata->cameraMatrix.at(0,0), + (int)mCalibdata->cameraMatrix.at(1,1), mCalibdata->totalAvgErr); + if(mController->getRMSState() && mController->getFramesNumberState()) + displayMessage.append(" OK"); + + int baseLine = 100; + cv::Size textSize = cv::getTextSize(displayMessage, 1, mTextSize - 1, 2, &baseLine); + cv::Point textOrigin = cv::Point(baseLine, 2*textSize.height); + cv::putText(frameCopy, displayMessage, textOrigin, 1, mTextSize - 1, textColor, 2, cv::LINE_AA); + + if(mCalibdata->stdDeviations.at(0) == 0) + displayMessage = cv::format("DF = %.2f", mCalibdata->stdDeviations.at(1)*sigmaMult); + else + displayMessage = cv::format("DFx = %.2f DFy = %.2f", mCalibdata->stdDeviations.at(0)*sigmaMult, + mCalibdata->stdDeviations.at(1)*sigmaMult); + if(mController->getConfidenceIntrervalsState() && mController->getFramesNumberState()) + displayMessage.append(" OK"); + cv::putText(frameCopy, displayMessage, cv::Point(baseLine, 4*textSize.height), 1, mTextSize - 1, textColor, 2, cv::LINE_AA); + + if(mController->getCommonCalibrationState()) { + displayMessage = cv::format("Calibration is done"); + cv::putText(frameCopy, displayMessage, cv::Point(baseLine, 6*textSize.height), 1, mTextSize - 1, textColor, 2, cv::LINE_AA); + } + int calibFlags = mController->getNewFlags(); + displayMessage = ""; + if(!(calibFlags & cv::CALIB_FIX_ASPECT_RATIO)) + displayMessage.append(cv::format("AR=%.3f ", mCalibdata->cameraMatrix.at(0,0)/mCalibdata->cameraMatrix.at(1,1))); + if(calibFlags & cv::CALIB_ZERO_TANGENT_DIST) + displayMessage.append("TD=0 "); + displayMessage.append(cv::format("K1=%.2f K2=%.2f K3=%.2f", mCalibdata->distCoeffs.at(0), mCalibdata->distCoeffs.at(1), + mCalibdata->distCoeffs.at(4))); + cv::putText(frameCopy, displayMessage, cv::Point(baseLine, frameCopy.rows - (int)(1.5*textSize.height)), + 1, mTextSize - 1, textColor, 2, cv::LINE_AA); + return frameCopy; + } + + return frame; +} + +bool ShowProcessor::isProcessed() const +{ + return false; +} + +void ShowProcessor::resetState() +{ + +} + +void ShowProcessor::setVisualizationMode(visualisationMode mode) +{ + mVisMode = mode; +} + +void ShowProcessor::switchVisualizationMode() +{ + if(mVisMode == Grid) { + mVisMode = Window; + updateBoardsView(); + } + else { + mVisMode = Grid; + cv::destroyWindow(gridWindowName); + } +} + +void ShowProcessor::clearBoardsView() +{ + cv::imshow(gridWindowName, cv::Mat()); +} + +void ShowProcessor::updateBoardsView() +{ + if(mVisMode == Window) { + cv::Size originSize = mCalibdata->imageSize; + cv::Mat altGridView = cv::Mat::zeros((int)(originSize.height*mGridViewScale), (int)(originSize.width*mGridViewScale), CV_8UC3); + if(mBoardType != chAruco) + for(std::vector >::iterator it = mCalibdata->imagePoints.begin(); it != mCalibdata->imagePoints.end(); ++it) + if(mBoardType != DoubleAcirclesGrid) + drawBoard(altGridView, *it); + else { + size_t pointsNum = (*it).size()/2; + std::vector points(pointsNum); + std::copy((*it).begin(), (*it).begin() + pointsNum, points.begin()); + drawBoard(altGridView, points); + std::copy((*it).begin() + pointsNum, (*it).begin() + 2*pointsNum, points.begin()); + drawBoard(altGridView, points); + } + else + for(std::vector::iterator it = mCalibdata->allCharucoCorners.begin(); it != mCalibdata->allCharucoCorners.end(); ++it) + drawBoard(altGridView, *it); + cv::imshow(gridWindowName, altGridView); + } +} + +void ShowProcessor::switchUndistort() +{ + mNeedUndistort = !mNeedUndistort; +} + +void ShowProcessor::setUndistort(bool isEnabled) +{ + mNeedUndistort = isEnabled; +} + +ShowProcessor::~ShowProcessor() +{ + +} diff --git a/apps/interactive-calibration/frameProcessor.hpp b/apps/interactive-calibration/frameProcessor.hpp new file mode 100644 index 0000000000..119910ad46 --- /dev/null +++ b/apps/interactive-calibration/frameProcessor.hpp @@ -0,0 +1,95 @@ +#ifndef FRAME_PROCESSOR_HPP +#define FRAME_PROCESSOR_HPP + +#include +#include +#include +#include "calibCommon.hpp" +#include "calibController.hpp" + +namespace calib +{ +class FrameProcessor +{ +protected: + +public: + virtual ~FrameProcessor(); + virtual cv::Mat processFrame(const cv::Mat& frame) = 0; + virtual bool isProcessed() const = 0; + virtual void resetState() = 0; +}; + +class CalibProcessor : public FrameProcessor +{ +protected: + cv::Ptr mCalibData; + TemplateType mBoardType; + cv::Size mBoardSize; + std::vector mTemplateLocations; + std::vector mCurrentImagePoints; + cv::Mat mCurrentCharucoCorners; + cv::Mat mCurrentCharucoIds; + + cv::Ptr mBlobDetectorPtr; + cv::Ptr mArucoDictionary; + cv::Ptr mCharucoBoard; + + int mNeededFramesNum; + unsigned mDelayBetweenCaptures; + int mCapuredFrames; + double mMaxTemplateOffset; + float mSquareSize; + float mTemplDist; + + bool detectAndParseChessboard(const cv::Mat& frame); + bool detectAndParseChAruco(const cv::Mat& frame); + bool detectAndParseACircles(const cv::Mat& frame); + bool detectAndParseDualACircles(const cv::Mat& frame); + void saveFrameData(); + void showCaptureMessage(const cv::Mat &frame, const std::string& message); + bool checkLastFrame(); + +public: + CalibProcessor(cv::Ptr data, captureParameters& capParams); + virtual cv::Mat processFrame(const cv::Mat& frame); + virtual bool isProcessed() const; + virtual void resetState(); + ~CalibProcessor(); +}; + +enum visualisationMode {Grid, Window}; + +class ShowProcessor : public FrameProcessor +{ +protected: + cv::Ptr mCalibdata; + cv::Ptr mController; + TemplateType mBoardType; + visualisationMode mVisMode; + bool mNeedUndistort; + double mGridViewScale; + double mTextSize; + + void drawBoard(cv::Mat& img, cv::InputArray points); + void drawGridPoints(const cv::Mat& frame); +public: + ShowProcessor(cv::Ptr data, cv::Ptr controller, TemplateType board); + virtual cv::Mat processFrame(const cv::Mat& frame); + virtual bool isProcessed() const; + virtual void resetState(); + + void setVisualizationMode(visualisationMode mode); + void switchVisualizationMode(); + void clearBoardsView(); + void updateBoardsView(); + + void switchUndistort(); + void setUndistort(bool isEnabled); + ~ShowProcessor(); +}; + +} + + +#endif diff --git a/apps/interactive-calibration/linalg.cpp b/apps/interactive-calibration/linalg.cpp new file mode 100644 index 0000000000..e75b4d2d93 --- /dev/null +++ b/apps/interactive-calibration/linalg.cpp @@ -0,0 +1,491 @@ +#include "linalg.hpp" + +#ifdef USE_LAPACK + +typedef int integer; +#include + +#include +using namespace cv; + +bool cvfork::solve(InputArray _src, const InputArray _src2arg, OutputArray _dst, int method ) + { + bool result = true; + Mat src = _src.getMat(), _src2 = _src2arg.getMat(); + int type = src.type(); + bool is_normal = (method & DECOMP_NORMAL) != 0; + + CV_Assert( type == _src2.type() && (type == CV_32F || type == CV_64F) ); + + method &= ~DECOMP_NORMAL; + CV_Assert( (method != DECOMP_LU && method != DECOMP_CHOLESKY) || + is_normal || src.rows == src.cols ); + + double rcond=-1, s1=0, work1=0, *work=0, *s=0; + float frcond=-1, fs1=0, fwork1=0, *fwork=0, *fs=0; + integer m = src.rows, m_ = m, n = src.cols, mn = std::max(m,n), + nm = std::min(m, n), nb = _src2.cols, lwork=-1, liwork=0, iwork1=0, + lda = m, ldx = mn, info=0, rank=0, *iwork=0; + int elem_size = CV_ELEM_SIZE(type); + bool copy_rhs=false; + int buf_size=0; + AutoBuffer buffer; + uchar* ptr; + char N[] = {'N', '\0'}, L[] = {'L', '\0'}; + + Mat src2 = _src2; + _dst.create( src.cols, src2.cols, src.type() ); + Mat dst = _dst.getMat(); + + if( m <= n ) + is_normal = false; + else if( is_normal ) + m_ = n; + + buf_size += (is_normal ? n*n : m*n)*elem_size; + + if( m_ != n || nb > 1 || !dst.isContinuous() ) + { + copy_rhs = true; + if( is_normal ) + buf_size += n*nb*elem_size; + else + buf_size += mn*nb*elem_size; + } + + if( method == DECOMP_SVD || method == DECOMP_EIG ) + { + integer nlvl = cvRound(std::log(std::max(std::min(m_,n)/25., 1.))/CV_LOG2) + 1; + liwork = std::min(m_,n)*(3*std::max(nlvl,(integer)0) + 11); + + if( type == CV_32F ) + sgelsd_(&m_, &n, &nb, (float*)src.data, &lda, (float*)dst.data, &ldx, + &fs1, &frcond, &rank, &fwork1, &lwork, &iwork1, &info); + else + dgelsd_(&m_, &n, &nb, (double*)src.data, &lda, (double*)dst.data, &ldx, + &s1, &rcond, &rank, &work1, &lwork, &iwork1, &info ); + buf_size += nm*elem_size + (liwork + 1)*sizeof(integer); + } + else if( method == DECOMP_QR ) + { + if( type == CV_32F ) + sgels_(N, &m_, &n, &nb, (float*)src.data, &lda, + (float*)dst.data, &ldx, &fwork1, &lwork, &info ); + else + dgels_(N, &m_, &n, &nb, (double*)src.data, &lda, + (double*)dst.data, &ldx, &work1, &lwork, &info ); + } + else if( method == DECOMP_LU ) + { + buf_size += (n+1)*sizeof(integer); + } + else if( method == DECOMP_CHOLESKY ) + ; + else + CV_Error( Error::StsBadArg, "Unknown method" ); + assert(info == 0); + + lwork = cvRound(type == CV_32F ? (double)fwork1 : work1); + buf_size += lwork*elem_size; + buffer.allocate(buf_size); + ptr = (uchar*)buffer; + + Mat at(n, m_, type, ptr); + ptr += n*m_*elem_size; + + if( method == DECOMP_CHOLESKY || method == DECOMP_EIG ) + src.copyTo(at); + else if( !is_normal ) + transpose(src, at); + else + mulTransposed(src, at, true); + + Mat xt; + if( !is_normal ) + { + if( copy_rhs ) + { + Mat temp(nb, mn, type, ptr); + ptr += nb*mn*elem_size; + Mat bt = temp.colRange(0, m); + xt = temp.colRange(0, n); + transpose(src2, bt); + } + else + { + src2.copyTo(dst); + xt = Mat(1, n, type, dst.data); + } + } + else + { + if( copy_rhs ) + { + xt = Mat(nb, n, type, ptr); + ptr += nb*n*elem_size; + } + else + xt = Mat(1, n, type, dst.data); + // (a'*b)' = b'*a + gemm( src2, src, 1, Mat(), 0, xt, GEMM_1_T ); + } + + lda = (int)(at.step ? at.step/elem_size : at.cols); + ldx = (int)(xt.step ? xt.step/elem_size : (!is_normal && copy_rhs ? mn : n)); + + if( method == DECOMP_SVD || method == DECOMP_EIG ) + { + if( type == CV_32F ) + { + fs = (float*)ptr; + ptr += nm*elem_size; + fwork = (float*)ptr; + ptr += lwork*elem_size; + iwork = (integer*)alignPtr(ptr, sizeof(integer)); + + sgelsd_(&m_, &n, &nb, (float*)at.data, &lda, (float*)xt.data, &ldx, + fs, &frcond, &rank, fwork, &lwork, iwork, &info); + } + else + { + s = (double*)ptr; + ptr += nm*elem_size; + work = (double*)ptr; + ptr += lwork*elem_size; + iwork = (integer*)alignPtr(ptr, sizeof(integer)); + + dgelsd_(&m_, &n, &nb, (double*)at.data, &lda, (double*)xt.data, &ldx, + s, &rcond, &rank, work, &lwork, iwork, &info); + } + } + else if( method == DECOMP_QR ) + { + if( type == CV_32F ) + { + fwork = (float*)ptr; + sgels_(N, &m_, &n, &nb, (float*)at.data, &lda, + (float*)xt.data, &ldx, fwork, &lwork, &info); + } + else + { + work = (double*)ptr; + dgels_(N, &m_, &n, &nb, (double*)at.data, &lda, + (double*)xt.data, &ldx, work, &lwork, &info); + } + } + else if( method == DECOMP_CHOLESKY || (method == DECOMP_LU && is_normal) ) + { + if( type == CV_32F ) + { + spotrf_(L, &n, (float*)at.data, &lda, &info); + if(info==0) + spotrs_(L, &n, &nb, (float*)at.data, &lda, (float*)xt.data, &ldx, &info); + } + else + { + dpotrf_(L, &n, (double*)at.data, &lda, &info); + if(info==0) + dpotrs_(L, &n, &nb, (double*)at.data, &lda, (double*)xt.data, &ldx, &info); + } + } + else if( method == DECOMP_LU ) + { + iwork = (integer*)alignPtr(ptr, sizeof(integer)); + if( type == CV_32F ) + sgesv_(&n, &nb, (float*)at.data, &lda, iwork, (float*)xt.data, &ldx, &info ); + else + dgesv_(&n, &nb, (double*)at.data, &lda, iwork, (double*)xt.data, &ldx, &info ); + } + else + assert(0); + result = info == 0; + + if( !result ) + dst = Scalar(0); + else if( xt.data != dst.data ) + transpose( xt, dst ); + + return result; + } + +static void _SVDcompute( const InputArray _aarr, OutputArray _w, + OutputArray _u, OutputArray _vt, int flags = 0) +{ + Mat a = _aarr.getMat(), u, vt; + integer m = a.rows, n = a.cols, mn = std::max(m, n), nm = std::min(m, n); + int type = a.type(), elem_size = (int)a.elemSize(); + bool compute_uv = _u.needed() || _vt.needed(); + + if( flags & SVD::NO_UV ) + { + _u.release(); + _vt.release(); + compute_uv = false; + } + + if( compute_uv ) + { + _u.create( (int)m, (int)((flags & SVD::FULL_UV) ? m : nm), type ); + _vt.create( (int)((flags & SVD::FULL_UV) ? n : nm), n, type ); + u = _u.getMat(); + vt = _vt.getMat(); + } + + _w.create(nm, 1, type, -1, true); + + Mat _a = a, w = _w.getMat(); + CV_Assert( w.isContinuous() ); + int work_ofs=0, iwork_ofs=0, buf_size = 0; + bool temp_a = false; + double u1=0, v1=0, work1=0; + float uf1=0, vf1=0, workf1=0; + integer lda, ldu, ldv, lwork=-1, iwork1=0, info=0; + char mode[] = {compute_uv ? 'S' : 'N', '\0'}; + + if( m != n && compute_uv && (flags & SVD::FULL_UV) ) + mode[0] = 'A'; + + if( !(flags & SVD::MODIFY_A) ) + { + if( mode[0] == 'N' || mode[0] == 'A' ) + temp_a = true; + else if( compute_uv && (a.size() == vt.size() || a.size() == u.size()) && mode[0] == 'S' ) + mode[0] = 'O'; + } + + lda = a.cols; + ldv = ldu = mn; + + if( type == CV_32F ) + { + sgesdd_(mode, &n, &m, (float*)a.data, &lda, (float*)w.data, + &vf1, &ldv, &uf1, &ldu, &workf1, &lwork, &iwork1, &info ); + lwork = cvRound(workf1); + } + else + { + dgesdd_(mode, &n, &m, (double*)a.data, &lda, (double*)w.data, + &v1, &ldv, &u1, &ldu, &work1, &lwork, &iwork1, &info ); + lwork = cvRound(work1); + } + + assert(info == 0); + if( temp_a ) + { + buf_size += n*m*elem_size; + } + work_ofs = buf_size; + buf_size += lwork*elem_size; + buf_size = alignSize(buf_size, sizeof(integer)); + iwork_ofs = buf_size; + buf_size += 8*nm*sizeof(integer); + + AutoBuffer buf(buf_size); + uchar* buffer = (uchar*)buf; + + if( temp_a ) + { + _a = Mat(a.rows, a.cols, type, buffer ); + a.copyTo(_a); + } + + if( !(flags & SVD::MODIFY_A) && !temp_a ) + { + if( compute_uv && a.size() == vt.size() ) + { + a.copyTo(vt); + _a = vt; + } + else if( compute_uv && a.size() == u.size() ) + { + a.copyTo(u); + _a = u; + } + } + + if( compute_uv ) + { + ldv = (int)(vt.step ? vt.step/elem_size : vt.cols); + ldu = (int)(u.step ? u.step/elem_size : u.cols); + } + + lda = (int)(_a.step ? _a.step/elem_size : _a.cols); + if( type == CV_32F ) + { + sgesdd_(mode, &n, &m, _a.ptr(), &lda, w.ptr(), + vt.data ? vt.ptr() : (float*)&v1, &ldv, + u.data ? u.ptr() : (float*)&u1, &ldu, + (float*)(buffer + work_ofs), &lwork, + (integer*)(buffer + iwork_ofs), &info ); + } + else + { + dgesdd_(mode, &n, &m, _a.ptr(), &lda, w.ptr(), + vt.data ? vt.ptr() : &v1, &ldv, + u.data ? u.ptr() : &u1, &ldu, + (double*)(buffer + work_ofs), &lwork, + (integer*)(buffer + iwork_ofs), &info ); + } + CV_Assert(info >= 0); + if(info != 0) + { + if( u.data ) + u = Scalar(0.); + if( vt.data ) + vt = Scalar(0.); + w = Scalar(0.); + } +} +////////////////////////////////////////////////////////// +template static void +MatrAXPY( int m, int n, const T1* x, int dx, + const T2* a, int inca, T3* y, int dy ) +{ + int i, j; + for( i = 0; i < m; i++, x += dx, y += dy ) + { + T2 s = a[i*inca]; + for( j = 0; j <= n - 4; j += 4 ) + { + T3 t0 = (T3)(y[j] + s*x[j]); + T3 t1 = (T3)(y[j+1] + s*x[j+1]); + y[j] = t0; + y[j+1] = t1; + t0 = (T3)(y[j+2] + s*x[j+2]); + t1 = (T3)(y[j+3] + s*x[j+3]); + y[j+2] = t0; + y[j+3] = t1; + } + + for( ; j < n; j++ ) + y[j] = (T3)(y[j] + s*x[j]); + } +} +template static void +SVBkSb( int m, int n, const T* w, int incw, + const T* u, int ldu, int uT, + const T* v, int ldv, int vT, + const T* b, int ldb, int nb, + T* x, int ldx, double* buffer, T eps ) +{ + double threshold = 0; + int udelta0 = uT ? ldu : 1, udelta1 = uT ? 1 : ldu; + int vdelta0 = vT ? ldv : 1, vdelta1 = vT ? 1 : ldv; + int i, j, nm = std::min(m, n); + + if( !b ) + nb = m; + + for( i = 0; i < n; i++ ) + for( j = 0; j < nb; j++ ) + x[i*ldx + j] = 0; + + for( i = 0; i < nm; i++ ) + threshold += w[i*incw]; + threshold *= eps; + + // v * inv(w) * uT * b + for( i = 0; i < nm; i++, u += udelta0, v += vdelta0 ) + { + double wi = w[i*incw]; + if( wi <= threshold ) + continue; + wi = 1/wi; + + if( nb == 1 ) + { + double s = 0; + if( b ) + for( j = 0; j < m; j++ ) + s += u[j*udelta1]*b[j*ldb]; + else + s = u[0]; + s *= wi; + + for( j = 0; j < n; j++ ) + x[j*ldx] = (T)(x[j*ldx] + s*v[j*vdelta1]); + } + else + { + if( b ) + { + for( j = 0; j < nb; j++ ) + buffer[j] = 0; + MatrAXPY( m, nb, b, ldb, u, udelta1, buffer, 0 ); + for( j = 0; j < nb; j++ ) + buffer[j] *= wi; + } + else + { + for( j = 0; j < nb; j++ ) + buffer[j] = u[j*udelta1]*wi; + } + MatrAXPY( n, nb, buffer, 0, v, vdelta1, x, ldx ); + } + } +} + +static void _backSubst( const InputArray _w, const InputArray _u, const InputArray _vt, + const InputArray _rhs, OutputArray _dst ) +{ + Mat w = _w.getMat(), u = _u.getMat(), vt = _vt.getMat(), rhs = _rhs.getMat(); + int type = w.type(), esz = (int)w.elemSize(); + int m = u.rows, n = vt.cols, nb = rhs.data ? rhs.cols : m; + AutoBuffer buffer(nb); + CV_Assert( u.data && vt.data && w.data ); + + CV_Assert( rhs.data == 0 || (rhs.type() == type && rhs.rows == m) ); + + _dst.create( n, nb, type ); + Mat dst = _dst.getMat(); + if( type == CV_32F ) + SVBkSb(m, n, (float*)w.data, 1, (float*)u.data, (int)(u.step/esz), false, + (float*)vt.data, (int)(vt.step/esz), true, (float*)rhs.data, (int)(rhs.step/esz), + nb, (float*)dst.data, (int)(dst.step/esz), buffer, 10*FLT_EPSILON ); + else if( type == CV_64F ) + SVBkSb(m, n, (double*)w.data, 1, (double*)u.data, (int)(u.step/esz), false, + (double*)vt.data, (int)(vt.step/esz), true, (double*)rhs.data, (int)(rhs.step/esz), + nb, (double*)dst.data, (int)(dst.step/esz), buffer, 2*DBL_EPSILON ); + else + CV_Error( Error::StsUnsupportedFormat, "" ); +} +/////////////////////////////////////////// + +#define Sf( y, x ) ((float*)(srcdata + y*srcstep))[x] +#define Sd( y, x ) ((double*)(srcdata + y*srcstep))[x] +#define Df( y, x ) ((float*)(dstdata + y*dststep))[x] +#define Dd( y, x ) ((double*)(dstdata + y*dststep))[x] + +double cvfork::invert( InputArray _src, OutputArray _dst, int method ) +{ + Mat src = _src.getMat(); + int type = src.type(); + + CV_Assert(type == CV_32F || type == CV_64F); + + size_t esz = CV_ELEM_SIZE(type); + int m = src.rows, n = src.cols; + + if( method == DECOMP_SVD ) + { + int nm = std::min(m, n); + + AutoBuffer _buf((m*nm + nm + nm*n)*esz + sizeof(double)); + uchar* buf = alignPtr((uchar*)_buf, (int)esz); + Mat u(m, nm, type, buf); + Mat w(nm, 1, type, u.ptr() + m*nm*esz); + Mat vt(nm, n, type, w.ptr() + nm*esz); + + _SVDcompute(src, w, u, vt); + _backSubst(w, u, vt, Mat(), _dst); + + return type == CV_32F ? + (w.ptr()[0] >= FLT_EPSILON ? + w.ptr()[n-1]/w.ptr()[0] : 0) : + (w.ptr()[0] >= DBL_EPSILON ? + w.ptr()[n-1]/w.ptr()[0] : 0); + } + return 0; +} + +#endif //USE_LAPACK diff --git a/apps/interactive-calibration/linalg.hpp b/apps/interactive-calibration/linalg.hpp new file mode 100644 index 0000000000..4a4d2b053b --- /dev/null +++ b/apps/interactive-calibration/linalg.hpp @@ -0,0 +1,13 @@ +#ifndef LINALG_HPP +#define LINALG_HPP + +#include + +namespace cvfork { + +double invert( cv::InputArray _src, cv::OutputArray _dst, int method ); +bool solve(cv::InputArray _src, cv::InputArray _src2arg, cv::OutputArray _dst, int method ); + +} + +#endif diff --git a/apps/interactive-calibration/main.cpp b/apps/interactive-calibration/main.cpp new file mode 100644 index 0000000000..06521593f8 --- /dev/null +++ b/apps/interactive-calibration/main.cpp @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "calibCommon.hpp" +#include "calibPipeline.hpp" +#include "frameProcessor.hpp" +#include "cvCalibrationFork.hpp" +#include "calibController.hpp" +#include "parametersController.hpp" +#include "rotationConverters.hpp" + +using namespace calib; + +const std::string keys = + "{v | | Input from video file }" + "{ci | 0 | Default camera id }" + "{flip | false | Vertical flip of input frames }" + "{t | circles | Template for calibration (circles, chessboard, dualCircles, chAruco) }" + "{sz | 16.3 | Distance between two nearest centers of circles or squares on calibration board}" + "{dst | 295 | Distance between white and black parts of daulCircles template}" + "{w | | Width of template (in corners or circles)}" + "{h | | Height of template (in corners or circles)}" + "{of | cameraParameters.xml | Output file name}" + "{ft | true | Auto tuning of calibration flags}" + "{vis | grid | Captured boards visualisation (grid, window)}" + "{d | 0.8 | Min delay between captures}" + "{pf | defaultConfig.xml| Advanced application parameters}" + "{help | | Print help}"; + +bool calib::showOverlayMessage(const std::string& message) +{ +#ifdef HAVE_QT + cv::displayOverlay(mainWindowName, message, OVERLAY_DELAY); + return true; +#else + std::cout << message << std::endl; + return false; +#endif +} + +static void deleteButton(int state, void* data) +{ + state++; //to avoid gcc warnings + (static_cast*>(data))->get()->deleteLastFrame(); + calib::showOverlayMessage("Last frame deleted"); +} + +static void deleteAllButton(int state, void* data) +{ + state++; + (static_cast*>(data))->get()->deleteAllData(); + calib::showOverlayMessage("All frames deleted"); +} + +static void saveCurrentParamsButton(int state, void* data) +{ + state++; + if((static_cast*>(data))->get()->saveCurrentCameraParameters()) + calib::showOverlayMessage("Calibration parameters saved"); +} + +#ifdef HAVE_QT +static void switchVisualizationModeButton(int state, void* data) +{ + state++; + ShowProcessor* processor = static_cast(((cv::Ptr*)data)->get()); + processor->switchVisualizationMode(); +} + +static void undistortButton(int state, void* data) +{ + ShowProcessor* processor = static_cast(((cv::Ptr*)data)->get()); + processor->setUndistort(static_cast(state)); + calib::showOverlayMessage(std::string("Undistort is ") + + (static_cast(state) ? std::string("on") : std::string("off"))); +} +#endif //HAVE_QT + +int main(int argc, char** argv) +{ + cv::CommandLineParser parser(argc, argv, keys); + if(parser.has("help")) { + parser.printMessage(); + return 0; + } + std::cout << consoleHelp << std::endl; + parametersController paramsController; + + if(!paramsController.loadFromParser(parser)) + return 0; + + captureParameters capParams = paramsController.getCaptureParameters(); + internalParameters intParams = paramsController.getInternalParameters(); + + cv::TermCriteria solverTermCrit = cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS, + intParams.solverMaxIters, intParams.solverEps); + cv::Ptr globalData(new calibrationData); + if(!parser.has("v")) globalData->imageSize = capParams.cameraResolution; + + int calibrationFlags = 0; + if(intParams.fastSolving) calibrationFlags |= CALIB_USE_QR; + cv::Ptr controller(new calibController(globalData, calibrationFlags, + parser.get("ft"), capParams.minFramesNum)); + cv::Ptr dataController(new calibDataController(globalData, capParams.maxFramesNum, + intParams.filterAlpha)); + dataController->setParametersFileName(parser.get("of")); + + cv::Ptr capProcessor, showProcessor; + capProcessor = cv::Ptr(new CalibProcessor(globalData, capParams)); + showProcessor = cv::Ptr(new ShowProcessor(globalData, controller, capParams.board)); + + if(parser.get("vis").find("window") == 0) { + static_cast(showProcessor.get())->setVisualizationMode(Window); + cv::namedWindow(gridWindowName); + cv::moveWindow(gridWindowName, 1280, 500); + } + + cv::Ptr pipeline(new CalibPipeline(capParams)); + std::vector > processors; + processors.push_back(capProcessor); + processors.push_back(showProcessor); + + cv::namedWindow(mainWindowName); + cv::moveWindow(mainWindowName, 10, 10); +#ifdef HAVE_QT + cv::createButton("Delete last frame", deleteButton, &dataController, cv::QT_PUSH_BUTTON); + cv::createButton("Delete all frames", deleteAllButton, &dataController, cv::QT_PUSH_BUTTON); + cv::createButton("Undistort", undistortButton, &showProcessor, cv::QT_CHECKBOX, false); + cv::createButton("Save current parameters", saveCurrentParamsButton, &dataController, cv::QT_PUSH_BUTTON); + cv::createButton("Switch visualisation mode", switchVisualizationModeButton, &showProcessor, cv::QT_PUSH_BUTTON); +#endif //HAVE_QT + try { + bool pipelineFinished = false; + while(!pipelineFinished) + { + PipelineExitStatus exitStatus = pipeline->start(processors); + if (exitStatus == Finished) { + if(controller->getCommonCalibrationState()) + saveCurrentParamsButton(0, &dataController); + pipelineFinished = true; + continue; + } + else if (exitStatus == Calibrate) { + + dataController->rememberCurrentParameters(); + globalData->imageSize = pipeline->getImageSize(); + calibrationFlags = controller->getNewFlags(); + + if(capParams.board != chAruco) { + globalData->totalAvgErr = + cvfork::calibrateCamera(globalData->objectPoints, globalData->imagePoints, + globalData->imageSize, globalData->cameraMatrix, + globalData->distCoeffs, cv::noArray(), cv::noArray(), + globalData->stdDeviations, globalData->perViewErrors, + calibrationFlags, solverTermCrit); + } + else { + cv::Ptr dictionary = + cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(capParams.charucoDictName)); + cv::Ptr charucoboard = + cv::aruco::CharucoBoard::create(capParams.boardSize.width, capParams.boardSize.height, + capParams.charucoSquareLenght, capParams.charucoMarkerSize, dictionary); + globalData->totalAvgErr = + cvfork::calibrateCameraCharuco(globalData->allCharucoCorners, globalData->allCharucoIds, + charucoboard, globalData->imageSize, + globalData->cameraMatrix, globalData->distCoeffs, + cv::noArray(), cv::noArray(), globalData->stdDeviations, + globalData->perViewErrors, calibrationFlags, solverTermCrit); + } + dataController->updateUndistortMap(); + dataController->printParametersToConsole(std::cout); + controller->updateState(); + for(int j = 0; j < capParams.calibrationStep; j++) + dataController->filterFrames(); + static_cast(showProcessor.get())->updateBoardsView(); + } + else if (exitStatus == DeleteLastFrame) { + deleteButton(0, &dataController); + static_cast(showProcessor.get())->updateBoardsView(); + } + else if (exitStatus == DeleteAllFrames) { + deleteAllButton(0, &dataController); + static_cast(showProcessor.get())->updateBoardsView(); + } + else if (exitStatus == SaveCurrentData) { + saveCurrentParamsButton(0, &dataController); + } + else if (exitStatus == SwitchUndistort) + static_cast(showProcessor.get())->switchUndistort(); + else if (exitStatus == SwitchVisualisation) + static_cast(showProcessor.get())->switchVisualizationMode(); + + for (std::vector >::iterator it = processors.begin(); it != processors.end(); ++it) + (*it)->resetState(); + } + } + catch (std::runtime_error exp) { + std::cout << exp.what() << std::endl; + } + + return 0; +} diff --git a/apps/interactive-calibration/parametersController.cpp b/apps/interactive-calibration/parametersController.cpp new file mode 100644 index 0000000000..c9356902da --- /dev/null +++ b/apps/interactive-calibration/parametersController.cpp @@ -0,0 +1,138 @@ +#include "parametersController.hpp" +#include + +template +static bool readFromNode(cv::FileNode node, T& value) +{ + if(!node.isNone()) { + node >> value; + return true; + } + else + return false; +} + +static bool checkAssertion(bool value, const std::string& msg) +{ + if(!value) + std::cerr << "Error: " << msg << std::endl; + + return value; +} + +bool calib::parametersController::loadFromFile(const std::string &inputFileName) +{ + cv::FileStorage reader; + reader.open(inputFileName, cv::FileStorage::READ); + + if(!reader.isOpened()) { + std::cerr << "Warning: Unable to open " << inputFileName << + " Applicatioin stated with default advanced parameters" << std::endl; + return true; + } + + readFromNode(reader["charuco_dict"], mCapParams.charucoDictName); + readFromNode(reader["charuco_square_lenght"], mCapParams.charucoSquareLenght); + readFromNode(reader["charuco_marker_size"], mCapParams.charucoMarkerSize); + readFromNode(reader["camera_resolution"], mCapParams.cameraResolution); + readFromNode(reader["calibration_step"], mCapParams.calibrationStep); + readFromNode(reader["max_frames_num"], mCapParams.maxFramesNum); + readFromNode(reader["min_frames_num"], mCapParams.minFramesNum); + readFromNode(reader["solver_eps"], mInternalParameters.solverEps); + readFromNode(reader["solver_max_iters"], mInternalParameters.solverMaxIters); + readFromNode(reader["fast_solver"], mInternalParameters.fastSolving); + readFromNode(reader["frame_filter_conv_param"], mInternalParameters.filterAlpha); + + bool retValue = + checkAssertion(mCapParams.charucoDictName >= 0, "Dict name must be >= 0") && + checkAssertion(mCapParams.charucoMarkerSize > 0, "Marker size must be positive") && + checkAssertion(mCapParams.charucoSquareLenght > 0, "Square size must be positive") && + checkAssertion(mCapParams.minFramesNum > 1, "Minimal number of frames for calibration < 1") && + checkAssertion(mCapParams.calibrationStep > 0, "Calibration step must be positive") && + checkAssertion(mCapParams.maxFramesNum > mCapParams.minFramesNum, "maxFramesNum < minFramesNum") && + checkAssertion(mInternalParameters.solverEps > 0, "Solver precision must be positive") && + checkAssertion(mInternalParameters.solverMaxIters > 0, "Max solver iterations number must be positive") && + checkAssertion(mInternalParameters.filterAlpha >=0 && mInternalParameters.filterAlpha <=1 , + "Frame filter convolution parameter must be in [0,1] interval") && + checkAssertion(mCapParams.cameraResolution.width > 0 && mCapParams.cameraResolution.height > 0, + "Wrong camera resolution values"); + + reader.release(); + return retValue; +} + +calib::parametersController::parametersController() +{ +} + +calib::captureParameters calib::parametersController::getCaptureParameters() const +{ + return mCapParams; +} + +calib::internalParameters calib::parametersController::getInternalParameters() const +{ + return mInternalParameters; +} + +bool calib::parametersController::loadFromParser(cv::CommandLineParser &parser) +{ + mCapParams.flipVertical = parser.get("flip"); + mCapParams.captureDelay = parser.get("d"); + mCapParams.squareSize = parser.get("sz"); + mCapParams.templDst = parser.get("dst"); + + if(!checkAssertion(mCapParams.squareSize > 0, "Distance between corners or circles must be positive")) + return false; + if(!checkAssertion(mCapParams.templDst > 0, "Distance betwen parts of dual template must be positive")) + return false; + + if (parser.has("v")) { + mCapParams.source = File; + mCapParams.videoFileName = parser.get("v"); + } + else { + mCapParams.source = Camera; + mCapParams.camID = parser.get("ci"); + } + + std::string templateType = parser.get("t"); + + if(templateType.find("circles", 0) == 0) { + mCapParams.board = AcirclesGrid; + mCapParams.boardSize = cv::Size(4, 11); + } + else if(templateType.find("chessboard", 0) == 0) { + mCapParams.board = Chessboard; + mCapParams.boardSize = cv::Size(7, 7); + } + else if(templateType.find("dualcircles", 0) == 0) { + mCapParams.board = DoubleAcirclesGrid; + mCapParams.boardSize = cv::Size(4, 11); + } + else if(templateType.find("charuco", 0) == 0) { + mCapParams.board = chAruco; + mCapParams.boardSize = cv::Size(6, 8); + mCapParams.charucoDictName = 0; + mCapParams.charucoSquareLenght = 200; + mCapParams.charucoMarkerSize = 100; + } + else { + std::cerr << "Wrong template name\n"; + return false; + } + + if(parser.has("w") && parser.has("h")) { + mCapParams.boardSize = cv::Size(parser.get("w"), parser.get("h")); + if(!checkAssertion(mCapParams.boardSize.width > 0 || mCapParams.boardSize.height > 0, + "Board size must be positive")) + return false; + } + + if(!checkAssertion(parser.get("of").find(".xml") > 0, + "Wrong output file name: correct format is [name].xml")) + return false; + + loadFromFile(parser.get("pf")); + return true; +} diff --git a/apps/interactive-calibration/parametersController.hpp b/apps/interactive-calibration/parametersController.hpp new file mode 100644 index 0000000000..6477901990 --- /dev/null +++ b/apps/interactive-calibration/parametersController.hpp @@ -0,0 +1,29 @@ +#ifndef PARAMETERS_CONTROLLER_HPP +#define PARAMETERS_CONTROLLER_HPP + +#include +#include +#include "calibCommon.hpp" + +namespace calib { + +class parametersController +{ +protected: + captureParameters mCapParams; + internalParameters mInternalParameters; + + bool loadFromFile(const std::string& inputFileName); +public: + parametersController(); + parametersController(cv::Ptr params); + + captureParameters getCaptureParameters() const; + internalParameters getInternalParameters() const; + + bool loadFromParser(cv::CommandLineParser& parser); +}; + +} + +#endif diff --git a/apps/interactive-calibration/rotationConverters.cpp b/apps/interactive-calibration/rotationConverters.cpp new file mode 100644 index 0000000000..dee3b531d6 --- /dev/null +++ b/apps/interactive-calibration/rotationConverters.cpp @@ -0,0 +1,121 @@ +#include "rotationConverters.hpp" + +#include +#include +#include + +#define CALIB_PI 3.14159265358979323846 +#define CALIB_PI_2 1.57079632679489661923 + +void calib::Euler(const cv::Mat& src, cv::Mat& dst, int argType) +{ + if((src.rows == 3) && (src.cols == 3)) + { + //convert rotaion matrix to 3 angles (pitch, yaw, roll) + dst = cv::Mat(3, 1, CV_64F); + double pitch, yaw, roll; + + if(src.at(0,2) < -0.998) + { + pitch = -atan2(src.at(1,0), src.at(1,1)); + yaw = -CALIB_PI_2; + roll = 0.; + } + else if(src.at(0,2) > 0.998) + { + pitch = atan2(src.at(1,0), src.at(1,1)); + yaw = CALIB_PI_2; + roll = 0.; + } + else + { + pitch = atan2(-src.at(1,2), src.at(2,2)); + yaw = asin(src.at(0,2)); + roll = atan2(-src.at(0,1), src.at(0,0)); + } + + if(argType == CALIB_DEGREES) + { + pitch *= 180./CALIB_PI; + yaw *= 180./CALIB_PI; + roll *= 180./CALIB_PI; + } + else if(argType != CALIB_RADIANS) + CV_Error(cv::Error::StsBadFlag, "Invalid argument type"); + + dst.at(0,0) = pitch; + dst.at(1,0) = yaw; + dst.at(2,0) = roll; + } + else if( (src.cols == 1 && src.rows == 3) || + (src.cols == 3 && src.rows == 1 ) ) + { + //convert vector which contains 3 angles (pitch, yaw, roll) to rotaion matrix + double pitch, yaw, roll; + if(src.cols == 1 && src.rows == 3) + { + pitch = src.at(0,0); + yaw = src.at(1,0); + roll = src.at(2,0); + } + else{ + pitch = src.at(0,0); + yaw = src.at(0,1); + roll = src.at(0,2); + } + + if(argType == CALIB_DEGREES) + { + pitch *= CALIB_PI / 180.; + yaw *= CALIB_PI / 180.; + roll *= CALIB_PI / 180.; + } + else if(argType != CALIB_RADIANS) + CV_Error(cv::Error::StsBadFlag, "Invalid argument type"); + + dst = cv::Mat(3, 3, CV_64F); + cv::Mat M(3, 3, CV_64F); + cv::Mat i = cv::Mat::eye(3, 3, CV_64F); + i.copyTo(dst); + i.copyTo(M); + + double* pR = dst.ptr(); + pR[4] = cos(pitch); + pR[7] = sin(pitch); + pR[8] = pR[4]; + pR[5] = -pR[7]; + + double* pM = M.ptr(); + pM[0] = cos(yaw); + pM[2] = sin(yaw); + pM[8] = pM[0]; + pM[6] = -pM[2]; + + dst *= M; + i.copyTo(M); + pM[0] = cos(roll); + pM[3] = sin(roll); + pM[4] = pM[0]; + pM[1] = -pM[3]; + + dst *= M; + } + else + CV_Error(cv::Error::StsBadFlag, "Input matrix must be 1x3, 3x1 or 3x3" ); +} + +void calib::RodriguesToEuler(const cv::Mat& src, cv::Mat& dst, int argType) +{ + CV_Assert((src.cols == 1 && src.rows == 3) || (src.cols == 3 && src.rows == 1)); + cv::Mat R; + cv::Rodrigues(src, R); + Euler(R, dst, argType); +} + +void calib::EulerToRodrigues(const cv::Mat& src, cv::Mat& dst, int argType) +{ + CV_Assert((src.cols == 1 && src.rows == 3) || (src.cols == 3 && src.rows == 1)); + cv::Mat R; + Euler(src, R, argType); + cv::Rodrigues(R, dst); +} diff --git a/apps/interactive-calibration/rotationConverters.hpp b/apps/interactive-calibration/rotationConverters.hpp new file mode 100644 index 0000000000..bddce3eb30 --- /dev/null +++ b/apps/interactive-calibration/rotationConverters.hpp @@ -0,0 +1,16 @@ +#ifndef RAOTATION_CONVERTERS_HPP +#define RAOTATION_CONVERTERS_HPP + +#include + +namespace calib +{ +#define CALIB_RADIANS 0 +#define CALIB_DEGREES 1 + + void Euler(const cv::Mat& src, cv::Mat& dst, int argType = CALIB_RADIANS); + void RodriguesToEuler(const cv::Mat& src, cv::Mat& dst, int argType = CALIB_RADIANS); + void EulerToRodrigues(const cv::Mat& src, cv::Mat& dst, int argType = CALIB_RADIANS); + +} +#endif diff --git a/doc/tutorials/calib3d/interactive_calibration/images/charuco_board.png b/doc/tutorials/calib3d/interactive_calibration/images/charuco_board.png new file mode 100644 index 0000000000000000000000000000000000000000..947a94cb56c596e45df872b91487dbc1da2f8668 GIT binary patch literal 10393 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 literal 0 HcmV?d00001 diff --git a/doc/tutorials/calib3d/interactive_calibration/images/dualCircles.jpg b/doc/tutorials/calib3d/interactive_calibration/images/dualCircles.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7a28bde76211659be91dceaf19cd4c130ef58693 GIT binary patch literal 71938 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
f`a5XT!~-=Mew%Lb(8W96#yl;- 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

#-!wbyH81=%HhrbgpE2LrQ~6)A3>BzTdKX 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 literal 0 HcmV?d00001 diff --git a/doc/tutorials/calib3d/interactive_calibration/images/screen_finish.jpg b/doc/tutorials/calib3d/interactive_calibration/images/screen_finish.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac2f28405bfdea44841f5354d2a07fee3dbacef9 GIT binary patch literal 79577 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�jtM01=T2ZBy0c4k>_dF7LcRVyq&ZNkiG^_-jD?0ucuyIq#A)R6Z= zQ(!6ROWE1zWh~e4p-%K``~&sNczZW%8&!-rD__=; zB5f9(VmlSyDU;_mh{?DVKvU2-IMJeSL646c>lfE)CjC6Qyzw35eVMX*JArY9R#Qf~ zIU-}0{w_jY<`{$js91vj>#)~$PzE9NSMlPRJcdAsc&<}7Vom^SngB*tV7luH0%GgF zQpA^5PuW7yU&O4i(Ly-t!`A(HAy`O!AuDu8K!L>{ncu09g(EG7xP*LaK0S3~LBV6{ zx^7S6iLv-ta0S*S|Kiq5a{GFsS_^%9A=mO@F7aJas{$F$QQxBNiFW#Woc-8whgTPy z96C=OsI~9Um|9uO*~%uK>Oa8LbSG+lueBK47Bhr`(k=gsfmp9pNGQlE^&;ujsx7Ii ze*0*x0emIq>L10g`xAaQXuE?bhf+CJSHk>a-f;wW6J@M#T>>t?AJNw(h)B1PO!eXx zY}d8u2`UNGzK+7@3z8)iB%WD3>pb2+AxYf9qo(XYq740?;;QxA{B3(@#>I!2GQm`iZ>O1+XhKh-wxShUuA9}^lMO|k>9akXXMC{W z!o8{V9kpZ_#Xj71(cPO7I=iszr^KkA^g=~5hJ_p59A#$=G731o82oE1SVCEj9%uq< z_vo*U&LG!s0cL<4-05_D=qtU@Cw9rjFh^jlf6P(5Fu;n;%{9aD-9Ds1i zo5V`d)7`NSjx_AiT@i)WQ^gTo6 zN|(GhS{g=krc#)TfY7`Ym5X(=$UCqz%Qxiv^^TRS@)Yd|IC2a?3+9WlU7Xt44|rP@ zZU%T(UaC=~2hP_(vhq54$j}7)GB~VH;Dh%B3-aY;$LQSL#gx6~24XQGHMWb!-!Dgv z8J zbj4_#t2d0a26F)gO?L%d+WrCD{FD`{1mJAT%-Eg#>y)Jg0U9Spkl@0UH@M{~Pl^u{ zMm#PZd?c4X9;vxUH~zAHA7(4#k7KOk-M)84)5XwzmlH)75A>MW@q$(RzhyWo>V2fD zS3>#3Exbg>vA3+UdMaQ+mrT>zkC#jCts3!kGFTY1l@pGfI~4xbuO3hUjTo879RcE! zxE)uh=9=Yz>CtcKs4TK9eS}p_?Hh4sTg&b6_3du_MdN_+n*)Ewo6vs%%*XoWJMByx z2gK8EvJJlQ7a#lpeD7IUH;80acJqD$YuQk_grSYvvnA`q{0KN`B81=h2s!qD=gU@g zcB&24$m5mT&$k;!Jkz;&-{CdY z2{C?ESX{fRr%xpcHB}1EJ6P=qI_rp_iN0i8Bk0TND{Ih`?~#g;6mdc^#$9>MYivjd#yf?_yk59*T*I?C2()I5@L)dR-YBjjz;Mg@R!sYGLulbE^}D z{AF23H|)n8I~Vqq>w0P1vZHoya5pf%c;h2V)}QGv1BB7#ZaTG!!;=DE zah--z;yNV&M_&QS1^)r8r^+WzkB(eFr|DHz(uHX?qBln&=wdaZ?sc+QWD;y7v`sNb zU!~9y=7J0UivI&}qCV=B@NAnWp1<|BgY~sD9F>)?;{NutR@1~+*sa5iY&Qc)tkZM? zE9*)`1^i)~nDz<0DRV})Jl)G=__tkfH2Nq?^T$lfNebquyw`{7`yztEmAHcMfh~}_ zH}cmaRX>Z(SXig0 z{Hp-B>Kn>fSifSJkql;q1I|sJ>ZwtuO@$4wmq!EQh5qpv`TgI<>PMhhY3@-op26d@ z38r>NXSQFbG%<&w0UKp@MqP0Ucr`tPh%m|P_zr0M0G=xz<13TvibGSU0rwgx;k+1|qC$8s>5${kq$5_qWpRy_6Ao1Zk+i;aBh^f>X^A9Tw#7uS-tz|ylTQMt-!~RH0`qjm7j~Y-9W1A zGmG=|CdShJ=Oc?Bs|%mRul7CMaSZIfZ661A8Bm@X>v>vCTuJ{t+2%SYJ~#TQxl&Bm zw1A#v_v7kgS5v%LaaDo^!`O`IDJ7Yk~__M1_W7;&f-_=kI zJN}#yvrTPlnIA+qE%VVx`aZmcy&+IxxuzT@U&)}GOMaVyES$8+JunW$#1NfgXzTM@ z7BVZe?eTRwyAosB4p$1*3zsiIj~!`C)xFu?q?i#wT74%R`u2_NfrZu1S33WW#@w&b zwJ>=Xtv{3`%S2yD`vVn)WrK`QoJ4vjs;q6ijQs0(AbXL$9^q-^EOw+ z?lql>``4Ysqwa2OFC_6P*8@Y1J*~p%xbxdAjA$+n_oUV&vp6(3Q8LhjRW<&))d(Rh zdWVg7v*<2YltnVyVhpmJU8JpJoB!*D9*yMFn72@vfHEtYfZfYpt>&b* zU(NM;Tk%oB{L(`bA2HNtkQQ^@G%xlTMZA1pY^0}$CCE|P9j+(mqyQi0qOU^ggIylV zw$=jg8h+(@u6>?if7kRhR1L)$h#uI(bz03E4kc#_{X$BANzRmZ�{GDWyK0pROCs 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

dunj1`SbX%OJOe4eyiHTtTB;M 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%0D2aK*kgE=$SvZ2` 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 RcJZQ#7^S(L)ZD$n_#0|xpC + +0 +200 +100 +1 +30 +10 +1e-7 +30 +0 +0.1 +1280 720 + +@endcode + +- *charuco_dict*: name of special dictionary, which has been used for generation of chAruco pattern +- *charuco_square_lenght*: size of square on chAruco board (in pixels) +- *charuco_marker_size*: size of Aruco markers on chAruco board (in pixels) +- *calibration_step*: interval in frames between launches of @ref cv::calibrateCamera +- *max_frames_num*: if number of frames for calibration is greater then this value frames filter starts working. +After filtration size of calibration dataset is equals to *max_frames_num* +- *min_frames_num*: if number of frames is greater then this value turns on auto flags tuning, undistorted view and quality evaluation +- *solver_eps*: precision of Levenberg-Marquardt solver in @ref cv::calibrateCamera +- *solver_max_iters*: iterations limit of solver +- *fast_solver*: if this value is nonzero and Lapack is found QR decomposition is used instead of SVD in solver. +QR faster than SVD, but potentially less precise +- *frame_filter_conv_param*: parameter which used in linear convolution of bicriterial frames filter +- *camera_resolution*: resolution of camera which is used for calibration + +**Note:** *charuco_dict*, *charuco_square_lenght* and *charuco_marker_size* are used for chAruco pattern generation +(see Aruco module description for details: [Aruco tutorials](https://github.com/Itseez/opencv_contrib/tree/master/modules/aruco/tutorials)) + +Default chAruco pattern: + +![](images/charuco_board.png) + +Dual circles pattern +------ + +To make this pattern you need standard OpenCV circles pattern and binary inverted one. +Place two patterns on one plane in order when all horizontal lines of circles in one pattern are + continuations of similar lines in another. +Measure distance between patterns as shown at picture below pass it as **dst** command line parameter. Also measure distance between centers of nearest circles and pass +this value as **sz** command line parameter. + +![](images/dualCircles.jpg) + +This pattern is very sensitive to quality of production and measurements. + + +Data filtration +------ +When size of calibration dataset is greater then *max_frames_num* starts working +data filter. It tries to remove "bad" frames from dataset. Filter removes the frame + on which \f$loss\_function\f$ takes maximum. + +\f[loss\_function(i)=\alpha RMS(i)+(1-\alpha)reducedGridQuality(i)\f] + +**RMS** is an average re-projection error calculated for frame *i*, **reducedGridQuality** + is scene coverage quality evaluation without frame *i*. \f$\alpha\f$ is equals to + **frame_filter_conv_param**. + + +Calibration process +------ + +To start calibration just run application. Place pattern ahead the camera and fixate pattern in some pose. +After that wait for capturing (will be shown message like "Frame #i captured"). +Current focal distance and re-projection error will be shown at the main screen. Move pattern to the next position and repeat procedure. Try to cover image plane +uniformly and don't show pattern on sharp angles to the image plane. + +![](images/screen_charuco.jpg) + +If calibration seems to be successful (confidence intervals and average re-projection + error are small, frame coverage quality and number of pattern views are big enough) + application will show a message like on screen below. + + +![](images/screen_finish.jpg) + +Hot keys: + +- Esc -- exit application +- s -- save current data to XML file +- r -- delete last frame +- d -- delete all frames +- u -- enable/disable applying of undistortion +- v -- switch visualization mode + +Results +------ + +As result you will get camera parameters and confidence intervals for them. + +Example of output XML file: + +@code{.xml} + + +"Thu 07 Apr 2016 04:23:03 PM MSK" +21 + + 1280 720 + + 3 + 3 +

d
+ + 1.2519588293098975e+03 0. 6.6684948780852471e+02 0. + 1.2519588293098975e+03 3.6298123112613683e+02 0. 0. 1. + + 4 + 1 +
d
+ + 0. 1.2887048808572649e+01 2.8536856683866230e+00 + 2.8341737483430314e+00
+ + 1 + 5 +
d
+ + 1.3569117181595716e-01 -8.2513063822554633e-01 0. 0. + 1.6412101575010554e+00
+ + 5 + 1 +
d
+ + 1.5570675523402111e-02 8.7229075437543435e-02 0. 0. + 1.8382427901856876e-01
+4.2691743074130178e-01 + +@endcode diff --git a/doc/tutorials/calib3d/table_of_content_calib3d.markdown b/doc/tutorials/calib3d/table_of_content_calib3d.markdown index adbda4b971..50e9d122d1 100644 --- a/doc/tutorials/calib3d/table_of_content_calib3d.markdown +++ b/doc/tutorials/calib3d/table_of_content_calib3d.markdown @@ -30,3 +30,14 @@ how to find out from the 2D images information about the 3D world. Real time pose estimation of a textured object using ORB features, FlannBased matcher, PnP approach plus Ransac and Linear Kalman Filter to reject possible bad poses. + +- @subpage tutorial_interactive_calibration + + *Compatibility:* \> OpenCV 3.1 + + *Author:* Vladislav Sovrasov + + Camera calibration by using either the chessboard, chAruco, asymmetrical circle or dual asymmetrical circle + pattern. Calibration process is continious, so you can see results after each new pattern shot. + As an output you get average reprojection error, intrinsic camera parameters, distortion coefficients and + confidence intervals for all of evaluated variables.