已知双相机位姿,如何从参考视角图像重投影得到3D对象另一视角图像
基于已知位姿的视图合成解决方案
你的场景属于无遮挡、小基线的已知相机参数视图合成任务,用传统几何方法即可实现,全程可通过OpenCV离线完成,步骤如下:
前置参数准备
你需要从Unity提前导出以下参数,与I1、位姿p1/p2配套:
- 相机内参矩阵
K:启用物理相机后直接导出即可,3×3矩阵格式,包含fx(x轴焦距)、fy(y轴焦距)、cx(成像中心x坐标)、cy(成像中心y坐标),单位统一为像素;若p1、p2下相机内参有调整,分别导出K1、K2即可 - I1对应的线性深度图
D1:Unity渲染I1时同步输出,深度值为p1相机坐标系下的真实距离,不要用默认归一化到0-1的裁剪深度,单位和位姿中的平移量单位(一般为米)保持一致 - 位姿转换为标准外参格式:将p1、p2转换为3×4的外参矩阵
[R | t],R为3×3旋转矩阵,t为3×1平移向量,代表世界坐标系到当前相机坐标系的变换
核心计算流程
步骤1:计算p1到p2的相对变换
R_rel = R2 @ R1.T t_rel = t2 - R_rel @ t1
步骤2:对I1所有像素反投影生成3D点
遍历I1的每个像素坐标(u, v),结合深度值D1[u][v]反投影到p1相机坐标系的3D点:
X1 = D1[u][v] * np.linalg.inv(K1) @ np.array([u, v, 1]).T
再转换到世界坐标系:
X_world = R1.T @ (X1 - t1)
步骤3:将3D点投影到p2的图像平面
将世界坐标系下的3D点转换到p2相机坐标系:
X2 = R2 @ X_world + t2
再投影为p2图像的像素坐标:
u2 = (K2[0][0] * X2[0] / X2[2]) + K2[0][2] v2 = (K2[1][1] * X2[1] / X2[2]) + K2[1][2]
步骤4:像素赋值与后处理
将I1中(u, v)的像素值赋值给I2中浮点坐标(u2, v2)对应的位置,完成后做两个优化:
- 用双线性插值处理非整数坐标的像素错位
- 极小的未赋值空洞直接用
cv2.inpaint()填充即可,因为位姿差极小,不会出现大面积空洞
可选优化方案
如果不想每次从Unity导出深度图,可利用你已有的(p1,p2,I1,I2)配对数据集,训练一个轻量的单视图人体深度估计网络,推理时直接从I1预测深度,再执行上述warp流程即可脱离Unity运行。
如果出现极微小的遮挡或几何计算偏差,可结合cv2.calcOpticalFlowFarneback()计算的光流结果,对投影坐标做加权修正,生成的I2边缘会更平滑。
内容的提问来源于stack exchange,提问作者chronosynclastic
相关产品推荐
相关产品推荐

