Opencv makes a simple RGB threshold editor (only use createTrackbar(), no QT)

Recently, I am learning the C++ version of opencv. The IDE I used to use openmv before came with a threshold editor. I was wondering if I could use opencv to reproduce it. I happened to be doing target tracking for rm.

Look at the effect first

Opencv creates a simple RGB threshold editor

 (Oranges on the way are white in the res window)

By dragging the slider, you can adjust the upper and lower limits of the three RGB channels respectively to obtain a binary image (white if the conditions are met)

Both windows are video streams, and the position of the measured object can be clearly adjusted.

source code:

#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
/*三种颜色的上限和下限6个值*/
int red_lower_pos = 0;
int green_lower_pos = 0;
int blue_lower_pos = 0;
int red_upper_pos = 255;
int green_upper_pos = 255;
int blue_upper_pos = 255;
/*滑块控件函数,pos是滑动的值,赋值给颜色值*/
void onChangeTrackBar_red_lower(int pos, void*) { red_lower_pos = pos; }
void onChangeTrackBar_red_upper(int pos, void*) { red_upper_pos = pos; }
void onChangeTrackBar_green_lower(int pos, void*) { green_lower_pos = pos; }
void onChangeTrackBar_green_upper(int pos, void*) { green_upper_pos = pos; }
void onChangeTrackBar_blue_lower(int pos, void*) { blue_lower_pos = pos; }
void onChangeTrackBar_blue_upper(int pos, void*) { blue_upper_pos = pos; }
int main()
{
    VideoCapture capture(0);
    bool flag = true;
    //标志位,目的是让创建滑块的函数只运行一次
    
    for (;;) {
        Mat frame,res;
        capture >> frame;
        namedWindow("capture");
        imshow("capture", frame);
        if (flag) {
            /*创建滑块*/
            createTrackbar("red_lower_pos", "capture", &red_lower_pos, 255,onChangeTrackBar_red_lower);
            createTrackbar("red_upper_pos", "capture", &red_upper_pos, 255,onChangeTrackBar_red_upper);
            createTrackbar("green_lower_pos", "capture", &green_lower_pos, 255, onChangeTrackBar_green_lower);
            createTrackbar("green_upper_pos", "capture", &green_upper_pos, 255, onChangeTrackBar_green_upper);
            createTrackbar("blue_lower_pos", "capture", &blue_lower_pos, 255, onChangeTrackBar_blue_lower);
            createTrackbar("blue_upper_pos", "capture", &blue_upper_pos, 255, onChangeTrackBar_blue_upper);
            flag = false;
        }
        inRange(frame, Scalar(blue_lower_pos, green_lower_pos, red_lower_pos), Scalar(blue_upper_pos, green_upper_pos, red_upper_pos), res);
        //通过inRange函数生成阈值筛选二值化后的图像
        imshow("res", res);
        if (waitKey(20) == 'q')
            break;
    }
    destroyAllWindows();

    return 0;
}

Code analysis:

CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,
                              int* value, int count,
                              TrackbarCallback onChange = 0,
                              void* userdata = 0);
/*trackbarname:滑块命名*/
/*winname:     窗口名称*/
/*value:这是一个指针,可以理解为滑块的初始位置*/
/*count:       滑块长度*/
/*TrackbarCallback onChange:这是一个函数
使用时需要建立一个函数onChangeTrackBar,在这个函数里获得pos的值*/
/*userdata:可传入任意类型指针,哥们c++不行不太会用这个*/

Here we focus on the onChangeTrackBar function to facilitate understanding by students with poor C++ foundation.

Create a void function. The parameters of this function are fixed. It looks like this.

void myTrackbarCallback(int pos, void* userdata);

(Function name is arbitrary)

After it is established, we can get the value of the slider by reading the value of pos, like this:

void onChangeTrackBar_red_lower(int pos, void*) { red_lower_pos = pos; }

 Then pass the function name of this function into createTrackbar, like this:

 createTrackbar("red_lower_pos", "capture", &red_lower_pos, 255,onChangeTrackBar_red_lower);

In this way, you can assign a value to any variable through the slider.

Also, after createTrackbar generates the slider, the generated window has nothing to do with the video stream. onChangeTrackBar will be called every time the slider changes, which is equivalent to an event.

So createTrackbar only needs to be called once. Each time it is called in a loop, it will be continuously refreshed and stuck.

Then use the inRange function to generate the binarized image. Regarding inRange:

CV_EXPORTS_W void inRange(InputArray src, InputArray lowerb,
                          InputArray upperb, OutputArray dst);
/*src:输入,为Mat类*/
/*lowerb:RGB下限,为Scalar(b,g,r)*/
/*upperb:RGB上限,为Scalar(b,g,r)*/
/*dst:输出,为Mat类*/

 Then just imshow the obtained dst

The amount of code is not much. I have seen many tutorials using QT, which seems quite troublesome.

Guess you like

Origin blog.csdn.net/qq_38830492/article/details/128637764