From b9af9f0f022e87b4f1ea916601eeaf57d2b57b17 Mon Sep 17 00:00:00 2001 From: Nicolas Pope <nwpope@utu.fi> Date: Tue, 12 Mar 2019 16:40:51 +0200 Subject: [PATCH] Make calib use same frames for each camera --- cv-node/CMakeLists.txt | 4 +- cv-node/include/ftl/calibrate.hpp | 4 +- cv-node/src/calibrate.cpp | 198 ++++++++++++------------------ cv-node/src/main.cpp | 10 +- 4 files changed, 94 insertions(+), 122 deletions(-) diff --git a/cv-node/CMakeLists.txt b/cv-node/CMakeLists.txt index 87cefadd6..8c4ec948b 100644 --- a/cv-node/CMakeLists.txt +++ b/cv-node/CMakeLists.txt @@ -9,14 +9,16 @@ enable_testing() set(THREADS_PREFER_PTHREAD_FLAG ON) +if (WIN32) find_package( glog REQUIRED ) +include_directories(${glog_DIR}) +endif (WIN32) find_package( OpenCV REQUIRED ) find_package( Threads REQUIRED ) #find_package(PkgConfig) #pkg_check_modules(GTKMM gtkmm-3.0) # Need to include staged files and libs -include_directories(${glog_DIR}) include_directories(${PROJECT_SOURCE_DIR}/include) include_directories(${PROJECT_BINARY_DIR}) diff --git a/cv-node/include/ftl/calibrate.hpp b/cv-node/include/ftl/calibrate.hpp index 6ddf9a479..b9a95a939 100644 --- a/cv-node/include/ftl/calibrate.hpp +++ b/cv-node/include/ftl/calibrate.hpp @@ -76,8 +76,8 @@ class Calibrate { private: bool runCalibration(cv::Mat &img, cv::Mat &cam); - bool _recalibrate(size_t cam, std::vector<std::vector<cv::Point2f>> &imagePoints, - cv::Mat &cameraMatrix, cv::Mat &distCoeffs, cv::Size &imageSize); + bool _recalibrate(std::vector<std::vector<cv::Point2f>> *imagePoints, + cv::Mat *cameraMatrix, cv::Mat *distCoeffs, cv::Size *imageSize); cv::Mat _nextImage(size_t cam); private: diff --git a/cv-node/src/calibrate.cpp b/cv-node/src/calibrate.cpp index c54eecf94..14e0ca3d5 100644 --- a/cv-node/src/calibrate.cpp +++ b/cv-node/src/calibrate.cpp @@ -196,8 +196,10 @@ bool Calibrate::recalibrate() { Mat cameraMatrix[2], distCoeffs[2]; Size imageSize[2]; - bool r = _recalibrate(0, imagePoints[0], cameraMatrix[0], distCoeffs[0], imageSize[0]); - if (local_->isStereo()) r &= _recalibrate(1, imagePoints[1], cameraMatrix[1], distCoeffs[1], imageSize[1]); + // TODO Ensure both left+right use same frames + + bool r = _recalibrate(imagePoints, cameraMatrix, distCoeffs, imageSize); + //if (local_->isStereo()) r &= _recalibrate(1, imagePoints[1], cameraMatrix[1], distCoeffs[1], imageSize[1]); if (r) calibrated_ = true; @@ -264,13 +266,30 @@ bool Calibrate::recalibrate() { initUndistortRectifyMap(cameraMatrix[0], distCoeffs[0], R1, P1, imageSize[0], CV_16SC2, map1_[0], map2_[0]); initUndistortRectifyMap(cameraMatrix[1], distCoeffs[1], R2, P2, imageSize[0], CV_16SC2, map1_[1], map2_[1]); + } else { + int cam = 0; + if (settings_.useFisheye) + { + Mat newCamMat; + fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix[cam], distCoeffs[cam], imageSize[cam], + Matx33d::eye(), newCamMat, 1); + fisheye::initUndistortRectifyMap(cameraMatrix[cam], distCoeffs[cam], Matx33d::eye(), newCamMat, imageSize[cam], + CV_16SC2, map1_[cam], map2_[cam]); + } + else + { + initUndistortRectifyMap( + cameraMatrix[cam], distCoeffs[cam], Mat(), + getOptimalNewCameraMatrix(cameraMatrix[cam], distCoeffs[cam], imageSize[cam], 1, imageSize[cam], 0), imageSize[cam], + CV_16SC2, map1_[cam], map2_[cam]); + } } return r; } -bool Calibrate::_recalibrate(size_t cam, vector<vector<Point2f>> &imagePoints, - Mat &cameraMatrix, Mat &distCoeffs, Size &imageSize) { +bool Calibrate::_recalibrate(vector<vector<Point2f>> *imagePoints, + Mat *cameraMatrix, Mat *distCoeffs, Size *imageSize) { // TODO WHAT IS WINSIZE!! int winSize = 11; //parser.get<int>("winSize"); @@ -284,163 +303,106 @@ bool Calibrate::_recalibrate(size_t cam, vector<vector<Point2f>> &imagePoints, clock_t prevTimestamp = 0; const Scalar RED(0,0,255), GREEN(0,255,0); - settings_.outputFileName = string(FTL_CONFIG_ROOT "/calib_cam") + std::to_string(cam) + ".yml"; + int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE; + if(!settings_.useFisheye) { + // fast check erroneously fails with high distortions like fisheye + chessBoardFlags |= CALIB_CB_FAST_CHECK; + } + //! [get_input] for(;;) { - Mat view; + Mat view[2]; //bool blinkOutput = false; - view = _nextImage(cam); - LOG(INFO) << "Grabbing calibration image..."; + local_->get(view[0],view[1]); - //----- If no more image, or got enough, then stop calibration and show result ------------- - if( mode == CAPTURING && imagePoints.size() >= (size_t)settings_.nrFrames ) - { - if(runCalibrationAndSave(settings_, imageSize, cameraMatrix, distCoeffs, imagePoints, grid_width, - release_object)) { - LOG(INFO) << "Calibration completed"; - mode = CALIBRATED; - } else - mode = DETECTION; - } - if(view.empty()) // If there are no more images stop the loop - { - LOG(INFO) << "More calibration images are required"; - // if calibration threshold was not reached yet, calibrate now - if( mode != CALIBRATED && !imagePoints.empty() ) - runCalibrationAndSave(settings_, imageSize, cameraMatrix, distCoeffs, imagePoints, grid_width, - release_object); - break; + //view = _nextImage(cam); + LOG(INFO) << "Grabbing calibration image..."; + + if (view[0].empty() || view[1].empty() || imagePoints[0].size() >= (size_t)settings_.nrFrames) { + settings_.outputFileName = FTL_CONFIG_ROOT "/cam0.xml"; + bool r = runCalibrationAndSave(settings_, imageSize[0], + cameraMatrix[0], distCoeffs[0], imagePoints[0], + grid_width, release_object); + settings_.outputFileName = FTL_CONFIG_ROOT "/cam1.xml"; + r &= runCalibrationAndSave(settings_, imageSize[1], + cameraMatrix[1], distCoeffs[1], imagePoints[1], + grid_width, release_object); + + if (!r && view[0].empty()) { + LOG(ERROR) << "Not enough frames to calibrate"; + return false; + } else if (r) { + LOG(INFO) << "Calibration successful"; + break; + } + } - //! [get_input] - imageSize = view.size(); // Format input image. - if( settings_.flipVertical ) flip( view, view, 0 ); + imageSize[0] = view[0].size(); // Format input image. + imageSize[1] = view[1].size(); + //if( settings_.flipVertical ) flip( view[cam], view[cam], 0 ); //! [find_pattern] - vector<Point2f> pointBuf; - - bool found; + vector<Point2f> pointBuf[2]; - int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE; - - if(!settings_.useFisheye) { - // fast check erroneously fails with high distortions like fisheye - chessBoardFlags |= CALIB_CB_FAST_CHECK; - } + bool found1,found2; - switch( settings_.calibrationPattern ) // Find feature points on the input format - { - case Settings::CHESSBOARD: - found = findChessboardCorners( view, settings_.boardSize, pointBuf, chessBoardFlags); - break; - case Settings::CIRCLES_GRID: - found = findCirclesGrid( view, settings_.boardSize, pointBuf ); - break; - case Settings::ASYMMETRIC_CIRCLES_GRID: - found = findCirclesGrid( view, settings_.boardSize, pointBuf, CALIB_CB_ASYMMETRIC_GRID ); - break; - default: - found = false; - break; - } - //! [find_pattern] - //! [pattern_found] - if ( found) // If done with success, + found1 = findChessboardCorners( view[0], settings_.boardSize, pointBuf[0], chessBoardFlags); + found2 = findChessboardCorners( view[1], settings_.boardSize, pointBuf[1], chessBoardFlags); + + if (found1 && found2) // If done with success, { // improve the found corners' coordinate accuracy for chessboard - if( settings_.calibrationPattern == Settings::CHESSBOARD) - { Mat viewGray; - cvtColor(view, viewGray, COLOR_BGR2GRAY); - cornerSubPix( viewGray, pointBuf, Size(winSize,winSize), + cvtColor(view[0], viewGray, COLOR_BGR2GRAY); + cornerSubPix( viewGray, pointBuf[0], Size(winSize,winSize), Size(-1,-1), TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001 )); - } - - if( mode == CAPTURING && // For camera only take new samples after delay time - (clock() - prevTimestamp > settings_.delay*1e-3*CLOCKS_PER_SEC) ) - { - imagePoints.push_back(pointBuf); - prevTimestamp = clock(); - // blinkOutput = s.inputCapture.isOpened(); - } + + cvtColor(view[1], viewGray, COLOR_BGR2GRAY); + cornerSubPix( viewGray, pointBuf[1], Size(winSize,winSize), + Size(-1,-1), TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001 )); + + imagePoints[0].push_back(pointBuf[0]); + imagePoints[1].push_back(pointBuf[1]); // Draw the corners. - drawChessboardCorners( view, settings_.boardSize, Mat(pointBuf), found ); + drawChessboardCorners( view[0], settings_.boardSize, Mat(pointBuf[0]), found1 ); + drawChessboardCorners( view[1], settings_.boardSize, Mat(pointBuf[1]), found2 ); } else { LOG(WARNING) << "No calibration pattern found"; } - //! [pattern_found] - //----------------------------- Output Text ------------------------------------------------ - //! [output_text] - /*string msg = (mode == CAPTURING) ? "100/100" : - mode == CALIBRATED ? "Calibrated" : "Press 'g' to start"; - int baseLine = 0; - Size textSize = getTextSize(msg, 1, 1, 1, &baseLine); - Point textOrigin(view.cols - 2*textSize.width - 10, view.rows - 2*baseLine - 10); - - if( mode == CAPTURING ) - { - if(s.showUndistorsed) - msg = format( "%d/%d Undist", (int)imagePoints.size(), s.nrFrames ); - else - msg = format( "%d/%d", (int)imagePoints.size(), s.nrFrames ); - } - - putText( view, msg, textOrigin, 1, 1, mode == CALIBRATED ? GREEN : RED); - if( blinkOutput ) - bitwise_not(view, view);*/ - //! [output_text] - //------------------------- Video capture output undistorted ------------------------------ - //! [output_undistorted] - /*if( mode == CALIBRATED && settings_.showUndistorsed ) - { - Mat temp = view.clone(); - if (settings_.useFisheye) - cv::fisheye::undistortImage(temp, view, cameraMatrix, distCoeffs); - else - cv::undistort(temp, view, cameraMatrix, distCoeffs); - }*/ - //! [output_undistorted] - //------------------------------ Show image and check for input commands ------------------- - //! [await_input] - imshow("Image View", view); + imshow("Left", view[0]); + imshow("Right", view[1]); char key = (char)waitKey(settings_.delay); if( key == 27 ) break; - - /*if( s.inputCapture.isOpened() && key == 'g' ) - { - mode = CAPTURING; - imagePoints.clear(); - }*/ - //! [await_input] - if (mode == CALIBRATED) break; } - if (mode != CALIBRATED) return false; + /*for (auto cam=0; cam<2; cam++) { Mat view, rview; if (settings_.useFisheye) { Mat newCamMat; - fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize, + fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix[cam], distCoeffs[cam], imageSize[cam], Matx33d::eye(), newCamMat, 1); - fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(), newCamMat, imageSize, + fisheye::initUndistortRectifyMap(cameraMatrix[cam], distCoeffs[cam], Matx33d::eye(), newCamMat, imageSize[cam], CV_16SC2, map1_[cam], map2_[cam]); } else { initUndistortRectifyMap( - cameraMatrix, distCoeffs, Mat(), - getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize, + cameraMatrix[cam], distCoeffs[cam], Mat(), + getOptimalNewCameraMatrix(cameraMatrix[cam], distCoeffs[cam], imageSize[cam], 1, imageSize[cam], 0), imageSize[cam], CV_16SC2, map1_[cam], map2_[cam]); } + }*/ return true; } diff --git a/cv-node/src/main.cpp b/cv-node/src/main.cpp index cc3e21921..8708bee42 100644 --- a/cv-node/src/main.cpp +++ b/cv-node/src/main.cpp @@ -3,6 +3,8 @@ #include <ftl/synched.hpp> #include <ftl/calibrate.hpp> +#include <glog/logging.h> + #include <string> #include <vector> @@ -76,7 +78,13 @@ int main(int argc, char **argv) { Calibrate calibrate(lsrc, OPTION_calibration_config); - if (!calibrate.isCalibrated()) calibrate.recalibrate(); + if (OPTION_calibrate) { + calibrate.recalibrate(); + } + + if (!calibrate.isCalibrated()) { + LOG(WARNING) << "Cameras are not calibrated!"; + } while (true) { Mat l, r; -- GitLab