Skip to content

Commit bbeab08

Browse files
committed
thuva4#152 Added Java 8 implementation of Histogram Equalization
1 parent 51bd085 commit bbeab08

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* This file has been created by github user vn17.
3+
* Feel free to use it for any purpose.
4+
*
5+
* This file makes extensive use of Java 8 lambdas.
6+
*
7+
* For more details on the algorithm,
8+
* refer to @see <a href=https://en.wikipedia.org/wiki/Histogram_equalization>https://en.wikipedia.org/wiki/Histogram_equalization</a>
9+
*/
10+
package Java;
11+
12+
import java.util.Arrays;
13+
import java.util.HashMap;
14+
import java.util.stream.IntStream;
15+
16+
import static java.util.stream.Collectors.joining;
17+
18+
19+
public class HistogramEqualization {
20+
21+
public static void main(String[] args) {
22+
ImageMatrix imageMatrix = new ImageMatrix(new int[][]{{2, 3, 1}, {3, 4, 6}, {7, 3, 6}});
23+
System.out.println("Input Matrix: \n" + imageMatrix);
24+
System.out.println("Frequency: \t" + imageMatrix.frequency() + "\nCDF: \t\t" + imageMatrix.cdf() + "\n");
25+
ImageMatrix equalizedImageMatrix = imageMatrix.equalize();
26+
System.out.println("Histogram Equalized Matrix: \n" + equalizedImageMatrix);
27+
}
28+
}
29+
30+
class ImageMatrix {
31+
private static final int NUMBER_OF_LEVELS = 8;//This is the intensity range.
32+
// Eg. For a 3 bit per pixel image, the intensity value is 8.
33+
34+
private int cdfMin = -1;//This is the cdf of the minimum intensity value
35+
36+
private int size;//Size of the image. 3 x 3 = 9 in this case
37+
38+
private int[][] imageArray;//3 x 3 Array to store intensity values at each pixel
39+
40+
private HashMap<Integer, Integer> frequency;//HashMap to store the frequency of each intensity value i.e.
41+
// the number of times each value has appeared in the 3 x 3 array.
42+
43+
private HashMap<Integer, Integer> cdf;//HashMap to store the CDF of each intensity value i.e.
44+
// the sum of the frequency values of all intensities lesser than the current intensity level.
45+
46+
public ImageMatrix(int[][] arr) {
47+
this.imageArray = arr;
48+
this.size = (int) Arrays.stream(arr).flatMapToInt(IntStream::of).count();
49+
}
50+
51+
public int getFrequency(int key) {
52+
if (frequency == null) calculateFrequency();
53+
return frequency().get(key);
54+
}
55+
56+
public int getCdf(int key) {
57+
if (cdf == null) calculateCdf();
58+
return cdf().get(key);
59+
}
60+
61+
public HashMap<Integer, Integer> frequency() {
62+
if (frequency == null) calculateFrequency();
63+
return frequency;
64+
}
65+
66+
public HashMap<Integer, Integer> cdf() {
67+
if (cdf == null) calculateCdf();
68+
return cdf;
69+
}
70+
71+
/**
72+
* This method calculates the frequency of each intensity value in the given intensity range.
73+
*/
74+
private void calculateFrequency() {
75+
this.frequency = new HashMap<>();
76+
Arrays.stream(imageArray)//Get the 2D array
77+
.flatMapToInt(IntStream::of)//Convert it to a 1D array
78+
.forEach(intensity -> {//Increment the frequency value for intensity by 1
79+
if (frequency.containsKey(intensity)) frequency.put(intensity, frequency.get(intensity) + 1);
80+
else frequency.put(intensity, 1);
81+
});
82+
}
83+
84+
/**
85+
* This method calculates the CDF by adding all the intensity values lesser than the current value.
86+
*/
87+
private void calculateCdf() {
88+
if (frequency == null) calculateFrequency();
89+
cdf = (HashMap) frequency().clone();
90+
cdf.keySet().stream()
91+
.sorted().mapToInt(Integer::intValue)
92+
.reduce(0, (previousSum, currentKey) -> {
93+
int sum = previousSum + cdf.get(currentKey);
94+
cdf.put(currentKey, sum);
95+
if (cdfMin == -1)//To store the cdf of the minimum intensity value
96+
cdfMin = sum;
97+
return sum;
98+
});
99+
}
100+
101+
/**
102+
* This method applies the equalization formula to each element in the matrix.
103+
* @return
104+
*/
105+
public ImageMatrix equalize() {
106+
int[][] equalizedArray = Arrays.stream(imageArray)
107+
.map(p -> Arrays.stream(p).map(q -> (getCdf(q) - cdfMin) * (NUMBER_OF_LEVELS - 2) / (size - 1) + 1).toArray())
108+
.toArray(int[][]::new);
109+
return new ImageMatrix(equalizedArray);
110+
}
111+
112+
/**
113+
* Prints a 2D array line by line for each array.
114+
* @return
115+
*/
116+
@Override
117+
public String toString() {
118+
return Arrays.stream(imageArray).map(s -> String.format("%s\n", Arrays.toString(s))).collect(joining());
119+
}
120+
}
121+

0 commit comments

Comments
 (0)