Friday, September 5, 2014

Change Contrast of Image or Video

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


Change Contrast of an Image

How to increase or decrease the contrast of an image is demonstrated in the following OpenCV C++ example. Keep in mind that this is the very basic way of changing contrast. In the next lesson, I'll show you how to change the contrast using histogram equalization.

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

 
using namespace cv;

using namespace std;

int main( int argc, const char** argv )

{

Mat img = imread("MyPic.JPG", CV_LOAD_IMAGE_COLOR); //open and read the image



if (img.empty())

{
cout << "Image cannot be loaded..!!" << endl;
return -1;
}

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

Mat imgL;
img.convertTo(imgL, -1, 0.5, 0); //decrease the contrast (halve)

//create windows
namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("High Contrast", CV_WINDOW_AUTOSIZE);
namedWindow("Low Contrast", CV_WINDOW_AUTOSIZE);

//show the image
imshow("Original Image", img);
imshow("High Contrast", imgH);
imshow("Low Contrast", imgL);

waitKey(0); //wait for key press

destroyAllWindows(); //destroy all open windows

return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
You can download this OpenCV visual c++ project from here. (The downloaded file is a compressed .rar folder. So, you have to extract it using Winrar or other suitable software)

Here is the original image.

Original Image
Original Image

Here is the image of which contrast is increased by the OpenCV program.
Contrast is increased with OpenCV
Contrast is increased with OpenCV


Here is the image of which contrast is decreased by the OpenCV program.

Contrast is decreased with OpenCV
Contrast is decreased with OpenCV

New OpenCV methods

  • 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
Complete list of depths can be found in Basics of OpenCV API
  • 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

Change the Contrast of a Video

It is similar to the above program except that you have to change the contrast for each and every frame of the video. Here is the example OpenCV program.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    VideoCapture cap("C:/Users/SHERMAL/Desktop/SampleVideo.wmv"); // open the video file for reading

    if ( !cap.isOpened() )  // if not success, exit program
    {
         cout << "Cannot open the video file" << endl;
         return -1;
    }

    //create windows
    namedWindow("Original Video",CV_WINDOW_AUTOSIZE); 
    namedWindow("Contrast Increased",CV_WINDOW_AUTOSIZE); 
    namedWindow("Contrast Decreased",CV_WINDOW_AUTOSIZE); 

    while (1)
    {
        Mat frame;

        bool bSuccess = cap.read(frame); // read a new frame from video

         if (!bSuccess) //if not success, break loop
        {
cout << "Cannot read the frame from video file" << endl;
break;
        }

Mat imgH;
frame.convertTo(imgH, -1, 2, 0); //increase the contrast (double)

Mat imgL;
frame.convertTo(imgL, -1, 0.5, 0); //decrease the contrast (halve)

//show the image
        imshow("Original Video", frame); 
imshow("Contrast Increased", imgH); 
imshow("Contrast Decreased", imgL); 

       if (waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
        {
                cout << "esc key is pressed by user" << endl; 
                break
        }
    }
    return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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) + c

 If 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) - c

e.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).


Change the Brightness of an Image


Now I am going to show you how to increase or decrease brightness of an image using an OpenCV C++ example.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, const char** argv )
{
Mat img = imread("MyPic.JPG", CV_LOAD_IMAGE_COLOR);

if (img.empty())
{
cout << "Image cannot be loaded..!!" << endl;
return -1;
}

Mat imgH = img + Scalar(75, 75, 75); //increase the brightness by 75 units
     //img.convertTo(imgH, -1, 1, 75);

Mat imgL = img + Scalar(-75, -75, -75); //decrease the brightness by 75 units
     //img.convertTo(imgL, -1, 1, -75);

namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
namedWindow("High Brightness", CV_WINDOW_AUTOSIZE);
namedWindow("Low Brightness", CV_WINDOW_AUTOSIZE);

imshow("Original Image", img);
imshow("High Brightness", imgH);
imshow("Low Brightness", imgL);

waitKey(0);

destroyAllWindows(); //destroy all open windows

return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
You can download this OpenCV visual c++ project from here. (The downloaded file is a compressed .rar folder. So, you have to extract it using Winrar or other suitable software)

Here is the original image.

Original image
original image

Here is the image of which brightness is increased by the OpenCV program.
Brightness is increased with OpenCV
Brightness is increased with OpenCV

Here is the image of which brightness is decreased by the OpenCV program.
Brightness is decreased with OpenCV
Brightness is decreased with OpenCV


New OpenCV functions

  • Mat imgH = img + Scalar(75, 75, 75);
This line of code adds 75 to each and every pixel in the 3 channels (B, G, R channels) of 'img'.  Then it assigns this new image to 'imgH'.
Instead you can use this function also.
                               img.convertTo(imgH, -1, 1, 75);


  • Mat imgL = img + Scalar(-75, -75, -75);
This line of code subtracts 75 from each and every pixel in the 3 channels (B, G, R channels) of 'img'.  Then it assigns this new image to'imgL'.
Instead you can use this function also.
                             img.convertTo(imgL, -1, 1, -75);



Change the Brightness of a Video


Now I am going to show you how to increase or decrease the brightness of a video using an OpenCV C++ example. This is pretty much similar to the previous example.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    VideoCapture cap("C:/Users/SHERMAL/Desktop/SampleVideo.wmv"); // open the video file for reading

    if ( !cap.isOpened() )  // if not success, exit program
    {
            cout << "Cannot open the video file" << endl;
            return -1;
    }

    namedWindow("Original Video",CV_WINDOW_AUTOSIZE); //create a window called "Original Video"
    namedWindow("Brightness Increased",CV_WINDOW_AUTOSIZE); //create a window called "Brightness Increased"
    namedWindow("Brightness Decreased",CV_WINDOW_AUTOSIZE); //create a window called "Brightness Decreased"

    while(1)
    {
           Mat frame;

           bool bSuccess = cap.read(frame); // read a new frame from video

            if (!bSuccess) //if not success, break loop
           {
                        cout << "Cannot read the frame from video file" << endl;
                       break;
           }

Mat imgH = frame + Scalar(50, 50, 50); //increase the brightness by 75 units

Mat imgL = frame + Scalar(-50, -50, -50); //decrease the brightness by 75 units

           imshow("Original Video", frame); //show the frame in "Original Video" window
imshow("Brightness Increased", imgH); //show the frame of which brightness increased
imshow("Brightness Decreased", imgL); //show the frame of which brightness decreased

           if (waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
           {
                   cout << "esc key is pressed by user" << endl; 
                   break
           }
    }

    return 0;

}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

You can download this OpenCV visual c++ project from here. (The downloaded file is a compressed .rar folder. So, you have to extract it using Winrar or other suitable software)

Filtering Images




Image filtering is an important part of computer vision. For most of computer vision applications, filtering should be done before anything else. OpenCV supports lots of in-build filtering methods for images. Here is the list of filtering methods that I am going to discuss with you in the following posts (with OpenCV 2.4.5 and C++ )



Here is the list of image filtering methods which are explained using examples with OpenCV 2.1  in C style (not C++)
  • Eroding
  • Dilating
  • Inverting
Here is the original image which I am going to filter using above methods.

Original Image
If you have not install and configure OpenCV yet, please refer to Installing & Configuring with Visual Studio. 



Eroding

Eroding is a simple way of filtering images. Here is how it can be done with OpenCV.

///////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <cv.h>
#include <highgui.h>

int main()
{
        //display the original image
        IplImage* img = cvLoadImage("C:/MyPic.jpg");
        cvNamedWindow("MyWindow");
        cvShowImage("MyWindow", img);

        //erode and display the eroded image
        cvErode(img, img, 0, 2);
        cvNamedWindow("Eroded");
        cvShowImage("Eroded", img);
      
        cvWaitKey(0);
      
        //cleaning up
        cvDestroyWindow("MyWindow");
        cvDestroyWindow("Eroded");
        cvReleaseImage(&img);
      
        return 0;
}
 

///////////////////////////////////////////////////////////////////////////////////////

You can download this OpenCV visual c++ project from here

Eroded Image

New OpenCV functions which are not found earlier are explained here 
  • cvErode(img, img, 0, 2)
The 1st parameter is the source image.
The 2nd parameter is the destination image which is to be the eroded image.
Here the 3rd parameter is the structuring element used for erosion. If it is 0, a 3×3 rectangular structuring element is used. 
The 4th parameter is the number of times, erosion is applied.
This function can process images in place. That means same variable can be used for the 1st and 2nd parameters.

If you want more explanation about various methods in the above computer application , please refer to Capturing Images & Videos. 



Dilating 

Dilating is something like opposite of the eroding an image. Here is the OpenCV code.

///////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <cv.h>
#include <highgui.h>

int main()
{
        //display the original image
        IplImage* img = cvLoadImage("C:/MyPic.jpg");
        cvNamedWindow("MyWindow");
        cvShowImage("MyWindow", img);

        //dilate and display the dilated image
        cvDilate(img, img, 0, 2);
        cvNamedWindow("Dilated");
        cvShowImage("Dilated", img);

        cvWaitKey(0);
      
        //cleaning up
        cvDestroyWindow("MyWindow");
        cvDestroyWindow("Dilated");
        cvReleaseImage(&img);
      
        return 0;
}

/////////////////////////////////////////////////////////////////////////////////////// 

You can download this OpenCV visual c++ project from here

Dilated Image

New OpenCV functions which are not found earlier are explained here 
  • cvDilate(img, img, 0, 2)
The 1st parameter is the source image.
The 2nd parameter is the destination image which is to be the dilated image.
Here the 3rd parameter is the structuring element used for dilation. If it is 0, a 3×3 rectangular structuring element is used. 
The 4th parameter is the number of times, dilation is applied.
This function can process images in place. That means same variable can be used for the 1st and 2nd parameters.


Inverting 

Inverting an image is like taking the negative of an image.

///////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <cv.h>
#include <highgui.h>

int main()
{
        //display the original image
        IplImage* img = cvLoadImage("C:/MyPic.jpg");
        cvNamedWindow("MyWindow");
        cvShowImage("MyWindow", img);

        //invert and display the inverted image
        cvNot(img, img);
        cvNamedWindow("Inverted");
        cvShowImage("Inverted", img);

        cvWaitKey(0);
     
        //cleaning up
        cvDestroyWindow("MyWindow");
        cvDestroyWindow("Inverted");
        cvReleaseImage(&img);
     
        return 0;
}

///////////////////////////////////////////////////////////////////////////////////////

You can download this OpenCV visual c++ project from here

Inverted Image

 New OpenCV functions which are not found earlier are explained here
  • cvNot(img, img)
This function inverts every bit in every element of the image in the 1st parameter and places the result in the image in the 2nd parameter.
This function can process images in place. That means same variable can be used for the 1st and 2nd parameters.

e.g - For a 8 bit image, the value 0 will be mapped to (255-0)=255
                                        the value 46 will be mapped to (255-46)=209

        For a 16 bit image, the value 0 will be mapped to (65535-0)=65535
                                   the value 46 will be mapped to (65535-46)=65489