1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
Histogram Equalization {#tutorial_histogram_equalization}
======================
@tableofcontents
@prev_tutorial{tutorial_warp_affine}
@next_tutorial{tutorial_histogram_calculation}
| | |
| -: | :- |
| Original author | Ana Huamán |
| Compatibility | OpenCV >= 3.0 |
Goal
----
In this tutorial you will learn:
- What an image histogram is and why it is useful
- To equalize histograms of images by using the OpenCV function @ref cv::equalizeHist
Theory
------
### What is an Image Histogram?
- It is a graphical representation of the intensity distribution of an image.
- It quantifies the number of pixels for each intensity value considered.

### What is Histogram Equalization?
- It is a method that improves the contrast in an image, in order to stretch out the intensity
range (see also the corresponding <a href="https://en.wikipedia.org/wiki/Histogram_equalization">Wikipedia entry</a>).
- To make it clearer, from the image above, you can see that the pixels seem clustered around the
middle of the available range of intensities. What Histogram Equalization does is to *stretch
out* this range. Take a look at the figure below: The green circles indicate the
*underpopulated* intensities. After applying the equalization, we get an histogram like the
figure in the center. The resulting image is shown in the picture at right.

### How does it work?
- Equalization implies *mapping* one distribution (the given histogram) to another distribution (a
wider and more uniform distribution of intensity values) so the intensity values are spread
over the whole range.
- To accomplish the equalization effect, the remapping should be the *cumulative distribution
function (cdf)* (more details, refer to *Learning OpenCV*). For the histogram \f$H(i)\f$, its
*cumulative distribution* \f$H^{'}(i)\f$ is:
\f[H^{'}(i) = \sum_{0 \le j < i} H(j)\f]
To use this as a remapping function, we have to normalize \f$H^{'}(i)\f$ such that the maximum value
is 255 ( or the maximum value for the intensity of the image ). From the example above, the
cumulative function is:

- Finally, we use a simple remapping procedure to obtain the intensity values of the equalized
image:
\f[equalized( x, y ) = H^{'}( src(x,y) )\f]
Code
----
- **What does this program do?**
- Loads an image
- Convert the original image to grayscale
- Equalize the Histogram by using the OpenCV function @ref cv::equalizeHist
- Display the source and equalized images in a window.
@add_toggle_cpp
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/4.x/samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp)
- **Code at glance:**
@include samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp
@end_toggle
@add_toggle_java
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/4.x/samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java)
- **Code at glance:**
@include samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java
@end_toggle
@add_toggle_python
- **Downloadable code**: Click
[here](https://github.com/opencv/opencv/tree/4.x/samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py)
- **Code at glance:**
@include samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py
@end_toggle
Explanation
-----------
- Load the source image:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Load image
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Load image
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Load image
@end_toggle
- Convert it to grayscale:
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Convert to grayscale
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Convert to grayscale
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Convert to grayscale
@end_toggle
- Apply histogram equalization with the function @ref cv::equalizeHist :
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Apply Histogram Equalization
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Apply Histogram Equalization
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Apply Histogram Equalization
@end_toggle
As it can be easily seen, the only arguments are the original image and the output (equalized)
image.
- Display both images (original and equalized):
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Display results
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Display results
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Display results
@end_toggle
- Wait until user exists the program
@add_toggle_cpp
@snippet samples/cpp/tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp Wait until user exits the program
@end_toggle
@add_toggle_java
@snippet samples/java/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHistDemo.java Wait until user exits the program
@end_toggle
@add_toggle_python
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_equalization/EqualizeHist_Demo.py Wait until user exits the program
@end_toggle
Results
-------
-# To appreciate better the results of equalization, let's introduce an image with not much
contrast, such as:

which, by the way, has this histogram:

notice that the pixels are clustered around the center of the histogram.
-# After applying the equalization with our program, we get this result:

this image has certainly more contrast. Check out its new histogram like this:

Notice how the number of pixels is more distributed through the intensity range.
@note
Are you wondering how did we draw the Histogram figures shown above? Check out the following
tutorial!
|