窗口交互操作

交互操作可以实现在程序运行过程中改变参数数值的作用

避免重复运行程序,节省时间,同时能够增强结果的对比效果

图像窗口滑动条createTrackbar()

OpenCV4提供了createTrackbar()函数实现在显示图像的窗口中创建滑动条

createTrackbar()函数原型:

int createTrackbar(const String& trackbarname,
                   const String& winname,
                   int* value,
                   int count,
                   TrackbarCallback onChange = 0,
                   void* userdata = 0
                   )
  • trackbarname:滑动条的名称
  • winname:创建滑动条窗口的名称
  • value:指向整数变量的指针,该指针指向的值反映滑块的位置,创建后,滑动位置由此变量定义
  • count:滑动条的最大值
  • onChange:每次滑块更改位置时要调用的函数的指针,函数原型为void Foo(int,void*);

    其中第一个参数是轨迹栏位置,第二个参数是用户数据,如果回调是NULL指针,则不会调用任何回调,而只是更新数值

  • userdata:传递给回调函数的可选参数

该函数能够在图像窗口上方创建一个从0开始的整数滑动条,滑动条默认只能输出整数,因此,如果需要小数,就需要进行后续处理

例如输出值/10得到含有一位小数的数据

该函数第一个参数是滑动条的名称,第二个参数是创建滑动条的图像窗口的名称,第三个参数是指向整数变量的指针

该指针指向的值反映滑块的位置,创建滑动条时,该参数确定了滑块的初始位置,滑动条创建完成后,指针指向的整数随滑块移动而改变

第四个参数是滑块条的最大取值,第五个参数是每次滑块更改位置时要调用的函数的指针,最后一个是传递给回调函数的void*类型数据

如果使用的第三个参数是全局变量,则可以不用修改最后一个参数,使用参数的默认值就可以

示例:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//为了能在被调用函数中使用,设置成全局
int value;
static void callBack(int,void*); //滑动条回调函数
Mat img1,img2;
int main()
{
    img1 = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg");
    if (img1.empty()) {
        cout << "Error" << endl;
        return -1;
    }
    namedWindow("滑动条改变图像亮度");
    imshow("滑动条改变图像亮度",img1);
    value = 100; //滑动条创建时的初始值
    //创建滑动条
    createTrackbar("亮度值百分比","滑动条改变图像亮度",&value,600,callBack,0);
    waitKey(0);
}
static void callBack(int,void*)
{
    float a = value/100.0;
    img2 = img1*a;
    imshow("滑动条改变图像亮度",img2);
}

鼠标响应setMouseCallback()

OpenCV4提供了鼠标响应相关函数setMouseCallback()函数

setMouseCallback()函数原型:

void setMouseCallback(const String& winname,
                      MouseCallback onMouse,
                      void * userdata = 0
                      )
  • winname:添加鼠标响应的窗口的名字
  • onMouse:鼠标响应的回调函数
  • userdata:传递给回调函数的可选参数

该函数能够为指定的图像窗口创建鼠标响应,第一个参数是需要创建鼠标响应的图像窗口的名字

第二个参数为鼠标响应的回调函数,该函数是鼠标状态发生改变时调用,是MouseCallback类型函数

最后一个参数是传递给回调函数的可选参数,一般情况下,使用默认值0即可

MouseCallback()回调函数原型:

typedef void(*cv::MouseCallback)(int event,
                                 int x,
                                 int y,
                                 int flags,
                                 void *userdata
                                 )
  • event:鼠标响应事件标志,参数为EVENT_*形式
  • x:鼠标指针在图像坐标系中的x坐标
  • y:鼠标指针在图像坐标系中的y坐标
  • flags:鼠标响应标志,参数为EVENT_FLAG_*形式
  • userdata:传递给回调函数的可选参数

MouseCallback类型的回调函数是一个无返回值的函数,函数名可以任意设置

最后一个参数是传递给回调函数的可选参数,一般情况下,使用void*默认即可

MouseCallback类型回调函数鼠标响应事件标志

标志参数 简记 含义
EVENT_MOUSEMOVE 0 表示鼠标指针在窗口上移动
EVENT_LBUTTONDOWN 1 表示按下鼠标左键
EVENT_RBUTTONDOWN 2 表示按下鼠标右键
EVENT_MBUTTONDOWN 3 表示按下鼠标中键
EVENT_LBUTTONUP 4 表示释放鼠标左键
EVENT_RBUTTONUP 5 表示释放鼠标右键
EVENT_MBUTTONUP 6 表示释放鼠标中键
EVENT_LBUTTONDBLCLK 7 表示双击鼠标左键
EVENT_RBUTTONDBLCLK 8 表示双击鼠标右键
EVENT_MBUTTONDBLCLK 9 表示双击鼠标中键
EVENT_MOUSEWHEEL 10 正值表示向前滚动,负值表示向后滚动
EVENT_MOUSEHWHEEL 11 正值表示向左滚动,负值表示向右滚动

MouseCallback类型回调函数鼠标响应标志

标志参数 简记 含义
EVENT_FLAG_LBUTTON 1 按住左键拖拽
EVENT_FLAG_RBUTTON 2 按住右键拖拽
EVENT_FLAG_MBUTTON 4 按住中键拖拽
EVENT_FLAG_CTRLKEY 8 按“Ctrl”键
EVENT_FLAG_SHIFTKEY 16 按“Shift”键
EVENT_FLAG_ALTKEY 32 按“Alt”键

鼠标响应就是当鼠标位于对应的图像窗口内时,时刻检测鼠标状态,当鼠标状态发生改变时,调用回调函数的判断逻辑选择相应的操作

示例程序:如果鼠标右键被按下,就会提示“点击鼠标左键才可以绘制轨迹”,若单击左键,就会输出当前鼠标的坐标

并将该点坐标定义为某段轨迹的起始位置。之后按住左键移动鼠标,会绘制鼠标的移动轨迹

该程序中提供了两种绘制轨迹的方式:

第一种是每次调用回调函数获得鼠标位置时更改周围图像像素值,但是由于回调函数有一定执行时间

当鼠标移动过快,就会出现断点

第二种是在前一时刻和当前时刻鼠标位置间绘制直线,可以避免因鼠标移动过快出现断点的问题

示例:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat img,imgPoint; //全局的图像
Point prePoint; //前一时刻鼠标的坐标,用于绘制直线

void mouse(int event,int x,int y,int flags, void*);
int main()
{
    img = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg");
    if (img.empty()) {
        cout << "Error" << endl;
        return -1;
    }
    img.copyTo(imgPoint);
    imshow("图像窗口1",img);
    imshow("图像窗口2",imgPoint);
    setMouseCallback("图像窗口1",mouse,0); //鼠标响应
    waitKey(0);
    return 0;
}
void mouse(int event,int x,int y,int flags, void*)
{

    if (event == EVENT_RBUTTONDOWN) //单击右键
    {
        cout << "点击鼠标左键才可以绘制轨迹" << endl;
    }
    if (event == EVENT_LBUTTONDOWN) //单击左键,输出坐标
    {
        prePoint = Point(x,y);
        cout << "轨迹起始坐标" << prePoint << endl;
    }
    if (flags == EVENT_FLAG_LBUTTON && event == EVENT_MOUSEMOVE ) //按住鼠标左键移动
    {
        //通过改变图像像素显示鼠标移动轨迹
        imgPoint.at<Vec3b>(y,x) = Vec3b(0,0,255);
        imgPoint.at<Vec3b>(y,x-1) = Vec3b(0,0,255);
        imgPoint.at<Vec3b>(y,x+1) = Vec3b(0,0,255);
        imgPoint.at<Vec3b>(y+1,x) = Vec3b(0,0,255);
        imgPoint.at<Vec3b>(y+1,x) = Vec3b(0,0,255);
        imshow("图像窗口2",imgPoint);
        //通过绘制直线显示鼠标移动轨迹
        Point pt(x,y);
        line(img,prePoint,pt,Scalar(0,0,255),2,5,0);
        prePoint = pt;
        imshow("图像窗口1",img);
    }
}

Opencv提供了直线函数line()

line()函数原型:

void line(Mat& img,
          Point pt1,
          Point pt2,
          const Scalar& color,
          int thickness=1,
          int lineType=8,
          int shift=0
          )
  • img: 要绘制线段的图像。
  • pt1: 线段的起点。
  • pt2: 线段的终点。
  • color: 线段的颜色,通过一个Scalar对象定义。
  • thickness: 线条的宽度。
  • lineType: 线段的类型。可以取值8, 4, 和CV_AA, 分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
  • shift: 坐标点小数点位数

results matching ""

    No results matching ""