The algorithm is simple enough. Create a 1-D array of data from the 2-D image matrix. Each element of the array has four attributes:
- x-position
- y-position
- intensity value on [0,255]
- priority (default it to zero for each pixel)
Now, generate a histogram from this data, with values in one of the 256 unique bins, based on the intensity value. That should be easy enough.
Now, just calculate the average number of elements there should be in each bin (ie: rows * columns / 256), and round it to the nearest integer. With this value you know how many pixels should be in each histogram "bin". So, in your histogram, you:
- Loop through the first 255 of the 256 histogram bins
- Calculate if the number of values in the bin is higher or lower than the average.
- If too many pixels in the current bin:
- Sort the pixels in each bin by its "priority" value, in ascending order (ie: start with 0; the higher the priority, the LESS likely you will move the pixel).
- Take the pixel with the lowest priority, and move the pixel up to the next bin (ie: increment its intensity value), and increment its priority value.
- Repeat this until the number of pixels in the current bin is equal to the expected value (ie: Rows * Columns / 256).
- You may end up with too many items in the final bin, bin #255 (ie: the 256th bin). You can remedy this by repeating the above algorithm on the histogram, but in reverse. This time, though, sort the pixels by priority in descending order. So, the higher the priority value, the MORE likely it will be moved. When you move this pixel this time, you are decrementing both its intensity value and priority, rather than incrementing them.
Now that the histogram is equalized, you can loop through it's contents to re-create the original 2D image.
The "priority" values are important, so you don't accidentally shift a pixel across more bins than needed, resulting in either Gaussian or even impulse/salt-pepper noise.
The overall algorithm should be O(n^2)
, so it should be half-decent in terms of performance.
One last thing: if the sorting algorithm you use is not a stable sort, it more-or-less randomizes which pixels of equal value are moved across bins, which is helpful such that it prevents moving a cluster of adjacent pixels that have equal intensity values.