Thursday 26 November 2015

Image Blender using addWeighted function

The purpose of blending or mixing two images linearly can be achieved by addWeighted function provided by OpenCV.
The syntax of OpenCV addWeighted function goes as:

C++: void addWeighted(src1, alpha, src2, beta,  gamma, dst, int dtype=-1)

Parameters:
src1 – first input array.
alpha – weight of the first array elements.
src2 – second input array of the same size and channel number as src1.
beta – weight of the second array elements.
dst – output array that has the same size and number of channels as the input arrays.
gamma – scalar added to each sum.
dtype – optional depth of the output array; when both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth().

Linear Blending means adding two images pixel by pixel.
Thus we can use the function
c(x)=(1-α)*a(x)+α*b(x)
where a(x) and b(x) are the two source images.
c(x) is the resultant blended image.

addWeighted( src1, alpha, src2, beta, 0.0, dst);
Thus addWeighted function performs the same thing as
dst = α*src1+β*src2+γ
Here γ=0  and   β=1-α

Why do we choose β=1-α?
Since we are having images of  8 bits.
Thus pixel value can range from 0 to 255.
Thus while  adding two images the pixel value of the resultant image should lie between 0 to 255.
Hence if we multiply a particular co-ordinate of an image by α the the other image's respective co-ordinate need to be 1-α.
Thus the sum would be α+1-α=1.
Thus the pixel value will range between 0-255.
E.g
Consider that pixel value of src1 at particular co-ordinate is 230.
And that of src2 is 215.
Now, we need to blend these two images linearly, for that we need to blend the pixel values of the two images.
Thus if we choose α=0.5 and β=0.7
The pixel value at that particular co-rodinate would be
c(x)=α*a(x)+β*b(x)
      =0.5*230+0.7*215
      =265.5
Thus β value need to be less or equal to  that of 1-α.
Hence here we have chosen it equal to 1-α to be on the safer side.But it can be less than 1-α too.

The code for it goes as below:

// OpenCV Image Blending Tutorial using addWeighted function
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
 double alpha = 0.5; 
 double beta; 
 double input;

 Mat src1, src2, dst,src3;
 /// Read image ( same size, same type )
 src1 = imread("C:\\Users\\arjun\\Desktop\\green.jpg");
 src2 = imread("C:\\Users\\arjun\\Desktop\\blue.jpg");

 if( !src1.data ) { printf("Error loading src1 \n"); return -1; }
 if( !src2.data ) { printf("Error loading src2 \n"); return -1; }
 
 ///Comparing whether the two images are of same size or not
 int width1 , width2 , height1 , height2;
 width1 =src1.cols; 
 height1=src1.rows; 
 width2 =src2.cols; 
 height2=src2.rows; 
 
 if (width1!=width2 && height1!=height2)
 {
  printf("Error:Images must be of the same size \n");
  return -1;
 }
 /// Ask the user enter alpha
 std::cout<<" Simple Linear Blender "<<std::endl;
 std::cout<<"-----------------------"<<std::endl;
 std::cout<<"* Enter alpha [0-1]: ";
 std::cin>>input;

 /// We use the alpha provided by the user if it is between 0 and 1
 if( input >= 0.0 && input <= 1.0 )
   { 
    alpha = input;
   }

 beta = ( 1.0 - alpha );
 addWeighted( src1, alpha, src2, beta, 0.0, dst);

 /// Create Windows
 namedWindow("Linear Blend", 1);
 imshow( "Linear Blend", dst );

 namedWindow("Original Image1", 1);
 imshow( "Original Image1", src1 );

 namedWindow("Original Image2", 1);
 imshow( "Original Image2", src2 );
 waitKey(0);
 return 0;
}

The above code of blending two images linearly by using Trackbar is as shown below:
// OpenCV Image bleding Tutorial using addWeighted function and trackbar
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

double alpha; 
double beta;
const int blend_slider_max = 100;
int alpha_slider;
Mat src1, src2, dst,src3;

void blend_trackbar( int , void* )
{
 alpha = (double) alpha_slider/blend_slider_max;
 beta = (double)( 1.0 - alpha );
    addWeighted( src1, alpha, src2, beta, 0.0, dst);
    imshow( "Linear Blend", dst );
}

int main()
{
 // Read image ( same size, same type )
 src1 = imread("C:\\Users\\arjun\\Desktop\\opencv_image1.jpg");
 src2 = imread("C:\\Users\\arjun\\Desktop\\opencv_image2.jpg");

 if( !src1.data ) { printf("Error loading src1 \n"); return -1; }
 if( !src2.data ) { printf("Error loading src2 \n"); return -1; }
 
 ///Comparing whether the two images are of same size or not
 int width1 , width2 , height1 , height2;
 width1 =src1.cols; 
 height1=src1.rows; 
 width2 =src2.cols; 
 height2=src2.rows; 
 
 if (width1!=width2 && height1!=height2)
 {
  printf("Error:Images must be of the same size \n");
  return -1;
 }

 // Create Windows 
 namedWindow("Linear Blend",CV_WINDOW_AUTOSIZE); 
 createTrackbar( "Blending", "Linear Blend", &alpha_slider, blend_slider_max, blend_trackbar );
 blend_trackbar( alpha_slider, 0 );

 namedWindow("Original Image1", 1);
 imshow( "Original Image1", src1 );

 namedWindow("Original Image2", 1);
 imshow( "Original Image2", src2 );

 waitKey(0);
 return 0;
}


Input Image1:
opencv image1
Input Image2:
opencv image2

Blended Image Video by changing the position on the trackbar:



No comments:

Post a Comment