OpenCV棋盘格相机标定:使用C++实现

相机标定是计算机视觉领域中的基础任务,用于确定相机的内参和外参。本文将介绍如何使用OpenCV库和C++编程语言,通过棋盘格图像实现相机标定。

代码解析

以下代码展示了如何加载棋盘格图像,检测角点,并进行相机标定:

cv::Mat image;
std::vector<std::vector<cv::Point3f>> objectPoints;
std::vector<std::vector<cv::Point2f>> imagePoints;

void MainWindow::loadImages()
{
    // 打开文件夹对话框,选择需要加载的图片文件夹
    QString dirName = QFileDialog::getExistingDirectory(this, tr('Open Directory'), '.', QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if (dirName.isEmpty())
        return;

    // 加载指定文件夹下的所有图片
    QStringList fileNames = QDir(dirName).entryList(QStringList() << '*.png' << '*.jpg' << '*.bmp', QDir::Files);
    int numImages = fileNames.size();
    for (int i = 0; i < numImages; i++)
    {
        QString fileName = dirName + '/' + fileNames[i];
        cv::Mat img = cv::imread(fileName.toStdString());
        if (img.empty())
            continue;

        // 检测特定点坐标
        int boardWidth = 9;
        int boardHeight = 6;
        std::vector<cv::Point2f> corners;
        bool found = cv::findChessboardCorners(img, cv::Size(boardWidth, boardHeight), corners, cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE + cv::CALIB_CB_FAST_CHECK);
        if (found)
        {
            cv::Mat gray;
            cv::cvtColor(img, gray, CV_BGR2GRAY);
            cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.1));
            cv::drawChessboardCorners(img, cv::Size(boardWidth, boardHeight), corners, found);
            imagePoints.push_back(corners);

            // 准备已知的物体点坐标,例如棋盘格
            std::vector<cv::Point3f> obj;
            for (int i = 0; i < boardHeight; i++)
                for (int j = 0; j < boardWidth; j++)
                    obj.push_back(cv::Point3f(j * 0.03f, i * 0.03f, 0.0f));
            for (int i = 0; i < corners.size(); i++)
                objectPoints.push_back(obj);
        }

        // 将检测结果显示在界面上
        cv::Mat tmp;
        cv::resize(img, tmp, cv::Size(640, 480));
        if (found)
            cv::putText(tmp, 'Chessboard Detected', cv::Point(20, 50), cv::FONT_HERSHEY_TRIPLEX, 1.0, CV_RGB(0, 255, 0), 2);
        else
            cv::putText(tmp, 'Chessboard Not Detected', cv::Point(20, 50), cv::FONT_HERSHEY_TRIPLEX, 1.0, CV_RGB(255, 0, 0), 2);
        cv::imshow('Chessboard Detection', tmp);
    }

    // 进行相机标定
    cv::Mat cameraMatrix, distCoeffs;
    std::vector<cv::Mat> rvecs, tvecs;
    cv::calibrateCamera(objectPoints, imagePoints, image.size(), cameraMatrix, distCoeffs, rvecs, tvecs);

    // 显示标定结果
    std::cout << 'Camera Matrix: ' << cameraMatrix << std::endl;
    std::cout << 'Distortion Coefficients: ' << distCoeffs << std::endl;
    cv::Mat undistorted;
    cv::undistort(image, undistorted, cameraMatrix, distCoeffs);
    cv::imshow('Undistorted Image', undistorted);
}

代码解释

  1. 加载图像: 使用 QFileDialog 选择包含棋盘格图像的文件夹,并使用 cv::imread() 函数加载所有图像。
  2. 检测角点: 使用 cv::findChessboardCorners() 函数检测图像中的棋盘格角点。
  3. 准备数据: 将检测到的角点存储在 imagePoints 中,并将已知的棋盘格三维坐标存储在 objectPoints 中。
  4. 相机标定: 使用 cv::calibrateCamera() 函数进行相机标定,得到相机内参矩阵 cameraMatrix 和畸变系数 distCoeffs
  5. 结果可视化: 打印标定结果,并使用 cv::undistort() 函数对图像进行畸变校正,最后显示校正后的图像。

总结

本文介绍了如何使用OpenCV和C++进行棋盘格相机标定。相机标定是许多计算机视觉应用的基础,希望本文能够帮助您理解其原理和实现方法。

OpenCV棋盘格相机标定:使用C++实现

原文地址: https://www.cveoy.top/t/topic/fZZy 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录