# \[SOLVED\] Difficulty getting registration to work with mask on moving image

**URL:** https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423
**Category:** Beginner Questions
**Tags:** registration, simpleitk
**Created:** [February 5, 2025, 4:06pm UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423 "2025-02-05T16:06:28Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![ebaudrez](https://discourse.itk.org/letter_avatar_proxy/v4/letter/e/e8c25b/32.png) [@ebaudrez](https://discourse.itk.org/u/ebaudrez)
#### Post date: [February 5, 2025, 4:06pm UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423/1 "2025-02-05T16:06:29Z")

</div>

**Update 6 February: I got this to work. I confirm the mask on the moving image works.**

Hello! I am having difficulty to get a registration with a mask on the _moving_ image to work. I have attached the full code below, as well as the two images that I’m trying to register. One of the images, the moving image, has “bad” values that I want the registration to ignore.

I am trying to register with a translation transform. The code works fine when I do not apply any mask. I can also get it to work when applying a mask to the fixed image, with `m.SetMetricFixedMask`. But when I try to apply a mask to the moving image, with `m.SetMetricMovingMask`, the registration refuses to run. It tells me that _“All samples map outside moving image buffer”_, but I do not understand why. I checked the mask, and it has 0 values exactly where the bad values are, and 1 elsewhere.

Could someone give me a hint about what I’m not doing right?

[fix.tif](https://discourse.itk.org/uploads/short-url/mJJHsu5LMha8DTxGjX3N7yMbT9P.tif) (842.7 KB)  
[mov.tif](https://discourse.itk.org/uploads/short-url/AuF2X8RhrYbIHy3sToIM4U3g3Kg.tif) (837.1 KB)  
[mov\_mask.png](https://discourse.itk.org/uploads/short-url/ir1nMyn040fS0SUhoHuuiDNj9Zq.png)  
[metric\_moving\_mask.py](https://discourse.itk.org/uploads/short-url/puSvZ7X6eH5divfbsHh6iF9SurN.py) (1.4 KB)

Here are the contents of `metric_moving_mask.py`:

```auto
import SimpleITK as sitk  
  
# unregistered images, in a type suitable for direct ingestion into the registration  
fix = sitk.ReadImage("fix.tif")  
mov = sitk.ReadImage("mov.tif")                 
mov_mask = sitk.ReadImage("mov_mask.png")   
                                        
# set up registration               
m = sitk.ImageRegistrationMethod()  
m.SetMetricMovingMask(mov_mask)                                                                               
m.SetMetricAsMattesMutualInformation()  
m.SetMetricSamplingStrategy(m.NONE)  
m.SetOptimizerAsGradientDescentLineSearch(2, 50, 1e-6)  
m.SetInterpolator(sitk.sitkLinear)   
m.AddCommand(  
    sitk.sitkIterationEvent,  
    lambda: print(  
        f"{m.GetOptimizerIteration():3}, {m.GetMetricValue():10.5f}, {m.GetOptimizerPosition()}"    
    ),  
)  
  
# execute registration   
t = sitk.TranslationTransform(2)  
m.SetInitialTransform(t)  
final_transform = m.Execute(fix, mov)  
print(f"final transform: {final_transform}")                                    
print(f"Optimizer stop condition: {m.GetOptimizerStopConditionDescription()}")  
                                                                     
# diagnostic image                                                   
resampler = sitk.ResampleImageFilter()                               
resampler.SetReferenceImage(fix)                                     
resampler.SetInterpolator(sitk.sitkLinear)  
resampler.SetTransform(final_transform)  
mov_r = resampler.Execute(mov)  
fix_8 = sitk.Cast(sitk.RescaleIntensity(fix), sitk.sitkUInt8)  
mov_r_8 = sitk.Cast(sitk.RescaleIntensity(sitk.Mask(mov_r, mov_mask)), sitk.sitkUInt8)                                       
im_registered = sitk.Compose(fix_8, mov_r_8, fix_8)                                      
sitk.WriteImage(im_registered, "diagnostic.png")

```

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [February 5, 2025, 4:54pm UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423/2 "2025-02-05T16:54:25Z")

</div>

Samples are randomly taken in the fixed image (within the fixed mask). Then they are transformed to the moving image. If they fall outside of the image (or within bad region), they are discarded. If the moving mask’s “good” region is small, this situation frequently happens.

If you don’t have a fixed mask, you can swap fixed/moving designation and later invert the transform. If you have both fixed and moving mask, try setting the image with more restrictive mask as the “fixed”. This trick is harder to pull of with transforms that do not have a closed-form inverse.

---

<div class="post-metadata">

### Author: ![ebaudrez](https://discourse.itk.org/letter_avatar_proxy/v4/letter/e/e8c25b/32.png) [@ebaudrez](https://discourse.itk.org/u/ebaudrez)
#### Post date: [February 6, 2025, 9:44am UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423/3 "2025-02-06T09:44:52Z")

</div>

Hi Dženan, thank you for your reply. Your reply made me try out a few more things, and I finally got it to work. I will document it here for future reference 🙂

Somewhat surprisingly (to me, at least 😃 ), when I change the optimizer method, I can get the code shown above to work on the images attached. For anyone interested in the solution, change the line that reads

```auto
m.SetOptimizerAsGradientDescentLineSearch(2, 50, 1e-6)

```

into

```auto
m.SetOptimizerAsPowell()

```

With this change, the code now converges nicely on the right solution (you can inspect the diagnostic image created at the end). You will also need to change the line

```auto
mov_r_8 = sitk.Cast(sitk.RescaleIntensity(sitk.Mask(mov_r, mov_mask)), sitk.sitkUInt8)                                       

```

into

```auto
mask_r = resampler.Execute(mov_mask)
mov_r_8 = sitk.Cast(sitk.RescaleIntensity(sitk.Mask(mov_r, mask_r)), sitk.sitkUInt8)

```

Of course, this begs the question why the gradient descent method failed. I suspect that it is trying extreme values of the parameters, but without extra information from the optimizer, I cannot confirm that.

Anyway, I consider this problem solved. Thank you for pointing me in the right direction!

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [February 6, 2025, 12:50pm UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423/4 "2025-02-06T12:50:43Z")

</div>

The gradient based methods are sensitive to the scales. They can over step the image bounds when not set correctional.

I don’t see any “SetOptimizerScales…” methods being used? You can give those methods a try.

---

<div class="post-metadata">

### Author: ![ebaudrez](https://discourse.itk.org/letter_avatar_proxy/v4/letter/e/e8c25b/32.png) [@ebaudrez](https://discourse.itk.org/u/ebaudrez)
#### Post date: [February 6, 2025, 1:14pm UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423/5 "2025-02-06T13:14:34Z")

</div>

> [@blowekamp](#):
>
> I don’t see any “SetOptimizerScales…” methods being used? You can give those methods a try.

That is correct. For a pure translation, I didn’t think settings the scales (which I assume are 1 by default) would provide any benefit. Am I mistaken?

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [February 6, 2025, 1:37pm UTC](https://discourse.itk.org/t/solved-difficulty-getting-registration-to-work-with-mask-on-moving-image/7423/6 "2025-02-06T13:37:06Z")

</div>

> [@ebaudrez](#):
>
> For a pure translation, I didn’t think settings the scales (which I assume are 1 by default) would provide any benefit. Am I mistaken?

This is a question best answered by an experiment. The auto scaling scale takes into consideration the pixel spacing, and the intensity values, and the particular metric, which all can effect the gradient.
