Search code examples
pythonhistogramcdf

Histogram equalization without extreme values


Is it possible to make a histogram equalization without the extreme values 0 and 255?

Specifically I have an image, in which many pixels are zero. More than half of all pixels are zero. So if I do a histogram equalization there I shift basically the value 1 up to value 240 which is exactly the opposite what I want to do with a histogram equalization. So is there a method to only calculate the histogram equalization between values 1 and 254?

At the moment my code looks the following:

flat = image.flatten()

# get image histogram
image_histogram, bins = np.histogram(flat, bins=range(0, number_bins), density=True)

cdf = image_histogram.cumsum() # cumulative distribution function
cdf = 255 * cdf /cdf.max() # normalize
cdf = cdf.astype('uint8')

# use linear interpolation of cdf to find new pixel values
image_equalized = np.interp(flat, bins[:-1], cdf)

image_equalized =  image_equalized.reshape(image.shape), cdf

Thanks


Solution

  • One way to solve this would be to filter out the unwanted values before we make the histogram, and then make a "conversion table" from a non-normalized pixel to a normalized pixel.

    import numpy as np
    
    # generate random image
    image = np.random.randint(0, 256, (32, 32))
    
    # flatten image
    flat = image.flatten()
    
    # get image histogram
    image_histogram, bins = np.histogram(flat[np.where((flat != 0) & (flat != 255))[0]],
                                         bins=range(0, 10),
                                         density=True)
    
    cdf = image_histogram.cumsum() # cumulative distribution function
    cdf = 255 * cdf /cdf.max() # normalize
    cdf = cdf.astype('uint8')
    
    # use linear interpolation of cdf to find new pixel values
    # we make a list conversion_table, where the index is the original pixel value,
    # and the value is the histogram normalized pixel value
    conversion_table = np.interp([i for i in range(0, 256)], bins[:-1], cdf)
    # replace unwanted values by original
    conversion_table[0] = 0
    conversion_table[-1] = 255
    image_equalized = np.array([conversion_table[pixel] for pixel in flat])
    
    image_equalized =  image_equalized.reshape(image.shape), cdf
    

    disclaimer: I have absolutely no experience whatsoever with image processing, so I have no idea about the validity :)