admin管理员组文章数量:1291065
I have a moved image that I created with simpleITK transforms and registration and I have object's measurements and centroids from the moved image(working as expected)
my transformation/registration:
final_transform1, registration_method1 = img_reg(roi11, mask11, roi21, mask21)
I then resample the images to produce the moved images:
moved_roi21 = sitk.Resample(roi21, roi11, final_transform1, sitk.sitkLinear, 0.0, roi21.GetPixelID())
moved_mask21 = sitk.Resample(mask21, roi11, final_transform1, sitk.sitkNearestNeighbor, 0.0, mask21.GetPixelID())
I do some measuring and get the centroids of those objects:
But then, I'm attempting to take those centroids from the moved image to map the location back to the original image.I need to pinpoint the centroid on the original image. Some of the centroids shift a bit due to the transformation. I tried the GetInverse() Function
Below: the column "Post centroid" is the location of the centroid from the moved image
inverse_transform1 = final_transform1.GetInverse()
stones1["Original Post Centroid"] = stones1["Post centroid"].apply(
lambda centroid: remap_centroid_with_inverse_transform(centroid, inverse_transform1)
)
def remap_centroid_with_inverse_transform(centroid, inverse_transform):
"""
Maps a centroid from the moved space back to the original space using the inverse transform.
Args:
centroid (tuple): The centroid in the moved image space (x, y, z).
inverse_transform (sitk.Transform): The inverse transform from registration.
Returns:
tuple: The remapped centroid in the original image space (x', y', z').
"""
try:
# Ensure the centroid is a tuple
if isinstance(centroid, (list, tuple)) and len(centroid) == 1:
centroid = centroid[0]
# Transform the centroid back to the original space
remapped_centroid = inverse_transform.TransformPoint(centroid)
print(f"Centroid {centroid} remapped to {remapped_centroid} using inverse transform.")
return remapped_centroid
except Exception as e:
print(f"Error remapping centroid {centroid} with inverse transform: {e}")
return None
My hope was this would map the centroid from the moved image(or any centoid in the moved image) to the centroid of the original image before the transform, but the remapping way off.
In case you're wondering what the img_reg function is doing:
def img_reg(fixed_image, fixed_image_mask, moving_image, moving_image_mask):
registration_method = sitk.ImageRegistrationMethod()
# Similarity metric settings.
# cross correlation
registration_method.SetMetricAsANTSNeighborhoodCorrelation(3)
registration_method.SetMetricSamplingStrategy(registration_method.RANDOM)
registration_method.SetMetricSamplingPercentage(0.95)
registration_method.SetMetricFixedMask(fixed_image_mask)
registration_method.SetInterpolator(sitk.sitkLinear)
# Optimizer settings.
registration_method.SetOptimizerAsGradientDescent(learningRate=1.0, numberOfIterations=300, convergenceMinimumValue=1e-6, convergenceWindowSize=10)
registration_method.SetOptimizerScalesFromPhysicalShift()
# Setup for the multi-resolution framework.
registration_method.SetShrinkFactorsPerLevel(shrinkFactors = [3, 2, 1])
registration_method.SetSmoothingSigmasPerLevel(smoothingSigmas= [2, 1, 1])
registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()
# Set the initial moving and optimized transforms.
#rigid
fix_mask = sitk.Cast(fixed_image > 1.0e-6, sitk.sitkFloat32) * sitk.Cast(fixed_image_mask > 0, sitk.sitkFloat32)
mov_mask = sitk.Cast(moving_image > 1.0e-6, sitk.sitkFloat32) * sitk.Cast(moving_image_mask > 0, sitk.sitkFloat32)
fix = sitk.Cast(fixed_image, sitk.sitkFloat32) * fix_mask
mov = sitk.Cast(moving_image, sitk.sitkFloat32) * mov_mask
#sitk.WriteImage(fix, 'tfix.nii.gz')
#sitk.WriteImage(mov, 'tmov.nii.gz')
initial_transform = sitk.CenteredTransformInitializer(fix_mask,
mov_mask,
sitk.Euler3DTransform(),
sitk.CenteredTransformInitializerFilter.MOMENTS) #GEOMETRY)
registration_method.SetOptimizerScales([0.2,0.2,0.2,0.5,0,5,0.5])
registration_method.SetInitialTransform(initial_transform, inPlace=True)
final_transform = registration_method.Execute(fix, mov)
# Always check the reason optimization terminated.
print('Final metric value: {0}'.format(registration_method.GetMetricValue()))
print('Optimizer\'s stopping condition, {0}'.format(registration_method.GetOptimizerStopConditionDescription()))
return final_transform, registration_method
Although the code runs:
The output of my debugging print statement
Centroid (-45.859375, 177.4645565257353, -218.10075018504835) remapped to (-37.074328555487725, 176.6125729911438, -323.46181403960696) using inverse transform. However the actual Centroid is or the original centroid is:
(-40.66764664446721, 165.81388511782788, -113.14662579231575)
(-45.859375, 177.4645565257353, -218.10075018504835) is the correct centroid of measurement from the moved image that was transformed from (-40.66764664446721, 165.81388511782788, -113.14662579231575), but was transformed because it was a follow up image.
I have a moved image that I created with simpleITK transforms and registration and I have object's measurements and centroids from the moved image(working as expected)
my transformation/registration:
final_transform1, registration_method1 = img_reg(roi11, mask11, roi21, mask21)
I then resample the images to produce the moved images:
moved_roi21 = sitk.Resample(roi21, roi11, final_transform1, sitk.sitkLinear, 0.0, roi21.GetPixelID())
moved_mask21 = sitk.Resample(mask21, roi11, final_transform1, sitk.sitkNearestNeighbor, 0.0, mask21.GetPixelID())
I do some measuring and get the centroids of those objects:
But then, I'm attempting to take those centroids from the moved image to map the location back to the original image.I need to pinpoint the centroid on the original image. Some of the centroids shift a bit due to the transformation. I tried the GetInverse() Function
Below: the column "Post centroid" is the location of the centroid from the moved image
inverse_transform1 = final_transform1.GetInverse()
stones1["Original Post Centroid"] = stones1["Post centroid"].apply(
lambda centroid: remap_centroid_with_inverse_transform(centroid, inverse_transform1)
)
def remap_centroid_with_inverse_transform(centroid, inverse_transform):
"""
Maps a centroid from the moved space back to the original space using the inverse transform.
Args:
centroid (tuple): The centroid in the moved image space (x, y, z).
inverse_transform (sitk.Transform): The inverse transform from registration.
Returns:
tuple: The remapped centroid in the original image space (x', y', z').
"""
try:
# Ensure the centroid is a tuple
if isinstance(centroid, (list, tuple)) and len(centroid) == 1:
centroid = centroid[0]
# Transform the centroid back to the original space
remapped_centroid = inverse_transform.TransformPoint(centroid)
print(f"Centroid {centroid} remapped to {remapped_centroid} using inverse transform.")
return remapped_centroid
except Exception as e:
print(f"Error remapping centroid {centroid} with inverse transform: {e}")
return None
My hope was this would map the centroid from the moved image(or any centoid in the moved image) to the centroid of the original image before the transform, but the remapping way off.
In case you're wondering what the img_reg function is doing:
def img_reg(fixed_image, fixed_image_mask, moving_image, moving_image_mask):
registration_method = sitk.ImageRegistrationMethod()
# Similarity metric settings.
# cross correlation
registration_method.SetMetricAsANTSNeighborhoodCorrelation(3)
registration_method.SetMetricSamplingStrategy(registration_method.RANDOM)
registration_method.SetMetricSamplingPercentage(0.95)
registration_method.SetMetricFixedMask(fixed_image_mask)
registration_method.SetInterpolator(sitk.sitkLinear)
# Optimizer settings.
registration_method.SetOptimizerAsGradientDescent(learningRate=1.0, numberOfIterations=300, convergenceMinimumValue=1e-6, convergenceWindowSize=10)
registration_method.SetOptimizerScalesFromPhysicalShift()
# Setup for the multi-resolution framework.
registration_method.SetShrinkFactorsPerLevel(shrinkFactors = [3, 2, 1])
registration_method.SetSmoothingSigmasPerLevel(smoothingSigmas= [2, 1, 1])
registration_method.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()
# Set the initial moving and optimized transforms.
#rigid
fix_mask = sitk.Cast(fixed_image > 1.0e-6, sitk.sitkFloat32) * sitk.Cast(fixed_image_mask > 0, sitk.sitkFloat32)
mov_mask = sitk.Cast(moving_image > 1.0e-6, sitk.sitkFloat32) * sitk.Cast(moving_image_mask > 0, sitk.sitkFloat32)
fix = sitk.Cast(fixed_image, sitk.sitkFloat32) * fix_mask
mov = sitk.Cast(moving_image, sitk.sitkFloat32) * mov_mask
#sitk.WriteImage(fix, 'tfix.nii.gz')
#sitk.WriteImage(mov, 'tmov.nii.gz')
initial_transform = sitk.CenteredTransformInitializer(fix_mask,
mov_mask,
sitk.Euler3DTransform(),
sitk.CenteredTransformInitializerFilter.MOMENTS) #GEOMETRY)
registration_method.SetOptimizerScales([0.2,0.2,0.2,0.5,0,5,0.5])
registration_method.SetInitialTransform(initial_transform, inPlace=True)
final_transform = registration_method.Execute(fix, mov)
# Always check the reason optimization terminated.
print('Final metric value: {0}'.format(registration_method.GetMetricValue()))
print('Optimizer\'s stopping condition, {0}'.format(registration_method.GetOptimizerStopConditionDescription()))
return final_transform, registration_method
Although the code runs:
The output of my debugging print statement
Centroid (-45.859375, 177.4645565257353, -218.10075018504835) remapped to (-37.074328555487725, 176.6125729911438, -323.46181403960696) using inverse transform. However the actual Centroid is or the original centroid is:
(-40.66764664446721, 165.81388511782788, -113.14662579231575)
(-45.859375, 177.4645565257353, -218.10075018504835) is the correct centroid of measurement from the moved image that was transformed from (-40.66764664446721, 165.81388511782788, -113.14662579231575), but was transformed because it was a follow up image.
Share Improve this question asked Feb 13 at 15:04 Joseph LoganJoseph Logan 11 silver badge1 bronze badge1 Answer
Reset to default 1If I followed your code correctly we have the following:
- Registering
roi11
androi21
whereroi11
is the fixed image androi21
is the moving image. - The result from registration is
final_transform1
, maps points from theroi11
physical space toroi21
physical space.roi21
andmask21
are resampled onto theroi11
grid using this transformation, yieldingmoved_roi21
andmoved_mask21
. - Points are somehow identified on
moved_mask21
ormoved_roi21
(make sure these points are in physical space, not image index based, see TransformContinuousIndexToPhysicalPoint). - To map these physical points back to the
roi21
physical space you need to apply thefinal_transform
to them. They are defined in theroi11
physical space and you want them in theroi21
physical space.
For further discussions relating to SimpleITK please use the ITK discourse which is a dedicated forum for the toolkit.
本文标签:
版权声明:本文标题:python 3.x - SimpleITK GetInverse() to remap moved images centroid to original image centroid CT images - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741525773a2383455.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论