Adding buttons to the user interface
In the previous sections, we learned how to create normal or Qt interfaces and interact with them using the mouse and sliders, but we can create different types of buttons too.
The types of buttons supported by OpenCV Qt are as follows:
- Push button
- Checkbox
- RadioBox
The buttons only appear in the control panel. The control panel is an independent window per program where we can attach buttons and trackbars. To show the control panel, we can push the last toolbar button, right-click in any part of the Qt window and select the Display properties window, or use the Ctrl + P shortcut. Let's create a basic sample with buttons. The code is extensive, and we are going to explain the main function first and later each callback separately so as to understand everything better. The following code shows us the main code function that generates the user interface:
Mat img; bool applyGray=false; bool applyBlur=false; bool applySobel=false; ... int main(int argc, const char** argv) { // Read images img= imread("../lena.jpg"); // Create windows namedWindow("Lena"); // create Buttons createButton("Blur", blurCallback, NULL, QT_CHECKBOX, 0); createButton("Gray",grayCallback,NULL,QT_RADIOBOX, 0); createButton("RGB",bgrCallback,NULL,QT_RADIOBOX, 1); createButton("Sobel",sobelCallback,NULL,QT_PUSH_BUTTON, 0); // wait app for a key to exit waitKey(0); // Destroy the windows destroyWindow("Lena"); return 0; }
We are going to apply thee types of filters: blur, a sobel filter, and a color conversion to gray. All these are optional and the user can choose each one using the buttons that we are going to create. Then, to get the status of each filter, we create three global Boolean variables:
bool applyGray=false; bool applyBlur=false; bool applySobel=false;
In the main function, after loading the image and creating the window, we have to use the createButton function to create each button.
There are three button types defined in OpenCV:
- QT_CHECKBOX
- QT_RADIOBOX
- QT_PUSH_BUTTON
Each button has five parameters with the following order:
- The button name
- A callback function
- A pointer to user variable data passed to callback
- The button type
- The default initialized state used for the checkbox and RadioBox button types
Then, we create a blur checkbox button, two radio buttons for color conversion, and a push button for a sobel filter, as you can see in the following code:
// create Buttons createButton("Blur", blurCallback, NULL, QT_CHECKBOX, 0); createButton("Gray",grayCallback,NULL,QT_RADIOBOX, 0); createButton("RGB",bgrCallback,NULL,QT_RADIOBOX, 1); createButton("Sobel",sobelCallback,NULL,QT_PUSH_BUTTON, 0);
These are the most important parts of the main function. We are going to explore the Callback functions. Each Callback changes its status variable to call another function called applyFilters in order to add the filters activated to the input image:
void grayCallback(int state, void* userData) { applyGray= true; applyFilters(); } void bgrCallback(int state, void* userData) { applyGray= false; applyFilters(); } void blurCallback(int state, void* userData) { applyBlur= (bool)state; applyFilters(); } void sobelCallback(int state, void* userData) { applySobel= !applySobel; applyFilters(); }
The applyFilters function checks the status variable for each filter:
void applyFilters(){ Mat result; img.copyTo(result); if(applyGray){ cvtColor(result, result, COLOR_BGR2GRAY); } if(applyBlur){ blur(result, result, Size(5,5)); } if(applySobel){ Sobel(result, result, CV_8U, 1, 1); } imshow("Lena", result); }
To change the color to gray, we use the cvtColor function which accepts three parameters: input image, output image, and the color conversion type.
The most useful color space conversions are as follows:
- RGB or BGR to gray (COLOR_RGB2GRAY, COLOR_BGR2GRAY)
- RGB or BGR to YcrCb (or YCC) (COLOR_RGB2YCrCb, COLOR_BGR2YCrCb)
- RGB or BGR to HSV (COLOR_RGB2HSV, COLOR_BGR2HSV)
- RGB or BGR to Luv (COLOR_RGB2Luv, COLOR_BGR2Luv)
- Gray to RGB or BGR (COLOR_GRAY2RGB, COLOR_GRAY2BGR)
We can see that the codes are easy to memorize.
The blur filter was described in the previous section, and finally, if the applySobel variable is true, we apply the sobel filter. The sobel filter is an image derivate obtained using the sobel operator, commonly used to detect edges. OpenCV allows us to generate different derivates with kernel size, but the most common is a 3x3 kernel to calculate the x derivates or y derivate.
The most important sobel parameters are the following:
- Input image
- Output image
- Output image depth (CV_8U, CV_16U, CV_32F, CV_64F)
- Order of the derivate x
- Order of the derivate y
- Kernel size (a value of 3 by default)
To generate a 3 x 3 kernel and a first x order derivate, we have to use the following parameters:
Sobel(input, output, CV_8U, 1, 0);
The following parameters are used for y order derivates:
Sobel(input, output, CV_8U, 0, 1);
In our example, we use the x and y derivate simultaneously, overwriting the input. The following snippet shows how to generate the x and y derivates simultaneously, adding 1 in the fourth and fifth parameters:
Sobel(result, result, CV_8U, 1, 1);
The result of applying x and y derivatives simultaneously looks like following image applied to the Lena picture: