diff --git a/CMakeLists.txt b/CMakeLists.txt index 594485f..d3e6b80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,8 +21,15 @@ add_executable(calibration calibration.cpp ) +add_executable(calibrationCharuco + ${COMMON_SOURCES} + calibrationCharuco.cpp +) + target_link_libraries( calibration -llccv ${OpenCV_LIBS} ) +target_link_libraries( calibrationCharuco -llccv ${OpenCV_LIBS} ) + # Project 2 sources and executable set(arucoDetectionSources ${COMMON_SOURCES} diff --git a/aruco/ArucoDetector.cpp b/aruco/ArucoDetector.cpp index 6870117..5de0f18 100644 --- a/aruco/ArucoDetector.cpp +++ b/aruco/ArucoDetector.cpp @@ -91,7 +91,7 @@ std::pair>>> Ar tags = this->arucoTags; } -cv::Mat frame; + cv::Mat frame; cv::Mat frameNotRotated; cv::Mat frameDistored; cam->getVideoFrame(frameNotRotated, 1000); diff --git a/calibrationCharuco.cpp b/calibrationCharuco.cpp new file mode 100644 index 0000000..9803426 --- /dev/null +++ b/calibrationCharuco.cpp @@ -0,0 +1,121 @@ +#include +#include + +int main(int argc, char *argv[]) { + + cv::aruco::Dictionary AruCoDict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50); + + int squaresX = 1920; + int squaresY = 1080; + float squareLength = 20; + float markerLength = 10; + + cv::aruco::CharucoBoard board(cv::Size(squaresX, squaresY), squareLength, markerLength, AruCoDict); + + lccv::PiCamera cap; + cap.options->video_width=1920; + cap.options->video_height=1080; + cap.options->framerate=5; + cap.options->verbose=true; + cap.startVideo(); + + cv::Mat img, imgCopy; + + cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters(); + + cv::aruco::CharucoParameters charucoParams; + + cv::aruco::CharucoDetector detector(board, charucoParams, detectorParams); + + // Collect data from each frame + std::vector allCharucoCorners; + std::vector allCharucoIds; + + std::vector> allImagePoints; + std::vector> allObjectPoints; + + std::vector allImages; + cv::Size imageSize; + + while(true) { + cv::Mat image, imageCopy; + cap.getVideoFrame(image,1000); + + std::vector markerIds; + std::vector> markerCorners, rejectedMarkers; + cv::Mat currentCharucoCorners; + cv::Mat currentCharucoIds; + std::vector currentObjectPoints; + std::vector currentImagePoints; + + // Detect ChArUco board + detector.detectBoard(image, currentCharucoCorners, currentCharucoIds); + + // Draw results + image.copyTo(imageCopy); + if(!markerIds.empty()) { + cv::aruco::drawDetectedMarkers(imageCopy, markerCorners); + } + + if(currentCharucoCorners.total() > 3) { + cv::aruco::drawDetectedCornersCharuco(imageCopy, currentCharucoCorners, currentCharucoIds); + } + + putText(imageCopy, "Press 'c' to add current frame. 'ESC' to finish and calibrate", + cv::Point(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 0, 0), 2); + + cv::imshow("out", imageCopy); + + // Wait for key pressed + char key = static_cast(cv::waitKey(10)); + + if(key == 27) { + break; + } + + if(key == 'c' && currentCharucoCorners.total() > 3) { + // Match image points + board.matchImagePoints(currentCharucoCorners, currentCharucoIds, currentObjectPoints, currentImagePoints); + + if(currentImagePoints.empty() || currentObjectPoints.empty()) { + std::cout << "Point matching failed, try again." << std::endl; + continue; + } + + std::cout << "Frame captured" << std::endl; + + allCharucoCorners.push_back(currentCharucoCorners); + allCharucoIds.push_back(currentCharucoIds); + allImagePoints.push_back(currentImagePoints); + allObjectPoints.push_back(currentObjectPoints); + allImages.push_back(image); + + imageSize = image.size(); + } + } + + if(allCharucoCorners.size() < 4) { + std::cerr << "Not enough corners for calibration" << std::endl; + return 0; + } + + cv::Mat cameraMatrix, distCoeffs; + + int calibrationFlags = 0; + + // Calibrate camera using ChArUco + double repError = calibrateCamera( + allObjectPoints, allImagePoints, imageSize, + cameraMatrix, distCoeffs, cv::noArray(), cv::noArray(), cv::noArray(), + cv::noArray(), cv::noArray(), calibrationFlags + ); + + std::cout << "Rep Error: " << repError << std::endl; + + cv::FileStorage fs("calibration_results.yaml", cv::FileStorage::WRITE); + fs << "cameraMatrix" << cameraMatrix; + fs << "distCoeffs" << distCoeffs; + fs.release(); // Release the file + + return 0; +} \ No newline at end of file