local histogram equalization

filter, histogram, image, numpy, python

Solution

You could use the scikit-image library to perform Global and Local Histogram Equalization. Stealing with pride from the link, below is the snippet. The equalization is done with a disk shaped kernel (or footprint), but you could change this to a square, by setting `kernel = np.ones((N,M))`.

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

from skimage import data
from skimage.util import img_as_ubyte
from skimage import exposure
import skimage.morphology as morp
from skimage.filters import rank

# Original image
img = img_as_ubyte(data.moon())

# Global equalize
img_global = exposure.equalize_hist(img)

# Local Equalization, disk shape kernel
# Better contrast with disk kernel but could be different
kernel = morp.disk(30)
img_local = rank.equalize(img, selem=kernel)

fig, (ax_img, ax_global, ax_local) = plt.subplots(1, 3)

ax_img.imshow(img, cmap=plt.cm.gray)
ax_img.set_title('Low contrast image')
ax_img.set_axis_off()

ax_global.imshow(img_global, cmap=plt.cm.gray)
ax_global.set_title('Global equalization')
ax_global.set_axis_off()

ax_local.imshow(img_local, cmap=plt.cm.gray)
ax_local.set_title('Local equalization')
ax_local.set_axis_off()

plt.show()

Problem

I am trying to use do some image analysis in python (I have to use python). I need to do both a global and local histogram equalization. The global version works well however the local version, using a 7x7 footprint, gives a very poor result. This is the global version: ``` import matplotlib.pyplot as plt import matplotlib.image as mpimg from scipy import ndimage,misc import scipy.io as io from scipy.misc import toimage import numpy as n import pylab as py from numpy import * mat = io.loadmat('image.mat') image=mat['imageD'] def histeq(im,nbr_bins=256): #get image histogram imhist,bins = histogram(im.flatten(),nbr_bins,normed=True) cdf = imhist.cumsum() #cumulative distribution function cdf = 0.6 * cdf / cdf[-1] #normalize #use linear interpolation of cdf to find new pixel values im2 = interp(im.flatten(),bins[:-1],cdf) #returns image and cumulative histogram used to map return im2.reshape(im.shape), cdf im=image im2,cdf = histeq(im) ``` To do the local version, I am trying to use a generic filter like so (using the same image as loaded previously): ``` def func(x): cdf=[] xhist,bins=histogram(x,256,normed=True) cdf = xhist.cumsum() cdf = 0.6 * cdf / cdf[-1] im_out = interp(x,bins[:-1],cdf) midval=interp(x[24],bins[:-1],cdf) return midval print im.shape im3=ndimage.filters.generic_filter(im, func,size=im.shape,footprint=n.ones((7,7))) ``` Does anyone have any suggestions/thoughts as to why the second version will not work? I'm really stuck and any comments would be greatly appreciated! Thanks in advance!

Original source