Stopping optimization by metric value for demons filters

Hi,

I’m currently using the Python demons registration filters (DemonsRegistrationFilter, DifferomorphicDRF, SymmetricDRF, etc.) from SimpleITK to perform non-rigid image registration on x-rays for my research.

Is there a simple way to set the filters to stop running upon reaching a certain metric value? Right now, the filters run until the maximum number of iterations has been reached regardless of metric value.

I’ve looked through the documentation several times and I can’t seem to find what I’m looking for. I know that one solution would be to run the the filter twice to see what metric value is achieved at each iteration but if registration takes 1000s of iterations I’d prefer not to do it more than once.

Should I be using the ITKv4 registration framework instead to better control optimization?

Hello @bbikdash,

Welcome to SimpleITK!

The Demons family of algorithms has a SetMaximumRMSError which provides you with an image similarity based stopping criterion, the SetNumberOfIterations gives you a known bound on the number of iterations.

Using the observer/callback mechanism you can look at the RMS change GetRMSChange and force early termination by changing the caller’s settings (I believe SetNumberOfIterations(GetElapsedIterations()-1) will work though haven’t tried it).

Hi @zivy,

Thanks for your advice. I tried some of what you recommended. I’ve been basing my code on the python version here: DemonsRegistration1 — SimpleITK 2.0rc2 documentation

I experimented with the SetMaximumRMSError function and it definitely works to stop iterations. However, when experimenting with two sets of images the final RMS was higher for the more similar images and lower for images that were more different. So, demons registration stopped for images that needed more registration but kept going for images that were registered very well.

When I added a callback to look at the RMS Change values they were all 0.0. The exact modification I did is shown below.

def command_iteration(filter):
    print(f"{filter.GetElapsedIterations():3} = {filter.GetMetric():10.5f}\n"
            f"RMS Change: {filter.GetRMSChange():5:10f}")

But, if I understand you what told me, the command_iteration inline function allows me to send callbacks to the demons observable during runtime. I should be able to add a stopping criterion in this inline function based on the metric or RMS error.

I added a stopping criterion based on the current metric value. Here’s my modified function:

def command_iteration(filter):
        print(f"{filter.GetElapsedIterations():3} = {filter.GetMetric():10.5f}")

        # This is a test to stop the filter in the middle of iterations
        if filter.GetMetric() < 10.0:
            filter.SetNumberOfIterations(filter.GetElapsedIterations() - 1)
            print(f"{filter.GetNumberOfIterations():3}")

I don’t think it stopped iterations. This is an excerpt of the output:

    40 =   10.13214
     41 =   10.06969
     42 =    9.95903
     41
     43 =   10.21076
     44 =    9.88058
     43
     45 =    9.95140
     44
     46 =    9.80128
     45
     47 =    9.84532
     46
     48 =    9.81111
     47
     49 =    9.67928
     48
     50 =    9.69624
     49

Do you know if there are any other methods that might work?

Hello @bbikdash,

Looks like this trick doesn’t work. It is due to the SimpleITK implementation and the interaction with the underlying ITK code. It should be addressed by this PR which will expose the StopRegistration method, allowing the caller to explicitly stop the registration.

To use the functionality you will have to update your version of SimpleITK to latest, once the PR is merged.

2 Likes

Hi, @zivy,

Thank you for the update. I’m glad I was able to contribute to adding more functionality to SimpleITK.

My last questions are, will the documentation be updated to include this new function and will this update also apply to the Anaconda version of SimpleITK?

Although it seems fairly intuitive, I want to make sure I use it properly.

Hi @bbikdash,

Yes documentation will be added and this will be part of the SimpleITK anaconda distribution.

The next official SimpleITK release, 2.1, is expected in the next couple of weeks so you will be able to install that from the toolkit’s anaconda cloud channel. If you are in a hurry you will be able to use the feature once the pull-request is merged and the latest release is updated on GitHub (the install from GitHub works for anaconda too).

Hello @bbikdash,

The StopRegistration method for all of the Demons based filters is now available, install latest release from GitHub.