利用aruco标定板标定相机

发布于:2025-07-24 ⋅ 阅读:(23) ⋅ 点赞:(0)

1、生成aruco标定板

#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/objdetect/aruco_detector.hpp>
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

int main() 
{
    int markersX = 17;
    int markersY = 12;
    int markerLength = 200;
    int markerSeparation = 44;
    int margins = markerSeparation;
    int borderBits = 1;
    bool showImage = false;
    String out = "aruco_board4.png";

    Size imageSize;
    imageSize.width = markersX * (markerLength + markerSeparation) - markerSeparation + 2 * margins;
    imageSize.height = markersY * (markerLength + markerSeparation) - markerSeparation + 2 * margins;

    aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
    aruco::GridBoard board(Size(markersX, markersY), float(markerLength), float(markerSeparation), dictionary);

    Mat boardImage;
    board.generateImage(imageSize, boardImage, margins, borderBits);

    imwrite(out, boardImage);

    return 0;
}

2、利用aruco标定板标定相机

#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/objdetect/aruco_detector.hpp>
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

int main() 
{
    int markersX = 17;
    int markersY = 12;
    float markerLength = 200;
    float markerSeparation = 44;
    string outputFile = "cam3.yml";
    int calibrationFlags = 0;
    float aspectRatio = 1;
    aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
    aruco::DetectorParameters detectorParams;

    bool refindStrategy = false;
    int camId = 0;

    aruco::GridBoard gridboard(Size(markersX, markersY), markerLength, markerSeparation, dictionary);
    aruco::ArucoDetector detector(dictionary, detectorParams);

    vector<vector<vector<Point2f>>> allMarkerCorners;
    vector<vector<int>> allMarkerIds;
    Size imageSize;

    vector<string> imgPath;
    glob("E:\\相机标定\\0723\\calib1_1\\*.jpg", imgPath);

    for (int i = 0; i < 1; i++)
    {
        Mat image, imageCopy;
        image = imread(imgPath[i]);

        vector<int> markerIds;
        vector<vector<Point2f>> markerCorners, rejectedMarkers;

        detector.detectMarkers(image, markerCorners, markerIds, rejectedMarkers);

        if (refindStrategy) {
            detector.refineDetectedMarkers(image, gridboard, markerCorners, markerIds, rejectedMarkers);
        }

        image.copyTo(imageCopy);

        if (!markerIds.empty()) {
            aruco::drawDetectedMarkers(imageCopy, markerCorners, markerIds);
        }

        std::cout << "markerIds.size() = " << markerIds.size() << std::endl;

        namedWindow("out", cv::WINDOW_NORMAL);
        resizeWindow("out", imageCopy.cols * 0.4, imageCopy.rows * 0.4);
        imshow("out", imageCopy);
        waitKey(0);
        cv::imwrite("draw.bmp", imageCopy);

        if (!markerIds.empty()) {
            allMarkerCorners.push_back(markerCorners);
            allMarkerIds.push_back(markerIds);
            imageSize = image.size();
        }
    }

    if (allMarkerIds.empty()) {
        throw std::runtime_error("Not enough captures for calibration\n");
    }

    Mat cameraMatrix, distCoeffs;
    if (calibrationFlags & CALIB_FIX_ASPECT_RATIO) {
        cameraMatrix = Mat::eye(3, 3, CV_64F);
        cameraMatrix.at<double>(0, 0) = aspectRatio;
    }

    vector<Point3f> objectPoints;
    vector<Point2f> imagePoints;
    vector<Mat> processedObjectPoints, processedImagePoints;
    size_t nFrames = allMarkerCorners.size();

    for (size_t frame = 0; frame < nFrames; frame++) {
        Mat currentImgPoints, currentObjPoints;
        gridboard.matchImagePoints(allMarkerCorners[frame], allMarkerIds[frame], currentObjPoints, currentImgPoints);
        if (currentImgPoints.total() > 0 && currentObjPoints.total() > 0) {
            processedImagePoints.push_back(currentImgPoints);
            processedObjectPoints.push_back(currentObjPoints);
        }
    }

    double repError = calibrateCamera(processedObjectPoints, processedImagePoints, imageSize, cameraMatrix, distCoeffs,
        noArray(), noArray(), noArray(), noArray(), noArray(), calibrationFlags);
    bool saveOk = saveCameraParams(outputFile, imageSize, aspectRatio, calibrationFlags,
        cameraMatrix, distCoeffs, repError);

    std::cout << "Rep Error: " << repError << endl;
    std::cout << "Calibration saved to " << outputFile << endl;

    std::cout << "cameraMatrix = " << cameraMatrix << endl;
    std::cout << "distCoeffs = " << distCoeffs << endl;
    return 0;
}