@@ -35,6 +35,92 @@ def define_subparser(subparsers):
35
35
sub .set_defaults (func = process )
36
36
return define_args (sub )
37
37
38
+ def parse_input_dir (input_dir ):
39
+ cameras = None
40
+ calibrationJson = f"{ input_dir } /calibration.json"
41
+ if os .path .exists (calibrationJson ):
42
+ with open (calibrationJson ) as f :
43
+ calibration = json .load (f )
44
+ if "cameras" in calibration :
45
+ cameras = calibration ["cameras" ]
46
+ device = None
47
+ metadataJson = f"{ input_dir } /metadata.json"
48
+ if os .path .exists (metadataJson ):
49
+ with open (metadataJson ) as f :
50
+ metadata = json .load (f )
51
+ if metadata .get ("platform" ) == "ios" :
52
+ device = "ios-tof"
53
+ if device == None :
54
+ vioConfigYaml = f"{ input_dir } /vio_config.yaml"
55
+ if os .path .exists (vioConfigYaml ):
56
+ with open (vioConfigYaml ) as file :
57
+ supported = ['oak-d' , 'k4a' , 'realsense' , 'orbbec-astra2' , 'orbbec-femto' , 'android' , 'android-tof' ]
58
+ for line in file :
59
+ if "parameterSets" in line :
60
+ for d in supported :
61
+ if d in line :
62
+ device = d
63
+ break
64
+ if device : break
65
+ return (device , cameras )
66
+
67
+ def auto_config (device_preset ,
68
+ key_frame_distance = 0.1 ,
69
+ mono = False ,
70
+ icp = True ,
71
+ fast = False ,
72
+ already_rectified = False ,
73
+ internal = []):
74
+
75
+ config = {
76
+ "maxMapSize" : 0 ,
77
+ "useSlam" : True ,
78
+ "passthroughColorImages" : True ,
79
+ "keyframeDecisionDistanceThreshold" : key_frame_distance ,
80
+ "icpVoxelSize" : min (key_frame_distance , 0.1 )
81
+ }
82
+ parameter_sets = ['wrapper-base' ]
83
+
84
+ if mono : config ['useStereo' ] = False
85
+
86
+ prefer_icp = icp and not mono
87
+
88
+ if not fast :
89
+ parameter_sets .append ('offline-base' )
90
+ # remove these to further trade off speed for quality
91
+ mid_q = {
92
+ 'maxKeypoints' : 1000 ,
93
+ 'optimizerMaxIterations' : 30
94
+ }
95
+ for k , v in mid_q .items (): config [k ] = v
96
+
97
+ if internal is not None :
98
+ for param in internal :
99
+ k , _ , v = param .partition (':' )
100
+ config [k ] = v
101
+
102
+ if device_preset :
103
+ parameter_sets .append (device_preset )
104
+
105
+ if device_preset == 'k4a' :
106
+ if prefer_icp :
107
+ parameter_sets .extend (['icp' ])
108
+ if not fast : parameter_sets .append ('offline-icp' )
109
+ elif device_preset == 'realsense' :
110
+ if prefer_icp :
111
+ parameter_sets .extend (['icp' , 'realsense-icp' ])
112
+ if not fast : parameter_sets .append ('offline-icp' )
113
+ elif device_preset == 'oak-d' :
114
+ config ['stereoPointCloudMinDepth' ] = 0.5
115
+ config ['alreadyRectified' ] = already_rectified
116
+ elif device_preset is not None and "orbbec" in device_preset :
117
+ if prefer_icp :
118
+ parameter_sets .extend (['icp' ])
119
+ if not fast : parameter_sets .append ('offline-icp' )
120
+
121
+ config ['parameterSets' ] = parameter_sets
122
+ return config
123
+
38
124
def interpolate_missing_properties (df_source , df_query , k_nearest = 3 ):
39
125
import pandas as pd
40
126
from scipy .spatial import KDTree
@@ -621,6 +707,7 @@ def on_mapping_output(output):
621
707
raise
622
708
623
709
def is_already_rectified (input_dir ):
710
+ # hack for OAK-D
624
711
vioConfigYaml = f"{ input_dir } /vio_config.yaml"
625
712
if os .path .exists (vioConfigYaml ):
626
713
with open (vioConfigYaml ) as file :
@@ -630,122 +717,53 @@ def is_already_rectified(input_dir):
630
717
return value .lower ().strip () == "true"
631
718
return False
632
719
633
- def parse_input_dir (input_dir ):
634
- cameras = None
635
- calibrationJson = f"{ input_dir } /calibration.json"
636
- if os .path .exists (calibrationJson ):
637
- with open (calibrationJson ) as f :
638
- calibration = json .load (f )
639
- if "cameras" in calibration :
640
- cameras = calibration ["cameras" ]
641
- device = None
642
- metadataJson = f"{ input_dir } /metadata.json"
643
- if os .path .exists (metadataJson ):
644
- with open (metadataJson ) as f :
645
- metadata = json .load (f )
646
- if metadata .get ("platform" ) == "ios" :
647
- device = "ios-tof"
648
- if device == None :
649
- vioConfigYaml = f"{ input_dir } /vio_config.yaml"
650
- if os .path .exists (vioConfigYaml ):
651
- with open (vioConfigYaml ) as file :
652
- supported = ['oak-d' , 'k4a' , 'realsense' , 'orbbec-astra2' , 'orbbec-femto' , 'android' , 'android-tof' ]
653
- for line in file :
654
- if "parameterSets" in line :
655
- for d in supported :
656
- if d in line :
657
- device = d
658
- break
659
- if device : break
660
- return (device , cameras )
720
+ device_preset , cameras = parse_input_dir (args .input )
661
721
662
- config = {
663
- "maxMapSize" : 0 ,
664
- "useSlam" : True ,
665
- "passthroughColorImages" : True ,
666
- "keyframeDecisionDistanceThreshold" : args .key_frame_distance ,
667
- "icpVoxelSize" : min (args .key_frame_distance , 0.1 )
668
- }
722
+ if args .device_preset :
723
+ device_preset = args .device_preset
669
724
670
- parameter_sets = ['wrapper-base' ]
725
+ if device_preset : print (f"Selected device type: { device_preset } " , flush = True )
726
+ else : print ("Warning! Couldn't automatically detect device preset, to ensure best results suply one via --device_preset argument" , flush = True )
727
+
728
+ useMono = args .mono or (cameras != None and len (cameras ) == 1 )
729
+
730
+ config = auto_config (device_preset ,
731
+ key_frame_distance = args .key_frame_distance ,
732
+ mono = useMono ,
733
+ icp = not args .no_icp ,
734
+ fast = args .fast ,
735
+ internal = args .internal ,
736
+ already_rectified = is_already_rectified (args .input )) # rectification required for stereo point cloud
671
737
672
738
tmp_dir = None
673
739
if args .format in ['ply' , 'pcd' ]:
674
740
config ["mapSavePath" ] = args .output
675
- parameter_sets .append ('point-cloud' )
741
+ config [ 'parameterSets' ] .append ('point-cloud' )
676
742
elif args .format == 'obj' :
677
743
assert not args .mono
678
744
config ['recMeshSavePath' ] = args .output
679
745
config ['recTexturize' ] = args .texturize
680
- parameter_sets .append ('meshing' )
746
+ config [ 'parameterSets' ] .append ('meshing' )
681
747
else :
682
748
# Clear output dir
683
749
shutil .rmtree (f"{ args .output } /images" , ignore_errors = True )
684
750
os .makedirs (f"{ args .output } /images" , exist_ok = True )
685
751
tmp_dir = tempfile .mkdtemp ()
686
752
687
- device_preset , cameras = parse_input_dir (args .input )
688
-
689
753
if cameras is not None :
690
754
cam = cameras [0 ]
691
755
exposureTime = cam .get ('exposureTimeSeconds' , 0 )
692
756
rollingShutterTime = cam .get ('shutterRollTimeSeconds' , 0 )
693
757
if args .no_undistort :
694
758
cameraDistortion = convert_distortion (cam )
695
759
696
- useMono = args .mono or (cameras != None and len (cameras ) == 1 )
697
-
698
- if useMono : config ['useStereo' ] = False
699
-
700
- prefer_icp = not args .no_icp and not useMono
701
-
702
- if not args .fast :
703
- parameter_sets .append ('offline-base' )
704
- # remove these to further trade off speed for quality
705
- mid_q = {
706
- 'maxKeypoints' : 1000 ,
707
- 'optimizerMaxIterations' : 30
708
- }
709
- for k , v in mid_q .items (): config [k ] = v
710
-
711
- if args .device_preset :
712
- device_preset = args .device_preset
713
-
714
- if args .internal is not None :
715
- for param in args .internal :
716
- k , _ , v = param .partition (':' )
717
- config [k ] = v
718
-
719
- if device_preset : print (f"Selected device type: { device_preset } " , flush = True )
720
- else : print ("Warning! Couldn't automatically detect device preset, to ensure best results suply one via --device_preset argument" , flush = True )
721
-
722
- if device_preset :
723
- parameter_sets .append (device_preset )
724
-
725
- if device_preset == 'k4a' :
726
- if prefer_icp :
727
- parameter_sets .extend (['icp' ])
728
- if not args .fast : parameter_sets .append ('offline-icp' )
729
- elif device_preset == 'realsense' :
730
- if prefer_icp :
731
- parameter_sets .extend (['icp' , 'realsense-icp' ])
732
- if not args .fast : parameter_sets .append ('offline-icp' )
733
- elif device_preset == 'oak-d' :
734
- config ['stereoPointCloudMinDepth' ] = 0.5
735
- config ['alreadyRectified' ] = is_already_rectified (args .input ) # rectification required for stereo point cloud
736
- elif device_preset is not None and "orbbec" in device_preset :
737
- if prefer_icp :
738
- parameter_sets .extend (['icp' ])
739
- if not args .fast : parameter_sets .append ('offline-icp' )
740
-
741
760
if args .preview3d :
742
761
from spectacularAI .cli .visualization .visualizer import Visualizer , VisualizerArgs
743
762
visArgs = VisualizerArgs ()
744
763
visArgs .targetFps = 30
745
764
visArgs .showCameraModel = False
746
765
visualizer = Visualizer (visArgs )
747
766
748
- config ['parameterSets' ] = parameter_sets
749
767
print (config )
750
768
751
769
replay = spectacularAI .Replay (args .input , mapperCallback = on_mapping_output , configuration = config , ignoreFolderConfiguration = True )
0 commit comments