鼠标事件
cv::waitKey()函数进行键值辅捉,下一个逻辑事件就是对鼠标事件进行“监听”和做出响应。
与键盘不同,鼠标事件使用更传统的回调函数函数机制来完成,这就意味着,我们必须先写好一个回调程序,
使得OpenCV在发生任何鼠标事件时都可以调用这个回调程序,当完成回调程序以后,需要在OpenCV中注册这个函数,
即告诉OpenCV这是一个正确的回调程序。
指向回调函数的指针是 cv::MouseCallback,定义回调函数的接口协议:
void your_mouse_callback
(
int event, //Event type
int x, //x-location of mouse event
int y, //y-location of mouse event
int flags, //More details on event
void* param //Parameters from cv::setMouseCallback()
);
第一个参数为鼠标事件类型,如下所示:
鼠标事件类型:
EVENT_MOUSEMOVE = 0, //!< indicates that the mouse pointer has moved over the window.
EVENT_LBUTTONDOWN = 1, //!< indicates that the left mouse button is pressed.
EVENT_RBUTTONDOWN = 2, //!< indicates that the right mouse button is pressed.
EVENT_MBUTTONDOWN = 3, //!< indicates that the middle mouse button is pressed.
EVENT_LBUTTONUP = 4, //!< indicates that left mouse button is released.
EVENT_RBUTTONUP = 5, //!< indicates that right mouse button is released.
EVENT_MBUTTONUP = 6, //!< indicates that middle mouse button is released.
EVENT_LBUTTONDBLCLK = 7, //!< indicates that left mouse button is double clicked.
EVENT_RBUTTONDBLCLK = 8, //!< indicates that right mouse button is double clicked.
EVENT_MBUTTONDBLCLK = 9, //!< indicates that middle mouse button is double clicked.
EVENT_MOUSEWHEEL = 10,//!< positive and negative values mean forward and backward scrolling, respectively.
EVENT_MOUSEHWHEEL = 11 //!< positive and negative values mean right and left scrolling, respectively.
第二个和第三个参数将被设置为鼠标事件的x坐标和y坐标,这里的坐标是图像上的像素坐标,是独立于窗口的
第四个参数是标志位,是一个bit位,每一个bit位都代表在事件发生时的不同条件。具体如下所示:
EVENT_FLAG_LBUTTON = 1, //!< indicates that the left mouse button is down.
EVENT_FLAG_RBUTTON = 2, //!< indicates that the right mouse button is down.
EVENT_FLAG_MBUTTON = 4, //!< indicates that the middle mouse button is down.
EVENT_FLAG_CTRLKEY = 8, //!< indicates that CTRL Key is pressed.
EVENT_FLAG_SHIFTKEY = 16,//!< indicates that SHIFT Key is pressed.
EVENT_FLAG_ALTKEY = 32 //!< indicates that ALT Key is pressed.
第五个参数是一个void*类型的指针,OpenCV可以用来传递额外的信息到任何类型的结构。
void cv::setMouseCallback
(
const string& windowName, //Handle used to identify window
cv::MouseCallback on_mouse, //Callback function
void* //Additional parameters for callback fn.
);
第一个参数,回调函数作用的窗口名称,只有事件在这个特定的窗口上时才能触发回调。
第二个参数,注册的回调函数。
第三个参数,可以在回调函数执行时给回调函数传递特定的信息。
#include<iostream>
#include<opencv2\highgui.hpp>
#include<opencv2\core.hpp>
#include<opencv2\imgproc.hpp>
void my_mouse_callback(int event, int x, int y, int flags, void*params);
cv::Rect box;
bool drawing_box = false;
void draw_box(cv::Mat& img, cv::Rect box)
{
cv::rectangle
(
img,
box.tl(),
box.br(),
cv::Scalar(0x00, 0x00, 0xff)
);
}
int main()
{
cv::Mat image(200, 200, CV_8UC3), tmp;
box = cv::Rect(-1, -1, 0, 0);
image = cv::Scalar::all(0);
cv::namedWindow("Box Example");
cv::setMouseCallback("Box Example", my_mouse_callback, (void*)&image);
for (;;)
{
image.copyTo(tmp);
cv::imshow("1", image);
//std::cout << drawing_box << std::endl;
if (drawing_box) draw_box(tmp, box);
cv::imshow("Box Example", tmp);
//cv::imshow("2", image);
cv::waitKey(33);
}
return 0;
}
void my_mouse_callback(int event, int x, int y, int flags, void*params)
{
cv::Mat& image = *(cv::Mat*)params;
switch (event)
{
//鼠标动
case cv::EVENT_MOUSEMOVE:
{
if (drawing_box)
{
box.width = x - box.x;
box.height = y - box.y;
}
break;
}
//左鼠标按下
case cv::EVENT_LBUTTONDOWN:
{
drawing_box = true;
box = cv::Rect(x, y, 0, 0);
break;
}
//左鼠标按下抬起
case cv::EVENT_LBUTTONUP:
{
drawing_box = false;
if (box.width < 0)
{
box.x += box.width;
box.width *= -1;
}
if (box.height < 0)
{
box.y += box.height;
box.height *= -1;
}
draw_box(image, box);
}
default:
break;
}
}
滑动条/滚动条 (slider/trackbar)
最初设计的目的就是在视频播放帧中选择特定帧。
在和父窗口使用时,需要给滑动条赋予一个特别的名字(通常是一个字符串),接下来将直接通过那个名字进行引用;
int cv::createTrackbar(
const string& trackbarName, // Handle used to identify trackbar
const string& windowName, // Handle used to identify window
int* value, // Slider position gets put here
int count, // Total counts for slider at far right
cv::TrackbarCallback onChange = NULL, // Callback function (option)
void* param = NULL // Addition params for callback fn
);
第一个参数是滑动条的名称,
第二个参数是滑动条将要添加到父窗口的名称,一旦滑动条创建好,它将被添加到窗口的顶部或底部。
滑动条不会挡住任何已经在窗口中的图像,只会让窗口变大,窗口的名将作为一个窗口的标记,至于滑动条上滑动钮的
的确切位置,由操作系统决定,一般都是最左边。
第三个参数 value,一个指向整数的指针,这个整数值会随着滑动钮的移动自动变化。
第四个参数 count,是滑动条可以滑动的最大值。
第五个参数 onChange,是一个指向回调函数的指针,当滑动钮移动时,回调函数就会自动调用。
第六个参数 param,可以是一个任何类型的指针,一旦回调函数执行,这个参数可以传递给回调函数
的param参数,这样不创建全局变量也可以处理滑动条事件。
回调函数的特定形式,也就是说必须满足一下定义:
void your_trackbar_callback
(
int pos, //Trackbar slider position
void* param = NULL //Parameters from cv::serTrackbarCallback()
);
这个回调函数不是必须的,如果不需要直接赋值为NULL,没有回调函数,移动滑动钮的唯一响应就是
value指向的变量值得变化,
//获取滑动条的位置
int cv::getTrackbarPos
(
const string& trackName, //Handle used to identify trackbar, label
const string& windowName //Handle used to identify window
);
//设置滑动条的位置
void cv::setTrackbarPos
(
const string& trackName, //Handle used to identify trackbar, label
const string& windowName, //Handle used to identify window
int pos //Trackbar slider position
);
#include<iostream>
#include<opencv2\highgui.hpp>
#include<opencv2\core.hpp>
int g_switch_value = 1;
void switch_off_function() { std::cout << "Puase" << std::endl; }
void switch_on_function() { std::cout << "Run" << std::endl; }
void switch_callback(int position, void*)
{
if (position)
{
switch_on_function();
}
else
{
switch_off_function();
}
}
char* videopath = "D:/Coder/vs/1_OpenCV/videoTest.mp4";
const cv::String nameWin = "Example";
int main()
{
cv::Mat frame;
cv::VideoCapture g_capture;
g_capture.open(videopath);
if (!g_capture.isOpened())
{
std::cout << "Error" << std::endl;
}
cv::namedWindow(nameWin, cv::WINDOW_AUTOSIZE);
cv::createTrackbar(
"Switch",
nameWin,
&g_switch_value,
1,
switch_callback
);
for (;;)
{
if (g_switch_value)
{
g_capture >> frame;
if (frame.empty())
break;
cv::imshow(nameWin, frame);
}
if (cv::waitKey(33) == 27)
break;
}
return 0;
}