相机标定中个函数简介(经典)

问题:两条平行线可以相交于一点
在欧氏几何空间,同一平面的两条平行线不能相交,这是我们都熟悉的一种场景。
然而,在透视空间里面,两条平行线可以相交,例如:火车轨道随着我们的视线越来越窄,最后两条平行线在无穷远处交于一点。

欧氏空间(或者笛卡尔空间)描述2D/3D几何非常适合,但是这种方法却不适合处理透视空间的问题(实际上,欧氏几何是透视几何的一个子集合),2维笛卡尔坐标可以表示为(x,y)。

如果一个点在无穷远处,这个点的坐标将会(∞,∞),在欧氏空间,这变得没有意义。平行线在透视空间的无穷远处交于一点,但是在欧氏空间却不能,数学家发现了一种方式来解决这个问题。

方法:齐次坐标
简而言之,齐次坐标就是用N+1维来代表N维坐标

我们可以在一个2D笛卡尔坐标末尾加上一个额外的变量w来形成2D齐次坐标,因此,一个点(X,Y)在齐次坐标里面变成了(x,y,w),并且有

X = x/w

Y = y/w

例如,笛卡尔坐标系下(1,2)的齐次坐标可以表示为(1,2,1),如果点(1,2)移动到无限远处,在笛卡尔坐标下它变为(∞,∞),然后它的齐次坐标表示为(1,2,0),因为(1/0, 2/0) = (∞,∞),我们可以不用”∞"来表示一个无穷远处的点了,哈哈。

为什么叫齐次坐标?

我们把齐次坐标转化为笛卡尔坐标的方法是前面n-1个坐标分量分别除以最后一个分量即可。







转化齐次坐标到笛卡尔坐标的过程中,我们有一个发现,例如:





你会发现(1, 2, 3), (2, 4, 6) 和(4, 8, 12)对应同一个Euclidean point (1/3, 2/3),任何标量的乘积,例如(1a, 2a, 3a) 对应 笛卡尔空间里面的(1/3, 2/3) 。因此,这些点是“齐次的”,因为他们代表了笛卡尔坐标系里面的同一个点。换句话说,齐次坐标有规模不变性。

证明:两条直线可以相交

考虑如下方程组:




我们知道在笛卡尔坐标系里面,该方程组无解,因为C ≠ D,如果C=D,两条直线就相同了。

让我们在透视空间里面,用齐次坐标x/w, y/w代替x ,y,




现在我们有一个解(x, y, 0),两条直线相交于(x, y, 0),这个点在无穷远处。

小结:齐次坐标在图形学中是一个非常基础的概念,例如3D场景映射到2D场景的过程中

参考: http://www.songho.ca/math/homogeneous/homogeneous.html
当然可以!下面是一个示例代码,用于使用OpenCV库进行相机标定函数: ```cpp #include <opencv2/opencv.hpp> void cameraCalibration(const std::vector<std::string>& imagePaths, cv::Size patternSize, float squareSize) { // 创建存储角点的数组 std::vector<std::vector<cv::Point2f>> imagePoints; std::vector<cv::Point3f> objectPoints; // 准备物体坐标系中的角点坐标 for (int i = 0; i < patternSize.height; ++i) { for (int j = 0; j < patternSize.width; ++j) { objectPoints.push_back(cv::Point3f(j * squareSize, i * squareSize, 0)); } } // 遍历每张图像进行角点检测 cv::Mat grayImage; for (const std::string& imagePath : imagePaths) { cv::Mat image = cv::imread(imagePath); cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY); std::vector<cv::Point2f> corners; bool patternFound = cv::findChessboardCorners(grayImage, patternSize, corners); if (patternFound) { // 收集角点坐标 imagePoints.push_back(corners); } } // 相机标定 cv::Mat cameraMatrix, distCoeffs; std::vector<cv::Mat> rvecs, tvecs; cv::calibrateCamera(objectPoints, imagePoints, grayImage.size(), cameraMatrix, distCoeffs, rvecs, tvecs); // 输出结果 std::cout << "Camera matrix:\n" << cameraMatrix << std::endl; std::cout << "Distortion coefficients:\n" << distCoeffs << std::endl; } ``` 你可以调用 `cameraCalibration` 函数,并传入一系列用于标定的图像路径、棋盘格角点数量和棋盘格方格大小。该函数会返回相机矩阵和畸变系数。 请注意,这只是一个简单的示例代码,实际应用中可能需要更多的错误处理和参数调整。此外,你还需要安装OpenCV库并在项目中包含相应的头文件和链接库。 希望这可以帮助到你!如果你有其他问题,请随时问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值