Jzl5325
Jzl5325

Reputation: 3974

numpy.interp & masked arrays

I am using a numpy masked array to perform some image processing. The mask is in place to handle NoData pixels which surround the image (a necessary border as these are map projected images with the origin in a no data pixel).

Using the following code block, I am able to perform a gaussian stretch on an image.

def gaussian_stretch(input_array, array_mean, array_standard_deviation, number_of_bins, n):
    shape = input_array.shape
    input_array = input_array.flatten()
    #define a gaussian distribution, get binned GDF histogram
    array_standard_deviation *= n
    gdf = numpy.random.normal(array_mean, array_standard_deviation, 10000)
    hist, bins = numpy.histogram(gdf, number_of_bins, normed=True)
    cdf = hist.cumsum()
    cdf = 256 * cdf / cdf[-1]
    #interpolate and reshape
    input_array = numpy.interp(input_array,bins[:-1],cdf)
    input_array = input_array.reshape(shape)
    return input_array

If the image does not contain a NoData border the stretch works as expected. On an image with a mask, the mask is ignored. Is this expected behavior? Any ideas on how to process only the unmasked data?

I have tried using input_array.compressed(), but this returns a 1D array of only the unmasked values. Using numpy.interp then fails, as expected, because of the size disparity between arrays.

Finally, I understand that using numpy.random.normal will not always return a perfect gaussian distribution and I will add some margin of error contraints once the rest of the algorithm is functioning.

Upvotes: 3

Views: 2049

Answers (1)

HYRY
HYRY

Reputation: 97281

you can get the mask of input_array first, and apply it to the result array, and use scipy.stats.norm to calculate cdf of normal distribution, or you can use scipy.special.erf() to calculate cdf by using the cdf formula of normal distribution:

import scipy.stats as stats    
def gaussian_stretch2(input_array, array_mean, array_standard_deviation, n):
    mask = input_array.mask
    n = stats.norm(array_mean, array_standard_deviation*n)
    return numpy.ma.array(n.cdf(input_array), mask=mask)

Upvotes: 3

Related Questions