quatrope / astroalign

A tool to align astronomical images based on asterism matching
MIT License
140 stars 44 forks source link

Feature request/discussion - additional RANSAC algorithm support #47

Closed 84danie closed 3 years ago

84danie commented 4 years ago

I know that the docs + paper explain that astroalign becomes way more sensitive to outliers and may not work for smaller sets or require special care; have/would you consider adding support for other RANSAC algorithms? There's some variants that may combat this issue, such as Optimal RANSAC, which is described as being able to handle situations when the inlier ratio is as little as 4%.

I ask because for my use case at NASA JPL, the images being registered have very few stars that can be detected (~3-5, with 10-20 predicted), and I was curious if this idea had already been explored or not.

martinberoiz commented 4 years ago

Hello Danielle,

Adding other RANSAC algorithms is an interesting idea. I was reading the paper for the Optimal RANSAC and it seems it can be a good addition. Opt Ransac would also solve issue of reproducibility (no randomness).

I first thought of using the adapter pattern to plug in different RANSAC or different source detection algorithms like photutils instead of sep.

Thank you for bringing that up!

Regarding images with few stars on it, I recommend trying setting MAX_CONTROL_POINTS to 3 or however many stars there are in the field. This until I fix #44, which I hope is soon.

import astroalign as aa
aa.MAX_CONTROL_POINTS = 3
registered = aa.register(source, target)
martinberoiz commented 4 years ago

@84danie by the way, do you know of any python implementation of Optimal RANSAC?

84danie commented 4 years ago

I definitely think it would be worth adding additional support, or at least making it possible to plug in your own implementation. You might not even need adapter pattern - a simple way could be just putting the core functionality of the find_transform function into a class and placing the ransac code into a method of that class. Then users can just override that method with their own implementation and use the class directly instead of calling find_transform. An even simpler approach is just adding a functional parameter to the find_transform function that allows users to pass their own RANSAC function (this could also be used to specify the specific ransac algorithm, if you end up supporting more in-house).

I tried playing around with MAX_CONTROL_POINTS - it didn't seem to have much of an effect. What did end up helping a lot (went from 30% registered to 88%) was effectively "pre-pruning" the initial lists of points of outliers. That is, basically doing:

# pick some max value. For my use case I have estimates of the maximum shift,
# so I use those to calculate the max euclidean distance
max_dist = calc_max_dist()
tree = spatial.KDTree(predicted)
distances, vals = tree.query(detected, distance_upper_bound=max_dist)
detected = detected[np.where(distances != np.inf)] # get rid of points that aren't near any predicted points
# then do the same thing, but swap detected + predicted to prune the predicted set

So I think this is further motivation for trying out different RANSAC algorithms designed for smaller inlier ratios.

Unfortunately, I don't know of any existing python implementations of Optimal RANSAC - you'd most likely have to implement it yourself based on the pseudocode.

martinberoiz commented 3 years ago

Version 2.4 implements a more "deterministic" (but still stochastic) ransac.