OpenCV使用trackBar
一、学习目标
- 了解并学会使用trackBar
- 应用trackBar实例调整图像的对比度和亮度
二、了解trackBar
在图像处理的教程中,我们经常会涉及到某个参数的调整,从而使图像算法具有不同的效果,调参是图像处理中很重要的一门艺术。
为了更方便地和用户进行交互,使得参数的调整和结果的显示更为灵活,OpenCV提供了trackBar这个控件来完成,它类似于窗体应用上的滑块,拖动滑块到不同值,则响应不同的操作。
为了更好地使用trackBar,我们需要熟悉以下两个函数。
- void cv::namedWindow
- int cv::createTrackbar
1、void cv::namedWindow 介绍
在之前的教程中,我们已经使用过namedWindow函数,这儿进行一个详细地介绍。通常情况下我们只是为了显示图像的话则不需要调用namedWindow函数提前建立窗体,但要使用creatBar时,需要指定窗体的名称,则我们要提前建立好对应名称的窗体实例。
namedWindow函数的原型为:
void cv::namedWindow(const String & winname,
int flags = WINDOW_AUTOSIZE)
- 参数 winname:用于指定窗体的名称
- 参数 flags:窗体的flag。枚举自cv::WindowFlags
该函数的作用是创建一个名为winname的窗体,可以用作图像和轨迹条的占位符。创建的窗体通过它们的名称来引用。如果已经存在同名窗体,则该函数不执行任何操作。可以调用cv::destroyWindow或cv::destroyAllWindows来关闭窗口并取消分配任何相关的内存。对于一个简单的程序,实际上不必调用这些函数,因为应用程序的所有资源和窗口都会在退出时由操作系统自动关闭。
对于 flags参数,其取值见下表:
参数取值 | 取值说明 |
---|---|
WINDOW_NORMAL | 用户可以调整窗口的大小(没有限制)/也可以使用切换全屏窗口到正常大小 |
WINDOW_AUTOSIZE | 用户不能调整窗口的大小,大小受所显示图像的限制 |
WINDOW_OPENGL | 窗体支持opengl |
WINDOW_FULLSCREEN | 将窗口更改为全屏 |
WINDOW_FREERATIO | 图像尽可能多地展开(没有宽高比例限制),即与图像尺寸和显示器分辨率相关 |
WINDOW_KEEPRATIO | 保持图像的宽高比例 |
WINDOW_GUI_EXPANDED | 状态栏和工具栏 |
WINDOW_GUI_NORMAL | 老fashious方式 |
其中我们通常使用WINDOW_NORMAL 和 WINDOW_AUTOSIZE这两个值,默认为WINDOW_AUTOSIZE。
2、int cv::createTrackbar函数介绍
int cv::createTrackbar函数原型为:
int cv::createTrackbar (const String & trackbarname,
const String & winname,
int * value,
int count,
TrackbarCallback onChange = 0,
void * userdata = 0)
- 参数 trackbarname:创建的轨迹条的名称
- 参数 winname:将被用于创建trackbar的父窗口的名称,上一步namedWindow函数创建
- 参数 value: 可选指针,指向一个整型变量,其值反映滑块的初始位置。在创建时,滑块的位置由这个变量定义
- 参数 count:滑块的最大位置,最小的位置总是0
- 参数 onChange:函数指针,指向每次滑动块改变位置时调用的函数。这个函数的原型应该是void Foo(int,void*),其中第一个参数是trackbar的当前位置,第二个参数是用户数据(参见下一个参数)。如果回调函数是空指针,则不调用回调函数,只更新值
- 参数 userdata:按原样传递给回调函数的用户数据,有了它就可以在不使用全局变量的情况下处理trackbar事件
函数createTrackbar使用指定的名称和范围创建一个trackbar(滑块或范围控件),分配一个变量值作为与trackbar同步的位置,并指定回调函数onChange在trackbar位置改变时被调用。创建的轨迹条显示在指定的窗口名中。
3、cv::setTrackbarPos函数介绍
setTrackbarPos函数原型为:
void cv::setTrackbarPos (const String & trackbarname,
const String & winname,
int pos)
- 参数 trackbarname:需要设置trackbar的名称,与创建的名称相对应
- 参数 winname:trackbar所在窗体的名称
- 参数 pos:设置该trackbar的值
该函数设置指定轨迹条在指定窗口中的位置。与此对应,可以调用cv::getTrackbarPos函数获取指定窗口指定trackbar的值。
三、使用实例(调整图像对比度和亮度)
调整图像对比度和亮度的笔记见我的上一节笔记:调整图像对比度和亮度
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// 提前声明三个回调函数
void onChangedConvertToAlpha(int value, void* data);
void onChangedConvertToBeta(int value, void* data);
void onChangedConvertToGama(int value, void* data);
int main(int argc, char** argv)
{
// 读取图像,判断是否读入成功
string fileName = samples::findFile("O:\\优快云\\7.jpg");
Mat src = imread(fileName, IMREAD_COLOR);
if (src.empty())
{
fprintf(stderr, "failed to load image: %s\n", fileName);
system("pause");
return EXIT_FAILURE;
}
int alpha = 10;
int beta = 0;
int gama = 10;
// 创建三个trackBar 在窗体demo上
namedWindow("demo", WINDOW_AUTOSIZE);
createTrackbar("alpha", "demo", &alpha, 30, onChangedConvertToAlpha, (void*)&src);
createTrackbar("beta", "demo", &beta, 100, onChangedConvertToBeta, (void*)&src);
createTrackbar("gama", "demo", &gama, 20, onChangedConvertToGama, (void*)&src);
// 显示地调用一次回调函数,显示默认值
onChangedConvertToAlpha(alpha, (void*)&src);
system("pause");
return EXIT_SUCCESS;
}
// 当改变alpha值时的响应函数
void onChangedConvertToAlpha(int value, void* data)
{
Mat src = (*(Mat*)data).clone();
Mat dst = Mat::zeros(src.size(), src.type());
int beta = getTrackbarPos("beta", "demo");
src.convertTo(dst, -1, (double)value / 10, beta);
setTrackbarPos("gama", "demo", 10);
imshow("demo", dst);
waitKey(0);
}
// 当改变beta值时的响应函数
void onChangedConvertToBeta(int value, void* data)
{
Mat src = (*(Mat*)data).clone();
Mat dst = Mat::zeros(src.size(), src.type());
int alpha = getTrackbarPos("alpha", "demo");
src.convertTo(dst, -1, (double)alpha / 10.0, value);
setTrackbarPos("gama", "demo", 10);
imshow("demo", dst);
waitKey(0);
}
// 当改变gama值时的响应函数
void onChangedConvertToGama(int value, void* data)
{
Mat lookUpTable(1, 256, CV_8U);
uchar* p = lookUpTable.ptr();
double gama = value / 10.0;
for (int i = 0; i < 256; ++i)
p[i] = saturate_cast<uchar>(pow(i / 255.0, gama) * 255.0);
Mat src = (*(Mat*)data).clone();
Mat dst = Mat::zeros(src.size(), src.type());
LUT(src, lookUpTable, dst);
imshow("demo", dst);
waitKey(0);
}