我有一个 2d RGB 图像数据集,我想生成一个 3D 点云作为 PLY 文件或 CSV 文件,格式如下 x、y、z、r、g、b。
我应该先将 2D 图像转换为深度图吗?
我尝试将一张图像转换为深度图,我想使用以下函数来创建 3d 点云,但问题是我不知道我可以在 fx、fy、cx、cy 中输入哪些值有人有想法可以帮助我。
import numpy as np
from PIL import Image
import imageio
import Openexr
import struct
import os
def get_pointcloud(color_image,depth_image,camera_intrinsics):
""" creates 3D point cloud of rgb images by taking depth information
input : color image: numpy array[h,w,c], dtype= uint8
depth image: numpy array[h,w] values of all channels will be same
output : camera_points, color_points - both of shape(no. of pixels, 3)
"""
image_height = depth_image.shape[0]
image_width = depth_image.shape[1]
pixel_x,pixel_y = np.meshgrid(np.linspace(0,image_width-1,image_width),
np.linspace(0,image_height-1,image_height))
camera_points_x = np.multiply(pixel_x-camera_intrinsics[0,2],depth_image/camera_intrinsics[0,0])
camera_points_y = np.multiply(pixel_y-camera_intrinsics[1,2],depth_image/camera_intrinsics[1,1])
camera_points_z = depth_image
camera_points = np.array([camera_points_x,camera_points_y,camera_points_z]).transpose(1,2,0).reshape(-1,3)
color_points = color_image.reshape(-1,3)
# Remove invalid 3D points (where depth == 0)
valid_depth_ind = np.where(depth_image.flatten() > 0)[0]
camera_points = camera_points[valid_depth_ind,:]
color_points = color_points[valid_depth_ind,:]
return camera_points,color_points
def write_pointcloud(filename,xyz_points,rgb_points=None):
""" creates a .pkl file of the point clouds generated
"""
assert xyz_points.shape[1] == 3,'Input XYZ points should be Nx3 float array'
if rgb_points is None:
rgb_points = np.ones(xyz_points.shape).astype(np.uint8)*255
assert xyz_points.shape == rgb_points.shape,'Input RGB colors should be Nx3 float array and have same size as input XYZ points'
# Write header of .ply file
fid = open(filename,'wb')
fid.write(bytes('ply\n', 'utf-8'))
fid.write(bytes('format binary_little_endian 1.0\n', 'utf-8'))
fid.write(bytes('element vertex %d\n'%xyz_points.shape[0], 'utf-8'))
fid.write(bytes('property float x\n', 'utf-8'))
fid.write(bytes('property float y\n', 'utf-8'))
fid.write(bytes('property float z\n', 'utf-8'))
fid.write(bytes('property uchar red\n', 'utf-8'))
fid.write(bytes('property uchar green\n', 'utf-8'))
fid.write(bytes('property uchar blue\n', 'utf-8'))
fid.write(bytes('end_header\n', 'utf-8'))
# Write 3D points to .ply file
for i in range(xyz_points.shape[0]):
fid.write(bytearray(struct.pack("fffccc",xyz_points[i,0],xyz_points[i,1],xyz_points[i,2],
rgb_points[i,0].tostring(),rgb_points[i,1].tostring(),
rgb_points[i,2].tostring())))
fid.close()
if __name__ == '__main__':
import argparse
# Parse command line arguments
parser = argparse.ArgumentParser(
description='create point cloud from depth and rgb image.')
parser.add_argument('--rgb_filename', required=True,
help='path to the rgb image')
parser.add_argument('--depth_filename', required=True,
help="path to the depth image ")
parser.add_argument('--output_directory', required=True,
help="directory to save the point cloud file")
parser.add_argument('--fx', required=True, type=float,
help="focal length along x-axis (longer side) in pixels")
parser.add_argument('--fy', required=True, type=float,
help="focal length along y-axis (shorter side) in pixels")
parser.add_argument('--cx', required=True, type=float,
help="centre of image along x-axis")
parser.add_argument('--cy', required=True, type=float,
help="centre of image along y-axis")
args = parser.parse_args()
color_data = imageio.imread(args.rgb_filename)
# color_data = np.asarray(im_color, dtype = "uint8")
if os.path.splitext(os.path.basename(args.depth_filename))[1] == '.npy':
depth_data = np.load(args.depth_filename)
else:
im_depth = imageio.imread(args.depth_filename)
depth_data = im_depth[:,:,0] # values of all channels are equal
# camera_intrinsics = [[fx 0 cx],
# [0 fy cy],
# [0 0 1]]
camera_intrinsics = np.asarray([[args.fx, 0, args.cx], [0, args.fy, args.cy], [0, 0, 1]])
filename = os.path.basename(args.rgb_filename)[:9] + '-pointCloud.ply'
output_filename = os.path.join(args.output_directory, filename)
print("Creating the point Cloud file at : ", output_filename )
camera_points, color_points = get_pointcloud(color_data, depth_data, camera_intrinsics)
write_pointcloud(output_filename, camera_points, color_points)