最近在学习c++版本的opencv,之前用openmv的ide自带了一个阈值编辑器,就想能不能用opencv复刻,正好也在做rm的目标追踪
先看效果
opencv制作简易RGB阈值编辑器
(途中橙子在res窗口为白色)
通过拖动滑块,可以分别调整RGB三个通道的上限和下限,得到二值化图像(满足条件为白)
这两个窗口都是视频流,可以很清楚的调整被测物体的位置
源代码:
#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;
}
代码解析:
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++不行不太会用这个*/
这里着重说一下onChangeTrackBar函数,方便c++基础不好的同学理解
建立一个void函数这个函数的参数是固定死的,长这样
void myTrackbarCallback(int pos, void* userdata);
(函数名随意)
建立好之后,我们就可以通过读取pos的值来获得滑块的值,像这样:
void onChangeTrackBar_red_lower(int pos, void*) { red_lower_pos = pos; }
然后把这个函数的函数名传入createTrackbar里,像这样:
createTrackbar("red_lower_pos", "capture", &red_lower_pos, 255,onChangeTrackBar_red_lower);
这样子就能通过滑块给任意变量赋值了。
还有createTrackbar生成完滑块后,生成的窗口跟视频流没关系了,会在每次滑块变动时候调用onChangeTrackBar,这里相当于一个事件
所以createTrackbar只要调用一次就行了,每次循环调用的话会不断刷新,卡死
之后就是使用inRange函数生成二值化之后的图像了,关于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类*/
然后把得到的dst imshow就可以了
代码量不多,我看很多教程用的是QT,感觉还挺麻烦