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()
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))
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
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
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)
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,
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,
# 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
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)
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
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,
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))