spectralpython/spectral

How to use iterator function for image masking

pythonic2020 opened this issue · 4 comments

Hello,

I have a floating point cube with lots of zeros in it indicating NoData. I would like to perform band math to generate spectral indices, and want to try masking to avoid the divide-by-zero issues. I can't figure how to use the SPy iterator function to do this. I have tried:

import spectral as spy

# Make mask
non_zero_mask = myimage[:, :, 0] > 0 

mask_iterator = spy.algorithms.iterator(myimage, mask=non_zero_mask)

After that, I have tried using the iterator for looping, etc. but can't get anything to work. Could you please explain what I'm doing wrong? I'll bet the answer is simple.... I can get my ratios going by adding small float values to the bands before dividing them, and that works fine, but I am seeking a more elegant method using masking.

Thank you in advance.

Not sure if I entirely understand what you're trying to do but if you're working with numpy arrays, using iterators is probably going to be very slow. I would try something like this:

In [26]: x = np.eye(3)                                                                                                                       

In [27]: y = 2 * x                                                                                                                           

In [28]: x                                                                                                                                   
Out[28]: 
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

In [29]: y                                                                                                                                   
Out[29]: 
array([[2., 0., 0.],
       [0., 2., 0.],
       [0., 0., 2.]])

In [30]: z = np.zeros_like(y)                                                                                                                

In [31]: m = x > 0                                                                                                                           

In [32]: z[m] = x[m] / y[m]                                                                                                                  

In [33]: z                                                                                                                                   
Out[33]: 
array([[0.5, 0. , 0. ],
       [0. , 0.5, 0. ],
       [0. , 0. , 0.5]])

Very nice! I'll try that now. Many thanks!

Could you also give an example of how your iterator function is intended to be used? It looks powerful, and it piqued my interest.

That is a base class for other iterators (e.g., ImageIterator) for general iteration over all image pixels (or all pixels associated with a ground truth mask). For most cases (e.g., simple band math), it's much more efficient to just use numpy masks but for some more complicated operations, they are handy. There are some examples in the linked code.

Thank you for the explanation! :-)