OpenCV: playing with brightness, contrast, histogram, blurness

Change Brightness of Image or Video

Changing brightness is a point operation on each pixel. If you want to increase the brightness, you have to add some constant value to each and every pixel.
new_img (i, j) = img(i, j) + cIf you want to decrease the brightness, you have to subtract some constant value from each and every pixel.
new_img (i, j) = img(i, j) – ce.g- Say, this is your original image

Original Image
Original Image

Say, you want to increase the brightness of the image by 20 units. Here is the output image of which the  brightness is increased by 20 units.

Image of which brightness is increased
Image of which brightness is increased

Say, you want to decrease the brightness of the image by 20 units. Here is the output image of which the  brightness is decreased by 20 units.

Image of which brightness is decreased
Image of which brightness is decreased

Note :
You may already notice that although the 1st pixel of the above image should have (12 – 20)  = -8, I have put 0. It is because pixels never have negative values. Any pixel value is bounded below by 0 and bounded above by 2^(bit depth).

#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/core/core.hpp"using namespace cv;
#include <iostream>using namespace std;

int main()
{
Mat img = imread("Deepika_Padukone.jpg");
Mat imgH;
Mat imgL;
imgH = img + Scalar(100, 100, 100);
imgL = img + Scalar(-100, -100, -100);

namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("Increased Brightness Image", CV_WINDOW_AUTOSIZE);
namedWindow("Decreased Brightness Image", CV_WINDOW_AUTOSIZE);

imshow("Original Image", img);
imshow("Increased Brightness Image", imgH);
imshow("Decreased Brightness Image", imgL);
cvWaitKey(0);

return 0;
}

Change Contrast of Image or Video

Changing the contrast is also a point operation on each pixel. The easiest way to increase the contrast of an image is, multiplying each pixel value by a number larger than 1.
                         new_img (i, j) = img(i, j) * c                     c > 1
The easiest way to decrease the contrast is, multiplying each pixel value by a number smaller than 1.
                         new_img (i, j) = img(i, j) * c                     c < 1
There are more advance methods to adjust contrast of an image such as histogram equalization. Such method adjust the contrast of an image such that color distribution is balanced equally. We will discuss the histogram equalization in the next lesson.
e.g- Say, this is your original image
Example Image
Example Image
By multiplying each pixel value by 2, you can effectively double the contrast of an image. Here is the image of which the contrast is increased.
I have considered this image as a 8 bit unsigned image. So, any pixel value should be from 0 to 255. If the resulting image has values more than 255, it should be rounded off to 255.
Contrast Increased
Contrast Increased
By multiplying each pixel value by 0.5, you can effectively halve the contrast of an image. Here is the image of which contrast is decreased.
Contrast Decreased
Contrast Decreased
#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/core/core.hpp"

using namespace cv;
#include <iostream>

using namespace std;

int main()
{
Mat img = imread("Deepika_Padukone.jpg");
Mat imgH;
Mat imgL;
imgH = img * 1.2;
imgL = img *0.8;

namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("Increased contrast Image", CV_WINDOW_AUTOSIZE);
namedWindow("Decreased contrast Image", CV_WINDOW_AUTOSIZE);

imshow("Original Image", img);
imshow("Increased contrast Image", imgH);
imshow("Decreased contrast Image", imgL);
cvWaitKey(0);
return 0;
}

Instead of imgH = img * 1.2, you can use convertTo function.

img.convertTo(imgH, -1, 1.2, 0); //increase the contrast (double)

 

  • void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 )
This OpenCV function converts  image into another format with scaling. Scaling is done according to the following formula.
                                              m[i,j] = alfa * img[i,j] + beta
Here is the parameters of this function
    • OutputArray m – Store the converted image
    • int rtype – Depth of the output image. If the value of rtype is negative, output type is same as the input image. I have used a negative value in the above program because I don’t want to change the depth of the original image. Possible inputs to this parameter
      • CV_8U
      • CV_32S
      • CV_64F
      • -1
    • double alpha – Multiplication factor; Every pixel will be multiplied by this value
    • double beta – This value will be added to very pixels after multiplying with the above value.
Here is the formula again. Here m[i, j] means a pixel at ith row and jth column.
m[i,j] = alfa * img[i,j] + beta

Histogram Equalization of Grayscale or Color Image

Histogram

Histogram is the intensity distribution of an image.
E.G –
Consider the following image. Say, depth of the image is 2 bits. Therefore the value range for each and every pixel is from 0 to 3.
Sample Image (Depth = 2 bits)
Sample Image (Depth = 2 bits)
Histogram of the a image shows how the pixel values are distributed. As you can see in the above image there are 5 pixels with value 0, 7 pixels with value 1, 9 pixels with value 2 and 4 pixels with value 3. These information is tabulated as follows.
Intensity Distribution of above image
Intensity Distribution of above image
Histogram of a image usually presented as a graph. The following graph represents the histogram of the above image.
Image Histogram
Image Histogram

Histogram Equalization

Histogram Equalization is defined as equalizing the intensity distribution of an image or flattening the intensity distribution curve. Histogram equalization is used to improve the contrast of an image. The equalized histogram of the above image should be ideally like the following graph.
Equalized Histogram
Equalized Histogram
But practically, you cannot achieve this kind of perfect histogram equalization. But there are various techniques to achieve histogram equalization close to the perfect one. In OpenCV, there is an in-built OpenCV function to equalize histogram.
With uncolored image
#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/core/core.hpp"using namespace cv;
#include <iostream>using namespace std;

int main()
{
Mat img = imread("Deepika_Padukone.jpg");
cvtColor(img, img, CV_BGR2GRAY);
Mat imgHist;
equalizeHist(img, imgHist);

namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("Histogram Image", CV_WINDOW_AUTOSIZE);

imshow("Original Image", img);
imshow("Histogram Image", imgHist);
cvWaitKey(0);

return 0;
}


With colored image
#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
//#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/core/core.hpp"using namespace cv;
#include <iostream>

using namespace std;

int main()
{
Mat img = imread("scenary2.png", CV_LOAD_IMAGE_COLOR);

Mat imgHist, Y, Cr, Cb;
vector<Mat> channels(3);
cvtColor(img, imgHist, CV_BGR2YCrCb);

split(img, channels);

equalizeHist(channels[0], channels[0]);

merge(channels, imgHist);
namedWindow("Histogram before convert Image", CV_WINDOW_AUTOSIZE);

imshow("Histogram before convert Image", imgHist);

cvtColor(imgHist, imgHist, CV_YCrCb2BGR);

namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("Histogram Image", CV_WINDOW_AUTOSIZE);

imshow("Original Image", img);
imshow("Histogram Image", imgHist);
cvWaitKey(0);

return 0;
}

Some of the functions to look:

  • cvtColor(img, img_hist_equalized, CV_BGR2YCrCb)
This line converts the color space of BGR in ‘img‘ to YCrCb color space and stores the resulting image in ‘img_hist_equalized‘.
In the above example, I am going to equalize the histogram of color images. In this scenario, I have to equalize the histogram of the intensity component only, not the color components. So, BGR format cannot be used because its all three planes represent color components blue, green and red. So, I have to convert the original BGR color space to YCrCb color space because its 1st plane represents the intensity of the image where as other planes represent the color components.
  • void split(const Mat& m, vector<Mat>& mv )
This function splits each channel of the ‘m‘ multi-channel array into separate channels and stores them in a vector, referenced by ‘mv‘.
Argument list
    • const Mat& m – Input multi-channel array
    •  vector<Mat>& mv – vector that stores the each channel of the input array
  • equalizeHist(channels[0], channels[0]);
Here we are only interested in the 1st channel (Y) because it  represents the intensity information whereas other two channels (Cr and Cb) represent color components. So, we equalize the histogram of the 1st channel using OpenCV in-built function, ‘equalizeHist(..)’ and other two channels remain unchanged.
  • void merge(const vector<Mat>& mv, OutputArray dst )
This function does the reverse operation of the split function. It takes the vector of channels and create a single multi-channel array.
Argument list
    • const vector<Mat>& mv – vector that holds several channels. All channels should have same size and same depths
    • OutputArray dst – stores the destination multi-channel array
  • cvtColor(img_hist_equalized, img_hist_equalized, CV_YCrCb2BGR)
This line converts the image from YCrCb color space to BGR color space. It is essential to convert to BGR color space because ‘imshow(..)’ OpenCV function can only show images with that color space.

Leave a Reply

Your email address will not be published. Required fields are marked *