Article link: http://blog.csdn.net/poem_qianmo/article/details/21176257
5: Off color channel & multi-channel image mixing
In order to better observe the characteristics of some image materials, sometimes it is necessary to display and adjust the components of three RGB color channels respectively. Through the split and merge methods of OpenCV, it is very convenient to achieve the goal.
split function
There are two prototypes in C + +:
C++: void split(const Mat& src, Mat*mvbegin); C++: void split(InputArray m,OutputArrayOfArrays mv);
About variables:
The first parameter, m of InputArray type or src of const Mat & type, fills in the multi-channel array we need to separate.
The second parameter, mv of OutputArrayOfArrays type, is the output array of the filler function or the vector container of the output. (about the introduction of OutputArrayOfArrays, in the original)
split function splits multi-channel array into independent single channel array, as shown in the formula:
Example:
Mat srcImage; Mat imageROI; vector<Mat> channels; srcImage= cv::imread("dota.jpg"); // Convert a 3-channel image to 3 single channel images split(srcImage,channels);//Separate color channels imageROI=channels.at(0); addWeighted(imageROI(Rect(385,250,logoImage.cols,logoImage.rows)),1.0, logoImage,0.5,0.,imageROI(Rect(385,250,logoImage.cols,logoImage.rows))); merge(channels,srcImage4); namedWindow("sample"); imshow("sample",srcImage);
merge function
The function of the merge() function is the reverse operation of the split() function, which combines multiple arrays into a multi-channel array.
It combines these isolated single channel arrays into a multi-channel array by combining some given single channel arrays, thus creating a multi-channel array composed of multiple single channel arrays. It has two C + + based function prototypes:
C++: void merge(const Mat* mv, size_tcount, OutputArray dst) C++: void merge(InputArrayOfArrays mv,OutputArray dst)
- The first parameter, mv, is to fill in the input matrix to be merged or the array of vector containers. All the matrices in this mv parameter must have the same size and depth.
- The second parameter, count, represents the number of input matrices when mv is a blank C array, which must be greater than 1
- The third parameter, dst, the output matrix, has the same size and depth as mv[0], and the number of channels is the total number of channels in the matrix array.
Function resolution:
The function of merge is to merge some arrays into a multichannel array. For details of composition, each element in the output matrix will be a concatenation of the output array, where the element of the ith input array is considered mv[i]. c usually uses the Mat::at () method to access a channel, that is, channels.at(0).
Example:
vector<Mat> channels; Mat imageBlueChannel; Mat imageGreenChannel; Mat imageRedChannel; srcImage4= imread("dota.jpg"); // Convert a 3-channel image to 3 single channel images split(srcImage4,channels);//Separate color channels imageBlueChannel = channels.at(0); imageGreenChannel = channels.at(1); imageRedChannel = channels.at(2);
The above code first makes the relevant type declaration, then converts the loaded 3-channel image into 3 single channel images, puts them into channels of vector type, and then makes reference and assignment.
According to the BGR color space of OpenCV (blue, Green, Red, blue, Green and Red), where channels.at(0) indicates that the blue component in channels is extracted by reference, channels.at(1) indicates that the Green component in channels is extracted by reference, and channels.at(2) indicates that the Red component in channels is extracted by reference.
//-----------------------------------[procedure description]---------------------------------------------- // Program name: [OpenCV Tutorial 4] separate color channel & multi-channel image mixing matching source code // VS2010 OpenCV version: 2.4.8 // Create by light ink, March 13, 2014 // Source of picture material: dota2 original painting dota2 logo // Light ink micro blog: @ light ink cloud //------------------------------------------------------------------------------------------------ //-----------------------------------[header contains]--------------------------------------- // Description: contains the header files that the program depends on //---------------------------------------------------------------------------------------------- #include <cv.h> #include <highgui.h> #include <iostream> #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> //The above two function libraries contain the basic functions such as imread, which are omitted from the original code of maoxingda. //-----------------------------------Namespace declaration part--------------------------------------- // Description: contains the namespace used by the program //----------------------------------------------------------------------------------------------- using namespace cv; using namespace std; //-----------------------------------Global function declaration part-------------------------------------- // Description: global function declaration //----------------------------------------------------------------------------------------------- bool MultiChannelBlending(); //-----------------------------------[main() function]-------------------------------------------- // Description: the entry function of the console application. Our program starts here //----------------------------------------------------------------------------------------------- int main( ) { system("color5E"); if(MultiChannelBlending()) { cout<<endl<<"Uh huh. All right, we've got the mixed value image you need~"; } waitKey(0); return 0; } //-----------------------------MultiChannelBlending() function-------------------------------- // Description: implementation function of multi-channel mixing //----------------------------------------------------------------------------------------------- bool MultiChannelBlending() { //[0] define related variables Mat srcImage; Mat logoImage; vector<Mat>channels; Mat imageBlueChannel; //=================[blue channel part]================= // Description: multichannel mix blue component section //============================================ //[1] Read in picture logoImage=imread("dota_logo.jpg",0); srcImage=imread("girl.jpg"); if(!logoImage.data ) { printf("Oh,no,read logoImage error~!\n"); return false; } if(!srcImage.data ) { printf("Oh,no,read srcImage error~!\n"); return false; } //[2] Convert a 3-channel image to 3 single channel images split(srcImage,channels);//Separate color channels //[3] Return the blue channel reference of the original image to imageBlueChannel. Note that it is a reference, equivalent to the equivalence of the two. Modify one and the other to change imageBlueChannel=channels.at(0); //[4] Weight an area at the bottom right of the (500250) coordinate of the blue channel of the original image and the logo image, and save the mixed results to the image blue channel addWeighted(imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0, logoImage,0.5,0,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows))); //[5] Recombine three single channels into one three channel merge(channels,srcImage); //[6] Show renderings namedWindow("<1>Game original painting+logo Blue channel by Light ink"); imshow("<1>Game original painting+logo Blue channel by Light ink",srcImage); //=================[green channel part]================= // Description: multichannel mix green component section //============================================ //[0] define related variables Mat imageGreenChannel; //[1] Reread picture logoImage=imread("dota_logo.jpg",0); srcImage=imread("girl"); if(!logoImage.data ) { printf("Oh,no,read logoImage error~!\n"); return false; } if(!srcImage.data ) { printf("Oh,no,read srcImage error~!\n"); return false; } //[2] Convert a three channel image to three single channel images split(srcImage,channels);//Separate color channels //[3] Return the reference of the green channel of the original image to imageBlueChannel. Note that the reference is equivalent to the two. Modify one and the other to change imageGreenChannel=channels.at(1); //[4] The area at the bottom right of the (500250) coordinate of the green channel of the original image and the logo image are weighted, and the resulting mixing results are saved in the imagegreen channel addWeighted(imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0, logoImage,0.5,0.,imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows))); //[5] Recombine three independent single channels into one three channel merge(channels,srcImage); //[6] Show renderings namedWindow("<2>Game original painting+logo Easy access by Light ink"); imshow("<2>Game original painting+logo Easy access by Light ink",srcImage); //=================[red channel part]================= // Description: multichannel mix red component section //============================================ //[0] define related variables Mat imageRedChannel; //[1] Reread picture logoImage=imread("dota_logo.jpg",0); srcImage=imread("girl.jpg"); if(!logoImage.data ) { printf("Oh,no,read logoImage error~!\n"); return false; } if(!srcImage.data ) { printf("Oh,no,read srcImage error~!\n"); return false; } //[2] Convert a three channel image to three single channel images split(srcImage,channels);//Separate color channels //[3] Return the red channel reference of the original image to imageBlueChannel. Note that it is a reference, equivalent to the equivalence of the two. Modify one and the other to change imageRedChannel=channels.at(2); //[4] Weight an area at the bottom right of the (500250) coordinate of the red channel of the original image and the logo image, and save the mixed results to the imageRedChannel addWeighted(imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0, logoImage,0.5,0.,imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows))); //[5] Recombine three independent single channels into one three channel merge(channels,srcImage); //[6] Show renderings namedWindow("<3>Game original painting+logo the red channel by Light ink"); imshow("<3>Game original painting+logo the red channel by Light ink",srcImage); return true; }
Operation effect:
6: Create trackbar & image contrast, brightness value adjustment
Original link: https://blog.csdn.net/poem_qianmo/article/details/21479533
In this section, learn how to use the createTrackbar function to create and use track bars in OpenCV, as well as the dynamic adjustment of image contrast and brightness values.
First of all, the function createTrackbar in the new version of OpenCV2.0 is explained in detail, and an example of detailed annotation is given.
Then it explains the details of image contrast and brightness value adjustment, and finally gives a program source code which uses createTrackbar function to create track bar to assist image contrast and brightness value adjustment.
The creation and use of Trackbar in OpenCV
<1> Create track bar -- detailed explanation of createTrackbar function
createTrackbar is a function we will often use in the future. It creates a track bar that can adjust the value, and attaches the track bar to the specified window. It is very convenient to use. First of all, you should remember that it is often used with a callback function. Let's take a look at his function prototype:
C++: int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
- The first parameter, const string & type trackbarname, represents the name of the track bar, which is used to represent the track bar we created.
- The second parameter, const string & type winname, is to fill in the name of the window, indicating which window this track bar will be attached to, that is, a window name corresponding to namedWindow() when creating the window.
- The third parameter, value of type int *, a pointer to integer, indicates the position of the slider. At the time of creation, the initial position of the slider is the current value of the variable.
- The fourth parameter, count of type int, represents the value of the maximum position that the slider can reach. PS: the value of the minimum position of the slider is always 0.
- The fifth parameter, onChange of TrackbarCallback type, first notice that it has a default value of 0. This is a pointer to the callback function, which will call back every time the position of the slider changes. And the prototype of this function must be void XXXX(int,void *); the first parameter is the position of the track bar, and the second parameter is the user data (see the sixth parameter below). If the callback is a NULL pointer, it means there is no call to the callback function, and only the value of the third parameter changes.
- The sixth parameter, userdata of type void *, also has a default value of 0. This parameter is the data passed by the user to the callback function, which is used to process the track bar event. If the value parameter of the third parameter is a global variable, the userdata parameter can be ignored.
This createTrackbar function creates a Trackbar (Trackbar, or slider range control tool) with a specific name and range, and specifies a variable synchronized with the position of the Trackbar. And you need to specify the callback function onChange (the fifth parameter), which is called when the position of the track bar changes. And we know that the created track bar is displayed on the window represented by the specified winname (second parameter).
Example:
//Create track bar createTrackbar("Contrast:", "[Rendering window]",&g_nContrastValue, 300,ContrastAndBright );// G ﹣ ncontrastvalue is the global integer variable, and contractandbright is the function name of the callback function (that is, the pointer to the function address)
But give you a complete example. This is the official sample program of OpenCV, which demonstrates how to use track bar to control contour detection and filling. Light ink cloud will be modified, code concise and detailed notes, put out for you to digest and study. A more detailed explanation of contour detection will be provided later in the updated blog.
//-----------------------------------[header contains]--------------------------------------- // Description: contains the header files that the program depends on //---------------------------------------------------------------------------------------------- #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> //-----------------------------------Namespace declaration part--------------------------------------- // Description: contains the namespace used by the program //----------------------------------------------------------------------------------------------- using namespace cv; using namespace std; //-----------------------------------Global function declaration part-------------------------------------- // Description: global function declaration //----------------------------------------------------------------------------------------------- Mat img; int threshval = 160; //Corresponding value of track bar slider, given initial value 160 //-----------------------------[on ﹐ trackbar() function]------------------------------------ // Description: callback function of track bar //----------------------------------------------------------------------------------------------- static void on_trackbar(int, void*) { Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); //Defining points and vectors vector<vector<Point> > contours; vector<Vec4i> hierarchy; //Find contour findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); //Initialize dst Mat dst = Mat::zeros(img.size(), CV_8UC3); //Start processing if( !contours.empty() && !hierarchy.empty() ) { //Traverse all top-level contours, randomly generate color values and draw them to each connecting component int idx = 0; for( ; idx >= 0; idx = hierarchy[idx][0] ) { Scalar color( (rand()&255), (rand()&255), (rand()&255) ); //Draw a fill profile drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy ); } } //Display window imshow( "Connected Components", dst ); } //-----------------------------------[main() function]-------------------------------------------- // Description: the entry function of the console application. Our program starts here //----------------------------------------------------------------------------------------------- int main( ) { system("color 5F"); //Load Images img = imread("1.jpg", 0); if( !img.data ) { printf("Oh,no,read img Picture file error~! \n"); return -1; } //Display original graph namedWindow( "Image", 1 ); imshow( "Image", img ); //Create processing window namedWindow( "Connected Components", 1 ); //Create track bar createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar ); on_trackbar(threshval, 0);//Track bar callback function waitKey(0); return 0; }
In addition, the original official code can be found in the OpenCV path opencv_source_code/samples/cpp/connected_components.cpp.
Next, by the way, a function used with createTrackbar to get the position of the current track bar's gettrackbar POS function.
<2> Get the position of the current track bar -- getTrackbarPos function
This function is used to get the position of the current track bar and return.
C++: int getTrackbarPos(conststring& trackbarname, conststring& winname);
- The first parameter, const string & type trackbarname, represents the name of the track bar.
- The second parameter, const string & type winname, represents the name of the parent window of the track bar.
2, Theoretical basis for brightness and contrast adjustment
3, About accessing pixels in a picture
There are many ways to access the pixels in the picture for future project learning. At present, learn one:
To perform this operation, we need to access every pixel of the image. Because of the operation of GBR image, each pixel has three values (G, B, R), so we must access them separately (the image storage mode in PS:OpenCV is GBR). Here is a code snippet for accessing pixels. Three for loops solve the problem:
//Three for loops, execute the operation new_image(i,j) =a*image(i,j) + b for(int y = 0; y < image.rows; y++ ) { for(int x = 0; x < image.cols; x++ ) { for(int c = 0; c < 3; c++ ) { new_image.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContrastValue*0.01)*(image.at<Vec3b>(y,x)[c] ) + g_nBrightValue ); } } }
Let's explain it in three aspects:
- To access every pixel of an image, we use the following syntax: image.at(y,x)[c]
Where y is the row where the pixel is located, x is the column where the pixel is located, and c is one of R, G, B (corresponding to 0, 1, 2). - Because the result of our operation may be out of the range of pixel value (overflow), or it may be a non integer (if it is a floating-point number), we need to convert the result with saturate ﹐ cast to ensure that it is a valid value.
- Here a is the contrast. Generally, for the purpose of observation, the value of a is 0.0 to 3.0 floating-point value, but our track bar generally takes an integer value. So here we can set the nContrastValue parameter representing the contrast value to an integer between 0 and 300, and multiply it by a 0.01 in the final formula, so that 300 different values in the track bar can be achieved Change. So in the formula, we will see g nconrastvalue * 0.01 in saturate cast ((g nconrastvalue 0.01) (image. At (y, x) [C]) + G nbrightvalue).
4, Example program of image contrast and brightness value adjustment
This example program uses two track bars to control the contrast and brightness values respectively, which has certain playability.
//-----------------------------------[procedure description]---------------------------------------------- // Program name: [OpenCV Tutorial 4] create trackbar & image contrast, brightness value adjustment matching blog source code // VS2010 OpenCV version: 2.4.8 // Create by light ink, March 18, 2014 //------------------------------------------------------------------------------------------------ //-----------------------------------[header contains]--------------------------------------- // Description: contains the header files that the program depends on //---------------------------------------------------------------------------------------------- #include <opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include"opencv2/imgproc/imgproc.hpp" #include <iostream> //-----------------------------------Namespace declaration part--------------------------------------- // Description: contains the namespace used by the program //----------------------------------------------------------------------------------------------- using namespace std; using namespace cv; //-----------------------------------Global function declaration part-------------------------------------- // Description: global function declaration //----------------------------------------------------------------------------------------------- static void ContrastAndBright(int, void *); //-----------------------------------[global variable declaration part]-------------------------------------- // Description: global variable declaration //----------------------------------------------------------------------------------------------- int g_nContrastValue; //Contrast value int g_nBrightValue; //Luminance value Mat g_srcImage,g_dstImage; //-----------------------------------[main() function]-------------------------------------------- // Description: the entry function of the console application. Our program starts here //----------------------------------------------------------------------------------------------- int main( ) { //Change console foreground and background colors system("color5F"); //Read in the image provided by the user g_srcImage= imread( "pic1.jpg"); if(!g_srcImage.data ) { printf("Oh,no,read g_srcImage Picture error~!\n"); return false; } g_dstImage= Mat::zeros( g_srcImage.size(), g_srcImage.type() ); //Set the initial value of contrast and brightness g_nContrastValue=80; g_nBrightValue=80; //create a window namedWindow("[Rendering window]", 1); //Create track bar createTrackbar("Contrast:", "[Rendering window]",&g_nContrastValue,300,ContrastAndBright ); createTrackbar("Brightness:","[Rendering window]",&g_nBrightValue,200,ContrastAndBright ); //Call callback function ContrastAndBright(g_nContrastValue,0); ContrastAndBright(g_nBrightValue,0); //Output some help information cout<<endl<<"\t Uh huh. OK, please adjust the scroll bar to observe the image effect~\n\n" <<"\t Press " q"Key, program exits~!\n" <<"\n\n\t\t\t\tby Light ink"; //When the "q" key is pressed, the program exits while(char(waitKey(1)) != 'q') {} return0; } //-----------------------------[contractandbright() function]------------------------------------ // Description: callback function for changing image contrast and brightness values //----------------------------------------------------------------------------------------------- static void ContrastAndBright(int, void *) { //create a window namedWindow("[Original image window]", 1); //Three for loops, performing the operation g ﹣ dstimage (I, J) = a * g ﹣ srcimage (I, J) + B for(int y = 0; y < g_srcImage.rows; y++ ) { for(int x = 0; x < g_srcImage.cols; x++ ) { for(int c = 0; c < 3; c++ ) { g_dstImage.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContrastValue*0.01)*(g_srcImage.at<Vec3b>(y,x)[c] ) + g_nBrightValue ); } } } //Display image imshow("[Original image window]", g_srcImage); imshow("[Rendering window]", g_dstImage); }