首页 > 编程笔记 > C++笔记 阅读:16

OpenCV滑动条事件详解(附带实例)

在 OpenCV 中,滑动条设计的主要目的是在视频播放帧中选择特定帧,它在调节图像参数时也会经常用到。在使用滑动条前,需要给滑动条赋予一个名字(通常是一个字符串),接下来将直接通过这个名字进行引用。

创建滑动条的函数是 createTrackbar(),该函数声明如下:
int cv::createTrackbar (const String & trackbarname, const String & winname, int * value, int count, TrackbarCallback onChange = 0,  void *userdata = 0);
参数说明如下:
回调函数类型 TrackbarCallback 的定义如下:
typedef void(* cv::TrackbarCallback) (int pos, void *userdata);

这个回调函数不是必需的,如果直接赋值为NULL,就没有回调函数,移动滑动按钮的唯一响应就是 createTrackbar 的参数 value 指向的变量值的变化。

除了创建滑动条的函数外,OpenCV 还提供了函数 getTrackbarPos(用于获取滑动块的位置)和 setTrackbarPos(用于设置滑动条的位置)。函数 getTrackbarPos 声明如下:
int cv::getTrackbarPos (const string& trackName, const string& windowName);
其中参数 trackName 是滑动条的名称,windowName 是滑动条将要添加到父窗口的名称。函数返回滑动块的当前位置。

函数 setTrackbarPos 声明如下:
void cv::setTrackbarPos(const string &trackName, const string& windowName, int pos);
其中参数 trackName 表示滑动条的名称,windowName 是滑动条将要添加到父窗口的名称,pos 表示要设置的滑动块位置。

下面来看一个专业的例子,利用滑动块调节参数。

【实例】利用滑动块控制腐蚀和膨胀。
1) 打开 Qt Creator,新建一个控制台工程,工程名是 test。

2) 在 IDE 中打开 main.cpp,输入如下代码:
#include <opencv2/opencv.hpp>
using namespace cv;

#include <iostream>
using namespace std;

Mat src, erosion_dst, dilation_dst;
int erosion_elem  = 0;
int erosion_size  = 0;
int dilation_elem = 0;
int dilation_size = 0;

const int max_elem        = 2;
const int max_kernel_size = 21;

void Erosion(int, void*);
void Dilation(int, void*);

int main(int argc, char** argv)
{
    // 读取原图
    src = imread("ter.jpg", IMREAD_COLOR);
    if (src.empty())
    {
        cout << "Could not open or find the image!" << endl;
        return -1;
    }

    // 创建窗口:腐蚀演示
    namedWindow("Erosion Demo", WINDOW_AUTOSIZE);
    // 创建窗口:膨胀演示
    namedWindow("Dilation Demo", WINDOW_AUTOSIZE);
    moveWindow("Dilation Demo", src.cols, 0);

    // 创建轨迹条:选择结构元素类型(矩形/十字/椭圆)
    createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse",
                   "Erosion Demo",
                   &erosion_elem, max_elem,
                   Erosion);

    // 创建轨迹条:设置结构元素大小(2n+1)
    createTrackbar("Kernel size:\n 2n + 1",
                   "Erosion Demo",
                   &erosion_size, max_kernel_size,
                   Erosion);

    // 膨胀窗口对应轨迹条
    createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse",
                   "Dilation Demo",
                   &dilation_elem, max_elem,
                   Dilation);

    createTrackbar("Kernel size:\n 2n + 1",
                   "Dilation Demo",
                   &dilation_size, max_kernel_size,
                   Dilation);

    // 首次执行一次以显示初始结果
    Erosion(0, 0);
    Dilation(0, 0);

    waitKey(0);
    return 0;
}

// 腐蚀回调函数
void Erosion(int, void*)
{
    int erosion_type = 0;
    if (erosion_elem == 0)
        erosion_type = MORPH_RECT;
    else if (erosion_elem == 1)
        erosion_type = MORPH_CROSS;
    else if (erosion_elem == 2)
        erosion_type = MORPH_ELLIPSE;

    Mat element = getStructuringElement(
        erosion_type,
        Size(2 * erosion_size + 1, 2 * erosion_size + 1),
        Point(erosion_size, erosion_size));

    erode(src, erosion_dst, element);
    imshow("Erosion Demo", erosion_dst);
}

// 膨胀回调函数
void Dilation(int, void*)
{
    int dilation_type = 0;
    if (dilation_elem == 0)
        dilation_type = MORPH_RECT;
    else if (dilation_elem == 1)
        dilation_type = MORPH_CROSS;
    else if (dilation_elem == 2)
        dilation_type = MORPH_ELLIPSE;

    Mat element = getStructuringElement(
        dilation_type,
        Size(2 * dilation_size + 1, 2 * dilation_size + 1),
        Point(dilation_size, dilation_size));

    dilate(src, dilation_dst, element);
    imshow("Dilation Demo", dilation_dst);
}
在上述代码中,首先读取 ter.jpg,然后利用函数 namedWindow 创建两个窗口,接着利用函数 createTrackbar 创建 4 个滑动条,每个窗口上有两个滑动条。

Erosion 和 Dilation 都是滑动条的回调函数,用于响应用户的滑动按钮事件。函数 erode 和 dilate 分别是 OpenCV 中腐蚀和膨胀图像的函数。

3) 保存工程并运行,结果如下图所示:

相关文章