You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从CSV存储的3D房屋模型生成指定参数相机的多姿态成像

实现3D点云的相机成像模拟

我来帮你把3D房屋点云转换成指定相机参数下的2D成像效果,核心是基于针孔相机模型完成3D到2D的投影变换。结合你给出的参数(焦距f=400px,图像分辨率640×480),我们可以一步步修改代码实现需求:

关键原理说明

针孔相机的成像需要两个核心矩阵:

  • 内参矩阵K:由相机固有参数决定,对于你的设置:
    • fx = fy = 400(焦距,单位像素)
    • cx = 640/2 = 320,cy = 480/2 = 240(主点坐标,默认在图像中心)
      所以内参矩阵为:
    K = np.array([
        [400, 0, 320],
        [0, 400, 240],
        [0, 0, 1]
    ])
    
  • 外参矩阵:由相机姿态(旋转R和平移t)决定,用来将世界坐标系的3D点转换到相机坐标系。我们可以先从默认姿态(相机位于世界原点,朝向Z轴正方向)开始测试,再修改R和t模拟不同姿态。

修改后的完整代码

import pandas as pd
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 1. 加载3D点云数据
data1 = pd.read_csv('house.csv', sep=' ')
# 提取x,y,z并转换为numpy数组(若原数据列索引不同,可自行调整)
points_3d = data1.drop(data1.columns[3], axis=1).values  # 保留前3列作为x,y,z坐标

# 2. 定义相机参数
f = 400
width, height = 640, 480
# 内参矩阵K
K = np.array([
    [f, 0, width/2],
    [0, f, height/2],
    [0, 0, 1]
])
# 默认外参:相机在世界原点,朝向Z轴正方向
R = np.eye(3)
t = np.array([[0], [0], [0]])
# 构造齐次外参矩阵
extrinsic = np.hstack((R, t))
extrinsic = np.vstack((extrinsic, np.array([0, 0, 0, 1])))

# 3. 将3D点转换为齐次坐标并变换到相机坐标系
points_3d_hom = np.hstack((points_3d, np.ones((points_3d.shape[0], 1))))  # 转为(N,4)齐次坐标
points_cam_hom = extrinsic @ points_3d_hom.T  # 变换到相机坐标系
points_cam = points_cam_hom[:3, :].T  # 提取相机坐标系下的3D点

# 4. 过滤相机后方不可见的点(Z轴坐标<=0的点)
visible_mask = points_cam[:, 2] > 0
points_cam_visible = points_cam[visible_mask]

# 5. 投影到图像平面
points_img_hom = K @ points_cam_visible.T  # 内参投影
points_img = (points_img_hom[:2, :] / points_img_hom[2, :]).T  # 归一化得到像素坐标(u,v)

# 6. 生成相机成像图
img = np.zeros((height, width, 3), dtype=np.uint8)
# 绘制投影后的点(红色圆点)
for u, v in points_img:
    u_int, v_int = int(np.round(u)), int(np.round(v))
    if 0 <= u_int < width and 0 <= v_int < height:
        cv.circle(img, (u_int, v_int), 1, (0, 0, 255), -1)

# 7. 可视化对比
plt.figure(figsize=(10,5))
# 子图1:原3D点云
plt.subplot(121, projection='3d')
plt.grid(b=None)
plt.scatter(points_3d[:,0], points_3d[:,1], points_3d[:,2], s=1)
plt.axis('off')
plt.title('3D Point Cloud')
# 子图2:相机成像效果
plt.subplot(122)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.axis('off')
plt.title('Camera Image (f=400px, 640×480)')
plt.savefig('house_camera_view.png')
plt.show()

调整相机姿态的方法

如果要模拟不同的相机视角,只需要修改旋转矩阵R和平移向量t即可:

  • 示例:让相机绕X轴旋转30度
    theta = np.radians(30)
    R = np.array([
        [1, 0, 0],
        [0, np.cos(theta), -np.sin(theta)],
        [0, np.sin(theta), np.cos(theta)]
    ])
    
  • 示例:让相机沿X轴平移10个单位
    t = np.array([[10], [0], [0]])
    

注意事项

  • 请确认你的CSV数据列索引是否正确,如果x/y/z列的位置和代码中不一致,需要调整points_3d的提取逻辑
  • 投影后的点可能会超出图像范围,代码中已经做了边界过滤,你可以根据需求调整点的大小、颜色或添加其他渲染效果

内容的提问来源于stack exchange,提问作者Corisco

火山引擎 最新活动