示例#1
0
def visualise_rgbd_cloud(key_list, resolution_height, resolution_width,
                         device_manager, coordinate_dimentions,
                         transformation_devices):
    # enable visualiser
    align = rs.align(rs.stream.depth)
    vis = o3d.Visualizer()
    vis.create_window('PCD', width=1280, height=720)
    pointcloud = o3d.PointCloud()
    geom_added = False
    voxel_size = 0.005

    while True:
        cloud_pcd = o3d.PointCloud()
        for (serial, device) in device_manager._enabled_devices.items():
            frames = device.pipeline.wait_for_frames()
            frames = align.process(frames)
            profile = frames.get_profile()
            depth_frame = frames.get_depth_frame()
            color_frame = frames.get_color_frame()
            if not depth_frame or not color_frame:
                continue

            # Convert images to numpy arrays
            depth_image = np.asanyarray(depth_frame.get_data())
            color_image = np.asanyarray(color_frame.get_data())

            img_depth = o3d.Image(depth_image)
            img_color = o3d.Image(color_image)
            rgbd = o3d.create_rgbd_image_from_color_and_depth(
                img_color, img_depth, convert_rgb_to_intensity=False)

            intrinsics = profile.as_video_stream_profile().get_intrinsics()
            pinhole_camera_intrinsic = o3d.PinholeCameraIntrinsic(
                intrinsics.width, intrinsics.height, intrinsics.fx,
                intrinsics.fy, intrinsics.ppx, intrinsics.ppy)
            pcd = o3d.create_point_cloud_from_rgbd_image(
                rgbd, pinhole_camera_intrinsic)

            pcd.transform(transformation_devices[serial].pose_mat)
            pointcloud.points = pcd.points
            pointcloud.colors = pcd.colors

            cloud_pcd = cloud_pcd + pointcloud

        #pcd = o3d.geometry.voxel_down_sample(cloud_pcd,
        # voxel_size=voxel_size)
        while True:
            if geom_added == False:
                vis.add_geometry(cloud_pcd)
                geom_added = True

            vis.update_geometry()
            vis.poll_events()
            vis.update_renderer()
示例#2
0
def save_depth_maps(mesh, intrinsic, extrinsics, filenames):
  glb = save_depth_maps
  glb.index = -1

  # intrinsics assumed by the renderer - corrected later
  cx = intrinsic.width/2.0-0.5
  cy = intrinsic.height/2.0-0.5
  f = max(intrinsic.get_focal_length())
  glb.intrinsic = open3d.PinholeCameraIntrinsic(intrinsic.width, intrinsic.height,
    f, f, cx, cy)
  glb.extrinsics = extrinsics
  glb.filenames = filenames
  glb.vis = open3d.Visualizer()

  # affine matrix for correction
  offset_x = intrinsic.get_principal_point()[0] - \
             intrinsic.get_focal_length()[0]/f*cx
  offset_y = intrinsic.get_principal_point()[1] - \
             intrinsic.get_focal_length()[1]/f*cy
  glb.affine_M = np.asarray([
    [intrinsic.get_focal_length()[0]/f, 0, offset_x],
    [0, intrinsic.get_focal_length()[1]/f, offset_y]],
    dtype=np.float32)

  def callback(vis):
    ctr = vis.get_view_control()
    glb = save_depth_maps
    if glb.index >= 0:
      depth = np.asarray(vis.capture_depth_float_buffer(False), dtype=np.float32)
      # correct the depth map (useful if your camera has non-ideal intrinsics)
      depth = cv2.warpAffine(depth, glb.affine_M,
        (depth.shape[1], depth.shape[0]), cv2.WARP_INVERSE_MAP,
        cv2.BORDER_CONSTANT, 0)
      cv2.imwrite(glb.filenames[glb.index], np.uint16(np.asarray(depth) * 1000))

    glb.index = glb.index + 1
    if glb.index < len(glb.extrinsics):
      ctr.convert_from_pinhole_camera_parameters(glb.intrinsic,
        glb.extrinsics[glb.index])
    else:
      glb.vis.register_animation_callback(None)
    return False

  vis = glb.vis
  vis.create_window(width=intrinsic.width, height=intrinsic.height)
  vis.add_geometry(mesh)
  vis.register_animation_callback(callback)
  vis.run()
  vis.destroy_window()
    def __init__(self):
        # Kinect runtime object
        self.joint_count = PyKinectV2.JointType_Count  # 25
        self.kinect = PyKinectRuntime.PyKinectRuntime(
            PyKinectV2.FrameSourceTypes_Body
            | PyKinectV2.FrameSourceTypes_Color
            | PyKinectV2.FrameSourceTypes_Depth)

        self.depth_width, self.depth_height = self.kinect.depth_frame_desc.Width, self.kinect.depth_frame_desc.Height  # Default: 512, 424
        self.color_width, self.color_height = self.kinect.color_frame_desc.Width, self.kinect.color_frame_desc.Height  # Default: 1920, 1080

        # User defined variables
        self.depth_scale = 0.001  # Default kinect depth scale where 1 unit = 0.001 m = 1 mm
        # depth_scale                 = 1.0 # Default kinect depth scale where 1 unit = 0.001 m = 1 mm
        self.clipping_distance_in_meters = 1.5  # Set the maximum distance to display the point cloud data
        self.clipping_distance = self.clipping_distance_in_meters / self.depth_scale  # Convert dist in mm to unit
        # Hardcode the camera intrinsic parameters for backprojection
        # width=depth_width; height=depth_height; ppx=258.981; ppy=208.796; fx=367.033; fy=367.033 # Hardcode the camera intrinsic parameters for backprojection
        ppx = 260.166
        ppy = 205.197
        fx = 367.535
        fy = 367.535
        # Open3D visualisation
        self.intrinsic = open3d.PinholeCameraIntrinsic(self.depth_width,
                                                       self.depth_height, fx,
                                                       fy, ppx, ppy)
        # To convert [x,y,z] -> [x.-y,-z]
        self.flip_transform = [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0],
                               [0, 0, 0, 1]]
        # 定义图像点云
        self.image_pcd = open3d.PointCloud()
        # self.joint_pcd = open3d.PointCloud()
        # 定义原点
        self.origin_point = open3d.geometry.create_mesh_coordinate_frame(
            size=0.5, origin=[0, 0, 0])
        # 定义关节点坐标点云
        self.axis_pcd = []
        for i in range(self.joint_count):  # 25 axes for 25 joints
            # XYZ axis length of 0.1 m
            pre_axis = open3d.create_mesh_coordinate_frame(size=0.1,
                                                           origin=[0, 0, 0])
            self.axis_pcd.append(pre_axis)
        # 定义关节点点云连接线:24关节点连接线
        self.bone_line_pcd = utils.create_line_set_bones(
            np.zeros((24, 3), dtype=np.float32))
示例#4
0
def trimesh_to_open3d(src):
    if isinstance(src, trimesh.Trimesh):
        dst = open3d.TriangleMesh()
        dst.vertices = open3d.Vector3dVector(src.vertices)
        dst.triangles = open3d.Vector3iVector(src.faces)

        vertex_colors = np.zeros((len(src.vertices), 3), dtype=float)
        for face, face_color in zip(src.faces, src.visual.face_colors):
            vertex_colors[face] += face_color[:3] / 255.0  # uint8 -> float
        indices, counts = np.unique(src.faces.flatten(), return_counts=True)
        vertex_colors[indices] /= counts[:, None]
        dst.vertex_colors = open3d.Vector3dVector(vertex_colors)
        dst.compute_vertex_normals()
    elif isinstance(src, trimesh.PointCloud):
        dst = open3d.PointCloud()
        dst.points = open3d.Vector3dVector(src.vertices)
        if src.colors:
            colors = src.colors
            colors = (colors[:, :3] / 255.0).astype(float)
            dst.colors = open3d.Vector3dVector(colors)
    elif isinstance(src, trimesh.scene.Camera):
        dst = open3d.PinholeCameraIntrinsic(
            width=src.resolution[0],
            height=src.resolution[1],
            fx=src.K[0, 0],
            fy=src.K[1, 1],
            cx=src.K[0, 2],
            cy=src.K[1, 2],
        )
    elif isinstance(src, trimesh.path.Path3D):
        lines = []
        for entity in src.entities:
            for i, j in zip(entity.points[:-1], entity.points[1:]):
                lines.append((i, j))
        lines = np.vstack(lines)
        points = src.vertices
        dst = open3d.LineSet()
        dst.lines = open3d.Vector2iVector(lines)
        dst.points = open3d.Vector3dVector(points)
    elif isinstance(src, list):
        dst = [trimesh_to_open3d(x) for x in src]
    else:
        raise ValueError("Unsupported type of src: {}".format(type(src)))

    return dst
示例#5
0
def create_color_point_cloud(align_color_img, depth_img,
                             depth_scale, clipping_distance_in_meters, intrinsic):
    fx = intrinsic[0, 0]
    fy = intrinsic[1, 1]
    ppx = intrinsic[0, 2]
    ppy = intrinsic[1, 2]
    depth_height, depth_width = depth_img.shape
    intrinsic = open3d.PinholeCameraIntrinsic(depth_width, depth_height, fx, fy, ppx, ppy)
    rgbd_image = get_rgbd_image(align_color_img, depth_img, depth_scale, clipping_distance_in_meters)
    pcd = open3d.create_point_cloud_from_rgbd_image(rgbd_image, intrinsic)
    # pcd = open3d.geometry.create_point_cloud_from_rgbd_image(rgbd_image, open3d.camera.PinholeCameraIntrinsic(
    #     open3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault))
    # Point cloud only without color
    # pcd = create_point_cloud_from_depth_image(
    #     Image(depth_img),
    #     intrinsic,
    #     depth_scale=1.0/depth_scale,
    #     depth_trunc=clipping_distance_in_meters)

    return pcd.points, pcd.colors
示例#6
0
def getPcRGBD(path, idx):

    frame = 'frame-000000'
    frame = frame[:-len(idx)] + idx
    depth = frame + '.depth.png'
    depth = os.path.join(path, depth)
    rgb = frame + '.color.png'
    rgb = os.path.join(path, rgb)

    im_depth = o3d.read_image(depth)
    im_color = o3d.read_image(rgb)

    # rgbd_image = o3d.create_rgbd_image_from_color_and_depth(im_color, im_depth)

    pcd = o3d.create_point_cloud_from_depth_image(
        im_depth,
        o3d.PinholeCameraIntrinsic(
            # pcd = o3d.create_point_cloud_from_rgbd_image(rgbd_image, o3d.PinholeCameraIntrinsic(
            o3d.PinholeCameraIntrinsicParameters.PrimeSenseDefault))

    # o3d.draw_geometries([pcd])

    return pcd
    connect_device = []
    for d in rs.context().devices:
        if d.get_info(rs.camera_info.name).lower() != 'platform camera':
            connect_device.append(d.get_info(rs.camera_info.serial_number))

    if len(connect_device) < 2:
        print('Registrition needs two camera connected.But got one.')
        exit()

    pipeline1 = rs.pipeline()
    rs_config.enable_device(connect_device[0])
    pipeline_profile1 = pipeline1.start(rs_config)

    intr1 = pipeline_profile1.get_stream(
        rs.stream.color).as_video_stream_profile().get_intrinsics()
    pinhole_camera1_intrinsic = o3d.PinholeCameraIntrinsic(
        intr1.width, intr1.height, intr1.fx, intr1.fy, intr1.ppx, intr1.ppy)
    cam1 = rgbdTools.Camera(intr1.fx, intr1.fy, intr1.ppx, intr1.ppy)
    # print('cam1 intrinsics:')
    # print(intr1.width, intr1.height, intr1.fx, intr1.fy, intr1.ppx, intr1.ppy)

    pipeline2 = rs.pipeline()
    rs_config.enable_device(connect_device[1])
    pipeline_profile2 = pipeline2.start(rs_config)

    intr2 = pipeline_profile2.get_stream(
        rs.stream.color).as_video_stream_profile().get_intrinsics()
    pinhole_camera2_intrinsic = o3d.PinholeCameraIntrinsic(
        intr2.width, intr2.height, intr2.fx, intr2.fy, intr2.ppx, intr2.ppy)
    cam2 = rgbdTools.Camera(intr2.fx, intr2.fy, intr2.ppx, intr2.ppy)
    # print('cam2 intrinsics:')
    # print(intr2.width, intr2.height, intr2.fx, intr2.fy, intr2.ppx, intr2.ppy)
示例#8
0
        depth += 50*np.random.rand(*depth.shape)
        tmp_filename = osp.join('/tmp', 'depth_{:s}'.format(depth_filenames[i]))
        depth_image_path.append(tmp_filename)

    assert(len(depth_image_path) == len(color_image_path))

    # Read RGBD images
    rgbd_images = []
    for i in range(len(depth_image_path)):
        depth = open3d.read_image(depth_image_path[i])
        color = open3d.read_image(os.path.join(path, 'image', color_image_path[i]))
        rgbd_image = open3d.create_rgbd_image_from_color_and_depth(color, depth,
                convert_rgb_to_intensity = False)
        if debug_mode:
            pcd = open3d.create_point_cloud_from_rgbd_image(rgbd_image,
                    open3d.PinholeCameraIntrinsic(open3d.PinholeCameraIntrinsicParameters.PrimeSenseDefault))
            open3d.draw_geometries([pcd])
        rgbd_images.append(rgbd_image)

    # Before full optimization, let's just visualize texture map
    # with given geometry, RGBD images, and camera poses.
    option = open3d.ColorMapOptmizationOption()
    option.maximum_iteration = 0
    open3d.color_map_optimization(mesh, rgbd_images, camera, option)
    open3d.draw_geometries([mesh])
    open3d.write_triangle_mesh(os.path.join(path, "scene",
        "color_map_before_optimization.ply"), mesh)

    # Optimize texture and save the mesh as texture_mapped.ply
    # This is implementation of following paper
    # Q.-Y. Zhou and V. Koltun,
示例#9
0
    return depth_image, intrin


data_path = '/home/spc/Desktop/DepthCodec/sample_data/*'
files = glob.glob(data_path)
assert files.__len__(), "no test data in " + data_path
for example in files:
    depth, intrin = loadSampleFromFile(example, 20)
    plt.figure()
    plt.imshow(depth)
    plt.pause(0.1)
    plt.waitforbuttonpress()

    open3d_depth = open3d.Image(depth)
    open3d_intrin = open3d.PinholeCameraIntrinsic(intrin.width, intrin.height,
                                                  intrin.fx, intrin.fy,
                                                  intrin.ppx, intrin.ppy)
    open3d_pc1 = open3d.create_point_cloud_from_depth_image(
        open3d_depth, open3d_intrin)
    open3d.draw_geometries([open3d_pc1])

    tc = DepthImageCodec()
    tc.compress(depth)
    bits = BitStream()
    bits = tc.encode(bits)
    print(depth.size * 16 / len(bits))
    uncompressed = tc.uncompress()

    open3d_uncompressed = open3d.Image(uncompressed)
    open3d_pc2 = open3d.create_point_cloud_from_depth_image(
        open3d_uncompressed, open3d_intrin,
示例#10
0
# width=depth_width; height=depth_height; ppx=258.981; ppy=208.796; fx=367.033; fy=367.033 # Hardcode the camera intrinsic parameters for backprojection

# ppx = 260.166
# ppy = 205.197
# fx = 367.535
# fy = 367.535

# camera_intrinsic=intrinsic.intrinsic_matrix
camera_intrinsic = np.asarray([[367.535, 0., 260.166], [0., 367.535, 205.197],
                               [0., 0., 1.]])
fx = camera_intrinsic[0, 0]
fy = camera_intrinsic[1, 1]
ppx = camera_intrinsic[0, 2]
ppy = camera_intrinsic[1, 2]
# Open3D visualisation
intrinsic = open3d.PinholeCameraIntrinsic(depth_width, depth_height, fx, fy,
                                          ppx, ppy).intrinsic_matrix

# To convert [x,y,z] -> [x.-y,-z]
flip_transform = [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]

joint_lines = [
    [0, 1],
    [1, 20],
    [20, 2],
    [2, 3],  # Spine
    [20, 4],
    [4, 5],
    [5, 6],
    [6, 7],
    [7, 21],
    [7, 22],  # Left arm and hand
示例#11
0
def map_texture(object_name, session_name, base_dir, models_dir,
    debug_mode=False, show_textured_mesh=False,
    depth_thresh_for_visibility=1e-2, depth_thresh_for_discontinuity=0.035,
    max_vertex_normal_angle=70, real_depth_maps=False):
  data_dir = osp.join(base_dir, session_name, object_name)
  try:
    with open(osp.join(data_dir, 'object_name.txt'), 'r') as f:
      object_name = f.readline().rstrip()
  except IOError:
    print('{:s} does not have object_name.txt, skipping'.format(data_dir))
    return

  # read mesh file
  mesh_filename = osp.join(models_dir, '{:s}.ply'.format(object_name))
  mesh = open3d.read_triangle_mesh(mesh_filename)
  if not mesh.has_vertex_normals():
    mesh.compute_vertex_normals()

  # names of views
  rgb_im_dir = osp.join(data_dir, 'thermal_images')
  pose_dir = osp.join(data_dir, 'poses')
  names = []
  for filename in os.listdir(pose_dir):
    if '.txt' not in filename:
      continue
    if 'camera_pose' not in filename:
      continue
    name = '_'.join(filename.split('.')[0].split('_')[2:])
    names.append(name)
  names = sorted(names)

  # camera extrinsics
  Ts = []
  for name in names:
    filename = osp.join(pose_dir, 'camera_pose_{:s}.txt'.format(name))
    T = np.eye(4)
    with open(filename, 'r') as f:
      f.readline()
      T[0, 3] = float(f.readline().strip())
      T[1, 3] = float(f.readline().strip())
      T[2, 3] = float(f.readline().strip())
      f.readline()
      f.readline()
      T[0, :3] = [float(v) for v in f.readline().strip().split()]
      T[1, :3] = [float(v) for v in f.readline().strip().split()]
      T[2, :3] = [float(v) for v in f.readline().strip().split()]
    Ts.append(np.linalg.inv(T))

  # RGB images
  rgb_ims = []
  im_intensities = []
  for name in names:
    rgb_im = open3d.read_image(osp.join(rgb_im_dir, '{:s}.png'.format(name)))
    rgb_im = np.asarray(rgb_im)
    rgb_ims.append(rgb_im)
    im_shape = rgb_im.shape
    intensity = rgb_im[:200, :200, 0].mean()
    im_intensities.append(intensity)
  target_intensity = np.mean(im_intensities)
  for i, rgb_im in enumerate(rgb_ims):
    rgb_im = rgb_im * target_intensity / im_intensities[i]
    rgb_im = np.clip(rgb_im, a_min=0, a_max=255)
    rgb_ims[i] = open3d.Image(rgb_im.astype(np.uint8))

  # camera intrinsic
  cinfo_filename = cinfo_manager.getPackageFileName(
    'package://contactdb_utils/calibrations/boson.yaml')
  cinfo = cinfo_manager.loadCalibrationFile(cinfo_filename, 'boson')
  h_scaling = float(im_shape[0]) / cinfo.height
  w_scaling = float(im_shape[1]) / cinfo.width
  K = np.asarray(cinfo.K)
  K[0] *= w_scaling
  K[2] *= w_scaling
  K[4] *= h_scaling
  K[5] *= h_scaling
  K = K.reshape((3,3))
  intrinsic = open3d.PinholeCameraIntrinsic(im_shape[1], im_shape[0], K[0,0],
    K[1,1], K[0,2], K[1,2])

  if real_depth_maps:  # use registered Kinect depthmaps
    depth_im_dir = osp.join(data_dir, 'depth_images')
    depth_ims = []
    for name in names:
      depth_im_filename = osp.join(depth_im_dir, '{:s}.png'.format(name))
      depth_im = open3d.read_image(depth_im_filename)
      depth_im = np.uint16(fill_holes(depth_im))
      depth_ims.append(depth_im)
  else:  # create depth maps by rendering
    depth_ims = render_depth_maps(mesh_filename, intrinsic, Ts)

  # create RGB-D images
  rgbds = []
  for depth_im, rgb_im, T in zip(depth_ims, rgb_ims, Ts):
    depth_im = open3d.Image(depth_im)
    rgbds.append(open3d.create_rgbd_image_from_color_and_depth(rgb_im,
      depth_im, convert_rgb_to_intensity=False))
    if debug_mode:
      pc = open3d.create_point_cloud_from_rgbd_image(rgbds[-1], intrinsic)
      tmesh = copy(mesh)
      tmesh.transform(T)
      geoms = [pc]
      if show_textured_mesh:
        geoms.append(tmesh)
      open3d.draw_geometries(geoms)

  # create trajectory for texture mapping
  traj = open3d.PinholeCameraTrajectory()
  traj.extrinsic = open3d.Matrix4dVector(np.asarray(Ts))
  traj.intrinsic = intrinsic

  # do texture mapping!
  option = open3d.ColorMapOptmizationOption()
  option.maximum_iteration = 300
  option.depth_threshold_for_visiblity_check = depth_thresh_for_visibility
  option.depth_threshold_for_discontinuity_check = \
      depth_thresh_for_discontinuity
  option.half_dilation_kernel_size_for_discontinuity_map = 0
  option.max_angle_vertex_normal_camera_ray = max_vertex_normal_angle
  open3d.color_map_optimization(mesh, rgbds, traj, option)

  if not debug_mode:  # write result as a PLY file
    mesh_filename = osp.join(data_dir, 'thermal_images',
      '{:s}_textured.ply'.format(object_name))
    open3d.write_triangle_mesh(mesh_filename, mesh)
    print('Written {:s}'.format(mesh_filename))
    if show_textured_mesh:
      show_object_mesh(data_dir)
示例#12
0
depth_scale = 0.001  # Default kinect depth scale where 1 unit = 0.001 m = 1 mm
# depth_scale                 = 1.0 # Default kinect depth scale where 1 unit = 0.001 m = 1 mm
clipping_distance_in_meters = 1.5  # Set the maximum distance to display the point cloud data
clipping_distance = clipping_distance_in_meters / depth_scale  # Convert dist in mm to unit
width = depth_width
height = depth_height
ppx = 260.166
ppy = 205.197
fx = 367.535
fy = 367.535  # Hardcode the camera intrinsic parameters for backprojection
# width=depth_width; height=depth_height; ppx=258.981; ppy=208.796; fx=367.033; fy=367.033 # Hardcode the camera intrinsic parameters for backprojection

############################
### Open3D visualisation ###
############################
intrinsic = open3d.PinholeCameraIntrinsic(width, height, fx, fy, ppx, ppy)
flip_transform = [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0],
                  [0, 0, 0, 1]]  # To convert [x,y,z] -> [x.-y,-z]
# Define the objects to be drawn
image_pcd = open3d.PointCloud()
bone_line_pcd = utils.create_line_set_bones(np.zeros(
    (24, 3), dtype=np.float32))  # 24 bones connecting 25 joints
axis_pcd = []
for i in range(PyKinectV2.JointType_Count):  # 25 axes for 25 joints
    axis_pcd.append(
        open3d.create_mesh_coordinate_frame(
            size=0.1, origin=[0, 0, 0]))  # XYZ axis length of 0.1 m
# Create Open3D Visualizer
vis = open3d.Visualizer()
vis.create_window(width=width, height=height)
vis.get_render_option().point_size = 3
示例#13
0
import open3d as o3d  # pip install open3d-python==0.5
import numpy as np
import math

# load point cloud
i = 4
depth_image_path = "../output/bop_data/lmo/train_pbr/000000/depth/000000.png"
depth_raw = o3d.read_image(depth_image_path)
image_width = 671
image_height = 502
fx = 1122.375
fy = 1122.375
cx = 334.4445
cy = 264.443075

intrinsic = o3d.PinholeCameraIntrinsic(image_width, image_height, fx, fy, cx,
                                       cy)
extrinsic = np.identity(4)
print(extrinsic)
depth_scale = 10
depth_trunc = 1500.0

np_depth = np.array(depth_raw)
depth_raw = o3d.geometry.Image(np_depth)
print(depth_raw)
print(type(depth_raw))
print(type(intrinsic))

color = True

pcd = o3d.create_point_cloud_from_depth_image(depth=depth_raw,
                                              intrinsic=intrinsic,
示例#14
0
def generate_object_masks(object_name,
                          session_name,
                          base_dir,
                          models_dir=default_models_dir,
                          dilate_size=default_dilation):
    logger = logging.getLogger(__name__)
    data_dir = osp.join(base_dir, session_name, object_name)
    try:
        with open(osp.join(data_dir, 'object_name.txt'), 'r') as f:
            object_name = f.readline().rstrip()
    except IOError:
        logger.warn(
            '{:s} does not have object_name.txt, skipping'.format(data_dir))
        return
    mesh_filename = osp.join(models_dir, '{:s}.ply'.format(object_name))

    # names of views
    pose_dir = osp.join(data_dir, 'poses')
    names = []
    for filename in os.listdir(pose_dir):
        if '.txt' not in filename:
            continue
        if 'camera_pose' not in filename:
            continue
        name = '_'.join(filename.split('.')[0].split('_')[2:])
        names.append(name)
    names = sorted(names)

    # camera extrinsics
    Ts = []
    for name in names:
        filename = osp.join(pose_dir, 'camera_pose_{:s}.txt'.format(name))
        T = np.eye(4)
        with open(filename, 'r') as f:
            f.readline()
            T[0, 3] = float(f.readline().strip())
            T[1, 3] = float(f.readline().strip())
            T[2, 3] = float(f.readline().strip())
            f.readline()
            f.readline()
            T[0, :3] = [float(v) for v in f.readline().strip().split()]
            T[1, :3] = [float(v) for v in f.readline().strip().split()]
            T[2, :3] = [float(v) for v in f.readline().strip().split()]
        Ts.append(np.linalg.inv(T))

    rgb_im_dir = osp.join(data_dir, 'thermal_images')
    im = cv2.imread(osp.join(rgb_im_dir, '{:s}.png'.format(names[0])))
    im_shape = im.shape

    # camera intrinsic
    cinfo_filename = cinfo_manager.getPackageFileName(
        'package://contactdb_utils/calibrations/boson.yaml')
    cinfo = cinfo_manager.loadCalibrationFile(cinfo_filename, 'boson')
    h_scaling = float(im_shape[0]) / cinfo.height
    w_scaling = float(im_shape[1]) / cinfo.width
    K = np.asarray(cinfo.K)
    K[0] *= w_scaling
    K[2] *= w_scaling
    K[4] *= h_scaling
    K[5] *= h_scaling
    K = K.reshape((3, 3))
    intrinsic = open3d.PinholeCameraIntrinsic(im_shape[1], im_shape[0],
                                              K[0, 0], K[1, 1], K[0, 2], K[1,
                                                                           2])

    # render depth maps
    depth_ims = render_depth_maps(mesh_filename, intrinsic, Ts)

    # save masks
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,
                                       (dilate_size, dilate_size))
    for name, depth_im in zip(names, depth_ims):
        mask_filename = osp.join(data_dir, 'thermal_images',
                                 '{:s}_mask.png'.format(name))
        mask = np.uint8(255 * (depth_im > 0))
        mask = cv2.dilate(mask, kernel)
        if cv2.imwrite(mask_filename, mask.astype(np.uint8)):
            logger.info('Written {:s}'.format(mask_filename))