鱼眼相机外参的计算和图像的透视变换

0.前言

之前的学习中已经完成了基于鱼眼相机内参进行图像畸变校正,和相机坐标系与像素坐标系之间的转换。这一次将引入相机外参,进行外参的标定计算和基于外参+内参的鱼眼相机透视变换。

1.相机外参的定义

世界坐标系映射至相机坐标系时,需要知道世界坐标系相对于相机坐标系的变换矩阵(平移矩阵R +旋转向量T ),对于世界坐标系中的点Pw(Xw,Yw,Zw),其在相机坐标系中的坐标Pc(Xc,Yc,Zc)通过下式求得

                                                                                         Pc=R*Pw+T

我们把[R,T]称为相机外参,为了求解外参,1)需要先确定世界坐标系的分布,2)需要建立有关外参的方程组。一种常见的方法是在确定了的世界坐标系中铺设带有某种指定特征(譬如棋盘格)的标定布,标定布中特征点的世界坐标已知,然后在相机成像图片中计算得到特征点的像素坐标。问题转换为已知特征点的世界坐标,像素坐标,相机的内参和畸变参数,计算世界坐标系变换至相机坐标系的欧式变换矩阵(即外参)的问题。

2.相机外参的求解

具体数学计算流程尚未仔细阅读,这里直接调用了cv::SolvePnP函数求解R和T,函数具体说明见

  • 3
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
好的,根据您的问题,我可以提供以下的思路: 假设您已经得到了相机的内参矩阵K、畸变系数D以及外参矩阵[R|T],其中R为旋转矩阵,T为平移向量,我们可以按照以下步骤将图像转换为正视图: 1. 定义目标图像的大小,根据需求设置。 2. 根据目标图像的大小,计算出目标图像的中心点,记为center。 3. 计算相机坐标系下的相机位置,即-C,其中C = R.t() * T。 4. 计算相机坐标系下的Z轴方向,即z = (0, 0, 1) * R.t()。注意,这里的Z轴是相机坐标系下的Z轴。 5. 计算相机坐标系下的Y轴方向,即y = (0, 1, 0) * R.t()。注意,这里的Y轴是相机坐标系下的Y轴。 6. 根据中心点center、相机位置-C以及相机坐标系下的Z轴和Y轴,计算相机坐标系下的X轴方向,即x = y.cross(z)。 7. 通过调整X、Y、Z轴的方向和相机位置,使得相机坐标系下的坐标系与目标图像的坐标系重合。 8. 根据相机内参矩阵K,将相机坐标系下的坐标转换为像素坐标。 9. 根据得到的像素坐标,对原始图像进行重采样,得到目标图像。 具体的代码实现可以参考以下示例代码: ```c++ // 定义目标图像的大小 cv::Size targetSize(640, 480); // 计算目标图像的中心点 cv::Point2d center(targetSize.width / 2, targetSize.height / 2); // 计算相机坐标系下的相机位置 cv::Mat R_inv = R.t(); cv::Mat C = -R_inv * T; // 计算相机坐标系下的Z轴和Y轴方向 cv::Mat z = R_inv.row(2); cv::Mat y = R_inv.row(1); // 计算相机坐标系下的X轴方向 cv::Mat x = y.cross(z); // 调整X、Y、Z轴的方向和相机位置,使得相机坐标系下的坐标系与目标图像的坐标系重合 cv::Mat R_new = cv::Mat::zeros(3, 3, CV_64F); x.copyTo(R_new.row(0)); y.copyTo(R_new.row(1)); z.copyTo(R_new.row(2)); cv::Mat T_new = -R_new * C; // 根据相机内参矩阵K,将相机坐标系下的坐标转换为像素坐标 cv::Mat P = K * R_new * (cv::Mat::eye(3, 3, CV_64F) - K.inv() * cv::Mat(T_new) * cv::Mat(z).t()); cv::Mat src = cv::imread("image.jpg"); cv::Mat dst = cv::Mat::zeros(targetSize, src.type()); for (int i = 0; i < targetSize.height; i++) { for (int j = 0; j < targetSize.width; j++) { cv::Mat p = (cv::Mat_<double>(3, 1) << j - center.x, i - center.y, 1); cv::Mat q = P.inv() * p; q /= q.at<double>(2, 0); if (q.at<double>(0, 0) >= 0 && q.at<double>(0, 0) < src.cols && q.at<double>(1, 0) >= 0 && q.at<double>(1, 0) < src.rows) { dst.at<cv::Vec3b>(i, j) = src.at<cv::Vec3b>(q.at<double>(1, 0), q.at<double>(0, 0)); } } } ``` 以上代码可以实现将图像转换为正视图的功能。您可以根据自己的需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mega_Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值