@@ -57,55 +57,62 @@ def shuffle_channels(channels, first_channel, order, num_channels=None):
5757 if num_channels is not None :
5858 del channels [first + num_channels :first + len (new_channels )]
5959
60- # Checks whether the image with specified features exists
61- def image_exists (name , features ):
62- suffixes = features .copy ()
63- if 'sh1' in suffixes :
64- suffixes .remove ('sh1' )
65- suffixes += ['sh1x' , 'sh1y' , 'sh1z' ]
66- return all ([os .path .isfile (name + '.' + s + '.exr' ) for s in suffixes ])
60+ # Checks whether the specified image feature files exist (name is a format string, e.g. 'image%s.01')
61+ def image_features_exist (name , features ):
62+ name = (name % '.%s' ) + '.exr'
63+ feature_exts = features .copy ()
64+ if 'sh1' in feature_exts :
65+ feature_exts .remove ('sh1' )
66+ feature_exts += ['sh1x' , 'sh1y' , 'sh1z' ]
67+ return all ([os .path .isfile (name % feature_ext ) for feature_ext in feature_exts ])
6768
6869# Returns the feature an image represents given its filename
6970def get_image_feature (filename ):
70- filename_split = filename .rsplit ('.' , 2 )
71- if len (filename_split ) < 2 :
72- return 'srgb' # no extension, assume sRGB
71+ filename_split = filename .rsplit ('.' , 3 )
72+ if len (filename_split ) == 1 :
73+ return 'srgb' # no format extension, assume sRGB
7374 else :
74- ext = filename_split [- 1 ].lower ()
75- if ext in {'exr' , 'pfm' , 'phm' , 'hdr' }:
76- if len (filename_split ) == 3 :
75+ format_ext = filename_split [- 1 ].lower ()
76+ if format_ext in {'exr' , 'pfm' , 'phm' , 'hdr' }:
77+ # Identify the feature extension, ignore the optional frame number
78+ if len (filename_split ) >= 3 and not filename_split [- 2 ].isdecimal ():
7779 feature = filename_split [- 2 ]
78- if feature in {'sh1x' , 'sh1y' , 'sh1z' }:
79- feature = 'sh1'
80- return feature
80+ elif len (filename_split ) >= 4 and not filename_split [- 3 ].isdecimal ():
81+ feature = filename_split [- 3 ]
8182 else :
82- return 'hdr' # assume HDR
83+ return 'hdr' # no feature extension, assume HDR
84+
85+ if feature in {'sh1x' , 'sh1y' , 'sh1z' }:
86+ feature = 'sh1'
87+ return feature
8388 else :
8489 return 'srgb' # assume sRGB
8590
86- # Loads image features in EXR format with given filename prefix, and returns the concatenated image
87- # and the number of channels loaded for each feature
91+ # Loads image features in EXR format, where name is a format string returned by
92+ # get_image_sample_groups() (e.g. 'image%s.01'), and returns the concatenated image and the number
93+ # of channels loaded per feature
8894def load_image_features (name , features ):
95+ name = (name % '.%s' ) + '.exr'
8996 images = []
9097 num_channels = {}
9198
9299 # HDR color
93100 if 'hdr' in features :
94- hdr , num_channels ['hdr' ] = load_image (name + '. hdr.exr ' , num_channels = 3 )
101+ hdr , num_channels ['hdr' ] = load_image (name % ' hdr' , num_channels = 3 )
95102 hdr = np .maximum (hdr , 0. )
96103 images .append (hdr )
97104
98105 # LDR color
99106 if 'ldr' in features :
100- ldr , num_channels ['ldr' ] = load_image (name + '. ldr.exr ' , num_channels = 3 )
107+ ldr , num_channels ['ldr' ] = load_image (name % ' ldr' , num_channels = 3 )
101108 ldr = np .clip (ldr , 0. , 1. )
102109 images .append (ldr )
103110
104111 # SH L1 color coefficients
105112 if 'sh1' in features :
106- sh1x , num_channels ['sh1x' ] = load_image (name + '. sh1x.exr ' , num_channels = 3 )
107- sh1y , num_channels ['sh1y' ] = load_image (name + '. sh1y.exr ' , num_channels = 3 )
108- sh1z , num_channels ['sh1z' ] = load_image (name + '. sh1z.exr ' , num_channels = 3 )
113+ sh1x , num_channels ['sh1x' ] = load_image (name % ' sh1x' , num_channels = 3 )
114+ sh1y , num_channels ['sh1y' ] = load_image (name % ' sh1y' , num_channels = 3 )
115+ sh1z , num_channels ['sh1z' ] = load_image (name % ' sh1z' , num_channels = 3 )
109116
110117 for sh1 in [sh1x , sh1y , sh1z ]:
111118 # Clip to [-1..1] range (coefficients are assumed to be normalized)
@@ -118,13 +125,13 @@ def load_image_features(name, features):
118125
119126 # Albedo
120127 if 'alb' in features :
121- albedo , num_channels ['alb' ] = load_image (name + '. alb.exr ' , num_channels = 3 )
128+ albedo , num_channels ['alb' ] = load_image (name % ' alb' , num_channels = 3 )
122129 albedo = np .clip (albedo , 0. , 1. )
123130 images .append (albedo )
124131
125132 # Normal
126133 if 'nrm' in features :
127- normal , num_channels ['nrm' ] = load_image (name + '. nrm.exr ' , num_channels = 3 )
134+ normal , num_channels ['nrm' ] = load_image (name % ' nrm' , num_channels = 3 )
128135 normal = np .clip (normal , - 1. , 1. )
129136
130137 # Transform to [0..1] range
@@ -134,7 +141,7 @@ def load_image_features(name, features):
134141
135142 # Depth
136143 if 'z' in features :
137- depth , num_channels ['z' ] = load_image (name + '.z.exr ' , num_channels = 1 )
144+ depth , num_channels ['z' ] = load_image (name % 'z ' , num_channels = 1 )
138145 depth = np .maximum (depth , 0. )
139146
140147 # If this is an auxiliary feature, transform to [0..1] range
@@ -149,19 +156,16 @@ def load_image_features(name, features):
149156 # Concatenate all feature images into one image
150157 return np .concatenate (images , axis = 2 ), num_channels
151158
152- # Tries to load metadata for an image with given filename/prefix, returns None if it fails
159+ # Loads image metadata in JSON format if it exists, where name is optionally a format string
160+ # returned by get_image_sample_groups() (e.g. 'image%s.01'),
153161def load_image_metadata (name ):
154- dirname , basename = os .path .split (name )
155- basename = basename .split ('.' )[0 ] # remove all extensions
156- while basename :
157- metadata_filename = os .path .join (dirname , basename ) + '.json'
158- if os .path .isfile (metadata_filename ):
159- return load_json (metadata_filename )
160- if '_' in basename :
161- basename = basename .rsplit ('_' , 1 )[0 ]
162- else :
163- break
164- return None
162+ if '%s' in name :
163+ name = name % ''
164+ name += '.json'
165+ if os .path .isfile (name ):
166+ return load_json (name )
167+ else :
168+ return {}
165169
166170# Saves image metadata to a file with given prefix
167171def save_image_metadata (name , metadata ):
@@ -180,19 +184,42 @@ def get_image_sample_groups(dir, input_features, target_features=None):
180184
181185 # Make image groups
182186 image_groups = defaultdict (set )
187+
183188 for filename in image_filenames :
184- image_name = os .path .relpath (filename , dir ) # remove dir path
185- image_name , _ , _ = image_name .rsplit ('.' , 2 ) # remove extensions
186- group = image_name
187- if '_' in image_name :
188- prefix , suffix = image_name .rsplit ('_' , 1 )
189- suffix = suffix .lower ()
189+ # Process the image filename
190+ filename = os .path .relpath (filename , dir ) # remove directory path
191+ filename = filename .replace ('%' , '%%' ) # escape for string formatting
192+ filename_split = filename .rsplit ('.' , 3 )
193+ group_name = filename_split [0 ]
194+
195+ # Identify the feature extension and the optional frame number
196+ feature_ext_idx = None
197+ frame_str = None
198+ for i in range (1 , len (filename_split )- 1 ):
199+ if filename_split [i ].isdecimal ():
200+ frame_str = filename_split [i ]
201+ else :
202+ feature_ext_idx = i
203+ if feature_ext_idx is None :
204+ continue # skip image with missing feature extension
205+
206+ # The image name is a format string which can be passed to load_image_features()
207+ # Replace the feature extension with a placeholder and remove the format extension ('exr')
208+ image_name = filename_split [0 ]
209+ for i in range (1 , len (filename_split )- 1 ):
210+ image_name += '%s' if i == feature_ext_idx else ('.' + filename_split [i ])
211+
212+ # Identify the samples per pixel
213+ if '_' in group_name :
214+ prefix , suffix = group_name .rsplit ('_' , 1 )
190215 if (suffix .isdecimal () or
191- (suffix .endswith ('spp' ) and suffix [:- 3 ].isdecimal ()) or
192- suffix == 'ref' or suffix == 'reference' or
193- suffix == 'gt' or suffix == 'target' ):
194- group = prefix
195- image_groups [group ].add (image_name )
216+ (suffix .lower ().endswith ('spp' ) and suffix [:- 3 ].isdecimal ()) or
217+ suffix .lower () in {'ref' , 'reference' , 'gt' , 'target' }):
218+ group_name = prefix
219+
220+ if frame_str is not None :
221+ group_name += '.' + frame_str
222+ image_groups [group_name ].add (image_name )
196223
197224 # Make sorted image sample (inputs + target) groups
198225 image_sample_groups = []
@@ -205,8 +232,8 @@ def get_image_sample_groups(dir, input_features, target_features=None):
205232 input_names , target_name = image_names , None
206233
207234 # Check whether all required features exist
208- if all ([image_exists (os .path .join (dir , input_name ), input_features ) for input_name in input_names ]):
209- if target_name and not image_exists (os .path .join (dir , target_name ), target_features ):
235+ if all ([image_features_exist (os .path .join (dir , input_name ), input_features ) for input_name in input_names ]):
236+ if target_name and not image_features_exist (os .path .join (dir , target_name ), target_features ):
210237 target_name = None # discard target due to missing features
211238
212239 # Add sample
0 commit comments