Skip to content

Commit 5dfe62e

Browse files
committed
Add .obj output format support to sai-cli process
Similar to PLY and PCD. Causes the output to be a single file, an (untexturized) OBJ mesh.
1 parent bb05ee4 commit 5dfe62e

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

python/cli/process/process.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,13 @@ def process(args):
295295
import numpy as np
296296
import pandas as pd
297297

298+
PC_AND_MESH_FORMATS = ['ply', 'pcd', 'obj']
299+
298300
# Overwrite format if output is set to pointcloud
299-
if args.output.endswith(".ply"):
300-
args.format = "ply"
301-
elif args.output.endswith(".pcd"):
302-
args.format = "pcd"
301+
for fmt in PC_AND_MESH_FORMATS:
302+
if args.output.endswith('.' + fmt):
303+
args.format = fmt
304+
break
303305

304306
useMono = None
305307

@@ -362,7 +364,9 @@ def processMappingOutput(output):
362364
if visualizer is not None:
363365
visualizer.onMappingOutput(output)
364366

365-
if args.format in ['ply', 'pcd']:
367+
saveImages = True
368+
if args.format in PC_AND_MESH_FORMATS:
369+
saveImages = False
366370
if output.finalMap: finalMapWritten = True
367371
return
368372

@@ -396,8 +400,9 @@ def processMappingOutput(output):
396400
img = undistortedFrame.image.toArray()
397401

398402
bgrImage = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
399-
fileName = f"{tmp_dir}/frame_{frameId:05}.{args.image_format}"
400-
cv2.imwrite(fileName, bgrImage)
403+
if saveImages:
404+
fileName = f"{tmp_dir}/frame_{frameId:05}.{args.image_format}"
405+
cv2.imwrite(fileName, bgrImage)
401406

402407
# Find colors for sparse features
403408
SHOW_FEATURE_MARKERS = True
@@ -440,8 +445,9 @@ def processMappingOutput(output):
440445
if frameSet.depthFrame is not None and frameSet.depthFrame.image is not None and not useMono:
441446
alignedDepth = frameSet.getAlignedDepthFrame(undistortedFrame)
442447
depthData = alignedDepth.image.toArray()
443-
depthFrameName = f"{tmp_dir}/depth_{frameId:05}.png"
444-
cv2.imwrite(depthFrameName, depthData)
448+
if saveImages:
449+
depthFrameName = f"{tmp_dir}/depth_{frameId:05}.png"
450+
cv2.imwrite(depthFrameName, depthData)
445451

446452
DEPTH_PREVIEW = False
447453
if args.preview and DEPTH_PREVIEW:
@@ -650,14 +656,20 @@ def parse_input_dir(input_dir):
650656
"icpVoxelSize": min(args.key_frame_distance, 0.1)
651657
}
652658

659+
parameter_sets = ['wrapper-base']
660+
661+
tmp_dir = None
653662
if args.format in ['ply', 'pcd']:
654663
config["mapSavePath"] = args.output
664+
elif args.format == 'obj':
665+
assert not args.mono
666+
config['recMeshSavePath'] = args.output
667+
parameter_sets.append('meshing')
655668
else:
656669
# Clear output dir
657670
shutil.rmtree(f"{args.output}/images", ignore_errors=True)
658671
os.makedirs(f"{args.output}/images", exist_ok=True)
659-
660-
tmp_dir = tempfile.mkdtemp()
672+
tmp_dir = tempfile.mkdtemp()
661673

662674
device_preset, cameras = parse_input_dir(args.input)
663675

@@ -673,7 +685,6 @@ def parse_input_dir(input_dir):
673685
if useMono: config['useStereo'] = False
674686

675687
prefer_icp = not args.no_icp and not useMono
676-
parameter_sets = ['wrapper-base']
677688

678689
if not args.fast:
679690
parameter_sets.append('offline-base')
@@ -741,10 +752,11 @@ def parse_input_dir(input_dir):
741752

742753
replay = None
743754

744-
try:
745-
shutil.rmtree(tmp_dir)
746-
except:
747-
print(f"Failed to clean temporary directory, you can delete these files manually, they are no longer required: {tmp_dir}", flush=True)
755+
if tmp_dir is not None:
756+
try:
757+
shutil.rmtree(tmp_dir)
758+
except:
759+
print(f"Failed to clean temporary directory, you can delete these files manually, they are no longer required: {tmp_dir}", flush=True)
748760

749761
if not finalMapWritten:
750762
print('Mapping failed: no output generated')

0 commit comments

Comments
 (0)