@@ -248,7 +248,7 @@ def __init__(
248248 self .converter_to_image_coordinate = AffineBox ()
249249 self .affine_lps_to_ras = affine_lps_to_ras
250250
251- def __call__ (self , data : Mapping [Hashable , NdarrayOrTensor ]) -> Dict [ Hashable , NdarrayOrTensor ]:
251+ def extract_affine (self , data : Mapping [Hashable , NdarrayOrTensor ]) -> Tuple [ NdarrayOrTensor , NdarrayOrTensor ]:
252252 d = dict (data )
253253
254254 meta_key = self .image_meta_key
@@ -269,6 +269,12 @@ def __call__(self, data: Mapping[Hashable, NdarrayOrTensor]) -> Dict[Hashable, N
269269 affine_t , * _ = convert_data_type (affine , torch .Tensor )
270270 # torch.inverse should not run in half precision
271271 inv_affine_t = torch .inverse (affine_t .to (COMPUTE_DTYPE ))
272+ return affine , inv_affine_t
273+
274+ def __call__ (self , data : Mapping [Hashable , NdarrayOrTensor ]) -> Dict [Hashable , NdarrayOrTensor ]:
275+ d = dict (data )
276+
277+ affine , inv_affine_t = self .extract_affine (data )
272278
273279 for key in self .key_iterator (d ):
274280 self .push_transform (d , key , extra_info = {"affine" : affine })
@@ -285,6 +291,54 @@ def inverse(self, data: Mapping[Hashable, NdarrayOrTensor]) -> Dict[Hashable, Nd
285291 return d
286292
287293
294+ class AffineBoxToWorldCoordinated (AffineBoxToImageCoordinated ):
295+ """
296+ Dictionary-based transform that converts box in image coordinate to world coordinate.
297+
298+ Args:
299+ box_keys: Keys to pick box data for transformation. The box mode is assumed to be ``StandardMode``.
300+ box_ref_image_keys: The single key that represents the reference image to which ``box_keys`` are attached.
301+ remove_empty: whether to remove the boxes that are actually empty
302+ allow_missing_keys: don't raise exception if key is missing.
303+ image_meta_key: explicitly indicate the key of the corresponding metadata dictionary.
304+ for example, for data with key `image`, the metadata by default is in `image_meta_dict`.
305+ the metadata is a dictionary object which contains: filename, affine, original_shape, etc.
306+ it is a string, map to the `box_ref_image_key`.
307+ if None, will try to construct meta_keys by `box_ref_image_key_{meta_key_postfix}`.
308+ image_meta_key_postfix: if image_meta_keys=None, use `box_ref_image_key_{postfix}` to fetch the metadata according
309+ to the key data, default is `meta_dict`, the metadata is a dictionary object.
310+ For example, to handle key `image`, read/write affine matrices from the
311+ metadata `image_meta_dict` dictionary's `affine` field.
312+ affine_lps_to_ras: default ``False``. Yet if 1) the image is read by ITKReader,
313+ and 2) the ITKReader has affine_lps_to_ras=True, and 3) the box is in world coordinate,
314+ then set ``affine_lps_to_ras=True``.
315+ """
316+
317+ def __init__ (
318+ self ,
319+ box_keys : KeysCollection ,
320+ box_ref_image_keys : str ,
321+ allow_missing_keys : bool = False ,
322+ image_meta_key : Union [str , None ] = None ,
323+ image_meta_key_postfix : Union [str , None ] = DEFAULT_POST_FIX ,
324+ affine_lps_to_ras = False ,
325+ ) -> None :
326+ super ().__init__ (
327+ box_keys , box_ref_image_keys , allow_missing_keys , image_meta_key , image_meta_key_postfix , affine_lps_to_ras
328+ )
329+ self .converter_to_world_coordinate = AffineBox ()
330+
331+ def __call__ (self , data : Mapping [Hashable , NdarrayOrTensor ]) -> Dict [Hashable , NdarrayOrTensor ]:
332+ d = dict (data )
333+
334+ affine , inv_affine_t = self .extract_affine (data )
335+
336+ for key in self .key_iterator (d ):
337+ self .push_transform (d , key , extra_info = {"affine" : inv_affine_t })
338+ d [key ] = self .converter_to_world_coordinate (d [key ], affine = affine )
339+ return d
340+
341+
288342class ZoomBoxd (MapTransform , InvertibleTransform ):
289343 """
290344 Dictionary-based transform that zooms input boxes and images with the given zoom scale.
0 commit comments