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. ![](images/Histogram_Equalization_Theory_0.jpg) ### 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 Wikipedia entry). - 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. ![](images/Histogram_Equalization_Theory_1.jpg) ### 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: ![](images/Histogram_Equalization_Theory_2.jpg) - 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: ![](images/Histogram_Equalization_Original_Image.jpg) which, by the way, has this histogram: ![](images/Histogram_Equalization_Original_Histogram.jpg) notice that the pixels are clustered around the center of the histogram. -# After applying the equalization with our program, we get this result: ![](images/Histogram_Equalization_Equalized_Image.jpg) this image has certainly more contrast. Check out its new histogram like this: ![](images/Histogram_Equalization_Equalized_Histogram.jpg) 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!