exr文件转ply文件

前情提要:在实践中有些3D相机只能输出exr格式的文件,为了实现3D点云的可视化,需要将其转为ply文件格式,因此找到了一下代码,可以实现该功能。

import OpenEXR
import numpy as np
from plyfile import PlyData, PlyElement


def read_exr(file_path):
    # 打开EXR文件
    exr_file = OpenEXR.InputFile(file_path)

    # 查看所有通道
    channels = exr_file.header()['channels']
    print("可用通道:", channels)  # 输出文件中所有通道的信息
    # 读取数据窗口信息
    dw = exr_file.header()['dataWindow']
    width = dw.max.x - dw.min.x + 1
    height = dw.max.y - dw.min.y + 1
    # 选择一个合适的通道名
    depth_channel = 'Y'  # 从可用通道中选择一个,如'Y'
    if depth_channel not in channels:
        raise ValueError(f"错误:通道 '{depth_channel}' 不在图像中。请检查通道名称。")

    # 读取深度数据(假设存储在'Y'通道中)直接不使用PixelType对象
    depth_str = exr_file.channel(depth_channel)  # 直接读取
    depth_array = np.frombuffer(depth_str, dtype=np.float32)
    depth_array.shape = (height, width)

    exr_file.close()
    return depth_array


def depth_to_point_cloud(depth_array, fx, fy, cx, cy):
    height, width = depth_array.shape
    xx, yy = np.meshgrid(np.arange(width), np.arange(height))

    # 计算三维坐标
    X = (xx - cx) * depth_array / fx
    Y = (yy - cy) * depth_array / fy
    Z = depth_array

    # 只提取有效的深度值
    mask = Z > 0  # 过滤掉无效点
    points = np.array([X[mask], Y[mask], Z[mask]]).T  # 将XYZ坐标合并为点云

    return points


def write_ply(file_path, points):
    # 创建PLY元素
    vertex = np.array([(p[0], p[1], p[2]) for p in points], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
    ply_data = PlyData([PlyElement.describe(vertex, 'vertex')], text=True)

    # 写入PLY文件
    ply_data.write(file_path)


if __name__ == '__main__':
    # 使用示例
    exr_file_path = 'E:/logs/depth.exr'  # 输入EXR深度图的路径
    ply_file_path = 'E:/logs/depth.ply'  # 输出PLY点云文件的路径

    # 摄像机内参(根据你的相机标定信息调整)
    fx, fy = 1.37599402e+03, 1.37599548e+03  # 焦距,假设为525像素
    cx, cy = 9.56831726e+02, 5.94493591e+02  # 主点坐标,假设为图像中心

    # 1. 读取深度图
    depth_array = read_exr(exr_file_path)

    # 2. 深度图转换为点云
    points = depth_to_point_cloud(depth_array, fx, fy, cx, cy)

    # 3. 写入PLY文件
    write_ply(ply_file_path, points)

    print(f"点云已保存到 {ply_file_path}")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值