当前位置: 首页 > article >正文

OpenCV相机标定与3D重建(3)校正鱼眼镜头畸变的函数calibrate()的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

cv::fisheye::calibrate 函数是 OpenCV 中用于校正鱼眼镜头畸变的一个重要函数。该函数通过一系列棋盘格标定板的图像来计算相机的内参矩阵和畸变系数。

函数原型

double cv::fisheye::calibrate	
(
	InputArrayOfArrays 	objectPoints,
	InputArrayOfArrays 	imagePoints,
	const Size & 	image_size,
	InputOutputArray 	K,
	InputOutputArray 	D,
	OutputArrayOfArrays 	rvecs,
	OutputArrayOfArrays 	tvecs,
	int 	flags = 0,
	TermCriteria 	criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 100, DBL_EPSILON) 
)	

参数

  • 参数objectPoints:标定图案坐标空间中标定图案点的向量的向量。
  • 参数imagePoints:标定图案点投影的向量的向量。对于每个 i,imagePoints.size() 和 objectPoints.size() 以及 imagePoints[i].size() 必须等于 objectPoints[i].size()。
  • 参数image_size:仅用于初始化相机内参矩阵的图像尺寸。
  • 参数K:输出 3x3 浮点型相机内参矩阵 K = [ f x 0 c x 0 f y c y 0 0 1 ] K = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} K= fx000fy0cxcy1 。如果指定了 fisheye::CALIB_USE_INTRINSIC_GUESS,则 fx, fy, cx, cy 中的一些或全部必须在调用函数前初始化。
  • 参数D:输出的畸变系数向量 D = [ k 1 k 2 k 3 k 4 ] D = \begin{bmatrix} k_1 & k_2 & k_3 & k_4 \end{bmatrix} D=[k1k2k3k4]
  • 参数rvecs:输出的旋转向量向量(见 Rodrigues),每个元素是一个 3x1 向量,表示每个图案视图的旋转。每个第 k 个旋转向量与对应的第 k 个平移向量(见下一个输出参数描述)一起,将标定板从模型坐标空间(在其中指定物体点)带到世界坐标空间,即标定板在第 k 个图案视图中的真实位置(k=0…M-1)。
  • 参数tvecs:输出的平移向量向量,每个元素是一个 3x1 向量,表示每个图案视图的平移。
  • 参数flags:不同的标志,可以是零或以下值的组合:
    • fisheye::CALIB_USE_INTRINSIC_GUESS:cameraMatrix 包含有效的初始值 fx, fy, cx, cy,这些值将进一步优化。否则,(cx, cy) 最初设置为图像中心(使用 imageSize),焦距以最小二乘法计算。
    • fisheye::CALIB_RECOMPUTE_EXTRINSIC:每次内在参数优化迭代后,外在参数将重新计算。
    • fisheye::CALIB_CHECK_COND:函数将检查条件数的有效性。
    • fisheye::CALIB_FIX_SKEW:斜率系数(alpha)设置为零并保持不变。
    • fisheye::CALIB_FIX_K1 到 fisheye::CALIB_FIX_K4:选定的畸变系数设置为零并保持不变。
    • fisheye::CALIB_FIX_PRINCIPAL_POINT:主点在全局优化过程中不改变。它保持在中心或在 fisheye::CALIB_USE_INTRINSIC_GUESS 设置时指定的不同位置。
    • fisheye::CALIB_FIX_FOCAL_LENGTH:焦距在全局优化过程中不改变。它是 max(width, height)/π 或者当
    • fisheye::CALIB_USE_INTRINSIC_GUESS 设置时提供的 fx, fy。
  • criteria:迭代优化算法的终止条件。

代码示例


#include <iostream>
#include <opencv2/calib3d.hpp>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    // 棋盘格尺寸(内部角点数)
    Size boardSize( 5, 8 );

    // 存储棋盘格角点的世界坐标
    vector< Point3f > objp;
    for ( int i = 0; i < boardSize.height; ++i )
    {
        for ( int j = 0; j < boardSize.width; ++j )
        {
            objp.push_back( Point3f( j, i, 0 ) );
        }
    }

    // 存储所有图像中的棋盘格角点的像素坐标
    vector< vector< Point2f > > imgPoints;
    // 存储所有图像中棋盘格角点的世界坐标
    vector< vector< Point3f > > objPoints;

    // 读取图像文件列表
    vector< String > imageNames;
    glob( "/media/dingxin/data/study/OpenCV/sources/images/chessboard.png", imageNames, false );

    if ( imageNames.empty() )
    {
        std::cout << "No images found at the specified path." << std::endl;
        return -1;
    }

    Mat img, gray;
    for ( const auto& imageName : imageNames )
    {
        img = imread( imageName, IMREAD_COLOR );
        if ( img.empty() )
        {
            std::cout << "Could not open or find the image: " << imageName << std::endl;
            continue;
        }

        cvtColor( img, gray, COLOR_BGR2GRAY );

        // 查找棋盘格角点
        vector< Point2f > corners;
        bool found = findChessboardCorners( gray, boardSize, corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK );
        if ( found )
        {
            // 亚像素精确定位
            cornerSubPix( gray, corners, Size( 11, 11 ), Size( -1, -1 ), TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1 ) );

            // 添加角点到 imgPoints 和 objPoints
            imgPoints.push_back( corners );
            objPoints.push_back( objp );

            // 绘制角点
            drawChessboardCorners( img, boardSize, corners, found );
            imshow( "Found Corners", img );
            waitKey( 500 );
        }
        else
        {
            std::cout << "Could not find chessboard corners in image: " << imageName << std::endl;
        }
    }

    // 检查是否有足够的图像用于校准
    if ( imgPoints.empty() )
    {
        std::cout << "No valid images found for calibration." << std::endl;
        return -1;
    }

    // 相机内参矩阵
    Mat K = Mat::eye( 3, 3, CV_64F );
    // 畸变系数
    Mat D = Mat::zeros( 4, 1, CV_64F );
    // 终止条件
    TermCriteria criteria( TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON );

    // 校准
    int flags  = cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC + cv::fisheye::CALIB_FIX_SKEW + cv::fisheye::CALIB_CHECK_COND;
    double rms = cv::fisheye::calibrate( objPoints, imgPoints, gray.size(), K, D, noArray(), noArray(), flags, criteria );

    cout << "RMS re-projection error: " << rms << endl;
    cout << "Camera matrix:\n" << K << endl;
    cout << "Distortion coefficients:\n" << D << endl;

    // 保存结果
    FileStorage fs( "calibration_result.yml", FileStorage::WRITE );
    fs << "camera_matrix" << K;
    fs << "dist_coeffs" << D;
    fs.release();

    cv::waitKey( 0 );
    return 0;
}

运行结果

在这里插入图片描述
终端输出:

RMS re-projection error: 0.0538752
Camera matrix:
[125280.3440762279, 0, 224.5000000010562;
 0, 125280.3438483639, 149.4999999998818;
 0, 0, 1]
Distortion coefficients:
[-582.4113543586071;
 116.5218245736505;
 -11.04383019115448;
 0.5796488453961863]


http://www.kler.cn/a/407448.html

相关文章:

  • Android Gradle 插件和 Android Studio 兼容性
  • GitLab|数据迁移
  • Java集合分页
  • Unity图形学之CubeMap立方体贴图
  • Spring Aop+自定义注解实践(待完善日志)
  • RTL8211F 1000M以太网PHY指示灯
  • 【Python · PyTorch】循环神经网络 RNN(基础概念)
  • Rust 力扣 - 198. 打家劫舍
  • 【汽车制动】汽车制动相关控制系统
  • UE5材质篇5 简易水面
  • 11-23刷题记录
  • 23、论文阅读:基于多分辨率特征学习的层次注意力聚合GAN水下图像增强
  • Docker 实践与应用举例:提升开发与运维效率的利器
  • 阿里Qwen系列开源模型介绍
  • 设计模式之 原型模式
  • 高危,Laravel参数注入漏洞安全风险通告
  • 神经网络(系统性学习一):入门篇——简介、发展历程、应用领域、基本概念、超参数调优、网络类型分类
  • SQL的四种语言介绍
  • JavaWeb之综合案例
  • 笔记整理—linux驱动开发部分(15)BMP图片显示
  • 微软安全文章合集
  • Redis进阶Redission实现分布式锁
  • 微信小程序中会议列表页面的前后端实现
  • 模型压缩笔记1:模型量化
  • python正则表达式基本字符字符
  • 【深度学习之回归预测篇】 深度极限学习机DELM多特征回归拟合预测(Matlab源代码)