Search code examples
pythonnumpyimage-processinghistogram

Adaptive Histogram Equalization in Python


I am trying to implement adaptive histogram equalization in python. I take an image and split it into smaller regions and then apply the traditional histogram equalization to it. I then combine the smaller images into one and obtain a final resultant image. The final image appears to be very blocky in nature and has different contrast levels for each individual region. Is there a way I could maintain a uniform contrast for each individual image so that it looks like a single image instead of smaller images stitched together.

Input Output

import cv2
import numpy as np
from matplotlib import pyplot as plt
from scipy.misc import imsave
from scipy import ndimage
from scipy import misc
import scipy.misc
import scipy

import image_slicer
from image_slicer import join
from PIL import Image

img = 'watch.png'
num_tiles = 25
tiles = image_slicer.slice(img, num_tiles)


for tile in tiles:
    img = scipy.misc.imread(tile.filename)
    hist,bins = np.histogram(img.flatten(),256,[0,256])
    cdf = hist.cumsum()
    cdf_normalized = cdf *hist.max()/ cdf.max()  
    plt.plot(cdf_normalized, color = 'g')
    plt.hist(img.flatten(),256,[0,256], color = 'g')
    plt.xlim([0,256])
    plt.legend(('cdf','histogram'), loc = 'upper left')
    cdf_m = np.ma.masked_equal(cdf,0)
    cdf_o = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
    cdf = np.ma.filled(cdf_o,0).astype('uint8')
    img3 = cdf[img]
    cv2.imwrite(tile.filename,img3)
    tile.image = Image.open(tile.filename

image = join(tiles)
image.save('watch-join.png')

Solution

  • I reviewed the actual algorithm and came up with the following implementation. I am sure there is a better way to do this. Any suggestions are appreciated.

    import numpy as np
    import cv2
    
    img = cv2.imread('watch.png',0)
    print img
    img_size=img.shape
    print img_size
    
    img_mod = np.zeros((600, 800))
    
    for i in range(0,img_size[0]-30):
        for j in range(0,img_size[1]-30):
            kernel = img[i:i+30,j:j+30]
            for k in range(0,30):
                for l in range(0,30):
                    element = kernel[k,l]
                    rank = 0
                    for m in range(0,30):
                        for n in range(0,30):
                            if(kernel[k,l]>kernel[m,n]):
                                rank = rank + 1
                    img_mod[i,j] = ((rank * 255 )/900)
    
    im = np.array(img_mod, dtype = np.uint8)
    cv2.imwrite('target.png',im)