quatrope / astroalign

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

propagate_mask #72

Closed yas-nakajima closed 2 years ago

yas-nakajima commented 2 years ago

I made a masked array.

[In]:

import numpy as np

array = np.zeros((5,5))
array[2, 2] = 1

mask = np.zeros((5,5), dtype=bool)
mask[2, 2] = True

marray = np.ma.masked_array(array, mask=mask)

marray

[Out]

masked_array(
  data=[[0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, --, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0]],
  mask=[[False, False, False, False, False],
        [False, False, False, False, False],
        [False, False,  True, False, False],
        [False, False, False, False, False],
        [False, False, False, False, False]],
  fill_value=1e+20)

Then I created a transform, a simple shift by (0.5, 0.5).

[In]:

import astroalign as aa

dst = np.array([[1, 1],[3,1],[1,3]])
src = np.array([[1.5, 1.5],[3.5,1.5],[1.5,3.5]])
tform = aa.estimate_transform('affine', src, dst)

tform.params 

[Out]:

array([[ 1.00000000e+00,  4.58589633e-16, -5.00000000e-01],
       [-1.45262251e-16,  1.00000000e+00, -5.00000000e-01],
       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])

Then I executed apply_transform with propagate_mask=True. [In]:

reg, footp = aa.apply_transform(tform, marray, marray, propagate_mask=True)

[In]:

reg

[Out]:

array([[0.00390625, 0.        , 0.        , 0.00390625, 0.        ],
       [0.        , 0.31640625, 0.31640625, 0.        , 0.        ],
       [0.        , 0.31640625, 0.31640625, 0.        , 0.        ],
       [0.00390625, 0.        , 0.        , 0.00390625, 0.        ],
       [0.        , 0.        , 0.        , 0.        , 0.        ]])

[In]:

footp

[Out]:

array([[False, False, False, False,  True],
       [False, False, False, False,  True],
       [False, False, False, False,  True],
       [False, False, False, False,  True],
       [ True,  True,  True,  True,  True]])

The 'True' mask(s) around the center vanished.
I expected something like

array([[True, False, False, True,  True],
       [False, True, True, False,  True],
       [False, True, True, False,  True],
       [True, False, False, True,  True],
       [ True,  True,  True,  True,  True]])

Do I misunderstand the usage?

Thanks

martinberoiz commented 2 years ago

Hi,

Sorry for the late reply. I looked into it and I found the source of the error. Turns out that when you apply the transformation to the mask the one center True pixel in the mask is smeared on its neighbor pixels. This is the transformation of the mask before discretizing it back into True/False.

array([[0.  , 0.  , 0.  , 0.  , 0.5 ],
       [0.  , 0.25, 0.25, 0.  , 0.5 ],
       [0.  , 0.25, 0.25, 0.  , 0.5 ],
       [0.  , 0.  , 0.  , 0.  , 0.5 ],
       [0.5 , 0.5 , 0.5 , 0.5 , 0.75]], dtype=float32)

The threshold value that astroalign uses to consider a pixel to be on the mask is if it's larger than 0.4. All the 0.25 don't make the cut and the hole is lost.

This is probably a not so common case, but I wonder if the threshold should be more aggressive and set it to 0.1 for example. Or even just do a > 0. The 0.4 was there to avoid too-soft edges.

yas-nakajima commented 2 years ago

Thank you for your reply. Now I understand the specification for the threshold.