Open3d利用彩色图和深度图生成点云进行室内三维重建

上一次得到的点云图在累加多张后配准会出现少量离群的点云,效果很差,于是考虑从 ICL-NUIM dataset这个数据集获得官方的室内图进行三维重建,数据集网址如下:

ICL-NUIM RGB-D Benchmark Dataset

一. 数据筛选

首先第一步,从九百多张彩色图和深度图中挑选部分图片进行点云生成,因为九百多张图太多了,重复的内容太多用来重建计算量太大(其实就是电脑配置不行)。

我选的是Living Room 'lr kt1'这个数据集,965张图,选36张,所以大概间隔27张选一张吧。注意,open3d生成rgbd图需要彩色图的深度是8位三通道或者是8位灰度图,所以在筛选时就要改成位深度,不然后面会报错说格式不符合要求: [CreateFromColorAndDepth] Unsupported image format

代码如下:

from PIL import Image
import os

def load(from_path, out_path):
    dirs = os.listdir(from_path)
    os.chdir(from_path)
    for file in dirs:        
        # 把文件类型后缀去掉后就只剩数字,所以转换成数字然后每27张选一张出来
        if(int(file.strip('.png')) % 27 == 0):
            image = Image.open(file) 
            # 这一步将彩色图转化为8位灰度图,会使后续点云没有颜色,建议保存成彩色8位
            # image = image.convert('L')
            image.save(os.path.join(out_path, file))  
   
# 这是rgb图的路径,转换深度图就把路径改成depth的
load('.\pcldata\living_room_traj1_frei_png/rgb', '.\pcldata\living_room/rgb')

二.数据转换

然后使用open3d的create_from_color_and_depth函数将彩色图和深度图转换成RGBD图,注意,这里对格式的要求是,彩色图是8位深度三通道,深度图是16位深度,右键图片看看自己图片符不符合标准。还要注意的一点就是彩色图和深度图的size要一样大,我这里下载的数据集就都是640x480的。

然后,用以下的代码生成RGBD图并利用RGBD图生成点云。

import open3d as o3d
import matplotlib.pyplot as plt # plt 用于显示图片
import numpy as np
import os

rgb_path = '.\pcldata\living_room/rgb/'
depth_path = '.\pcldata\living_room\depth/'
rgb_dirs = os.listdir(rgb_path)
depth_dirs = os.listdir(depth_path)
print("读取RGB图片:", len(rgb_dirs), "张")
print("读取Depth图片:", len(depth_dirs), "张")

#一共转换36张图
for i in range(36):

    color_raw = o3d.io.read_image(rgb_path + rgb_dirs[i])
    depth_raw = o3d.io.read_image(depth_path + depth_dirs[i])
    # 这一步因为我的深度图的值都在10000左右,但depth_scale默认值是1000,我就把depth_trunc从默认的3改成30,深度就显示出来,原理不是很懂
    rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(color_raw, depth_raw, depth_scale=1000.0, depth_trunc=30, convert_rgb_to_intensity=False)
    plt.subplot(1, 2, 1)
    plt.title('read_depth')
    plt.imshow(rgbd_image.color)
    plt.subplot(1, 2, 2)
    plt.title('depth image')
    plt.imshow(rgbd_image.depth)
    plt.show()
    # 若要查看自己的深度图值是多少,使用下面的np函数显示
    # print(np.asarray(rgbd_image.depth))
    pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image,o3d.camera.PinholeCameraIntrinsic(
            o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault))
    print("第%d张点云数据:"%i, pcd)
    pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
    # o3d.visualization.draw_geometries([pcd])
    o3d.io.write_point_cloud("./pcldata/living_room/pcd/%d.pcd" %i, pcd)

我遇到的一个问题是生成的RGBD图中的深度图是纯黑的,如下图

Open3d利用彩色图和深度图生成点云进行室内三维重建_第1张图片

 然后我用 print(np.asarray(rgbd_image.depth)) 看了下图片的深度值,基本在10000左右,但我看官方文档实例的图片深度在两三千浮动,怀疑自己的深度值太大导致的,然后看了下 PointCloud.create_from_rgbd_image 这个函数的文档,有个默认值depth_scale 的值是1000,我的深度范围10000明显超过了它的范围,我试了两种方法,一个是把depth_scale改成10000,深度图正常显示了,另一个方法是depth_scale还是保持1000不变,depth_trunc从默认值3改到30,也能正常显示,效果基本一样,我就用了第二种方法。显示效果如下:

Open3d利用彩色图和深度图生成点云进行室内三维重建_第2张图片

至此,RGBD图的生成就结束了,接下来只需调用自带的点云生成函数PointCloud.create_from_rgbd_image 就好了,注意,如果要生成彩色点云,convert_rgb_to_intensity参数需要设为False。在可视化点云的时候官方文档加了个参数

zoom = 0.5,我加了这个参数后可视化就报错,把它删了就正常了。

 Open3d利用彩色图和深度图生成点云进行室内三维重建_第3张图片

 保存下来,下一步准备进行点云配准和室内三维重建的工作。

你可能感兴趣的:(计算机视觉,图像处理)