① 鼠标事件是通过传统的回调函数机制来完成。
void your_mouse_callback(int event, int x, int y, int flags, void* param)
其中,第一个参数要指明事件,第二个和第三个参数是鼠标事件的位置,第四个参数是标志位,第五个参数是一个void类型的指针,可用于传递额外的信息。
事件 | 数值 | 含义 |
---|---|---|
cv::EVENT_MOUSEMOVE | 0 | 鼠标移动事件 |
cv::EVENT_LBUTTONDOWN | 1 | 鼠标左键按下事件 |
cv::EVENT_RBUTTONDOWN | 2 | 鼠标右键按下事件 |
cv::EVENT_MBUTTONDOWN | 3 | 鼠标中键按下事件 |
cv::EVENT_LBUTTONUP | 4 | 鼠标左键释放事件 |
cv::EVENT_RBUTTONUP | 5 | 鼠标右键释放事件 |
cv::EVENT_MBUTTONUP | 6 | 鼠标中键释放事件 |
cv::EVENT_LBUTTONBLCLK | 7 | 鼠标左键双击事件 |
cv::EVENT_RBUTTONBLCLK | 8 | 鼠标右键双击事件 |
cv::EVENT_MBUTTONBLCLK | 9 | 鼠标中键双击事件 |
cv::EVENT_MOUSEWHEEL | 10 | 滑动滚轮上下滚动 |
cv::EVENT_MOUSEHWHEEL | 11 | 滑动滚轮左右滚动 |
标志 | 数值 | 含义 |
---|---|---|
cv::EVENT_FlAG_LBUTTON | 1 | 指示鼠标左键已关闭。 |
cv::EVENT_FlAG_RBUTTON | 2 | 指示鼠标右键已关闭。 |
cv::EVENT_FlAG_MBUTTON | 4 | 指示鼠标中键已关闭。 |
cv::EVENT_FlAG_CTRLKEY | 8 | 指示CTRL键被按下。 |
cv::EVENT_FlAG_SHIFTKEY | 16 | 指示SHIFT键被按下。 |
cv::EVENT_FlAG_ALTKEY | 32 | 指示ALT键被按下。 |
② 在定义完回调函数后需要注册该回调函数。
void cv::setMouseCallback(const string& windowName, cv::MouseCallback on_mouse, void* param=NULL)
其中,第一个参数是回调函数作用的窗口名称,第二个参数是要注册的回调函数,第三个是要给回调函数传递的特定信息。
#include "stdafx.h"
#include
// 定义回调函数
void my_mouse_callback(int event, int x, int y, int flags, void* param);
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));
}
void help() {
std::cout << "Call: ./ch4_ex4_1\n" << "show how to use a mouse to draw regions in an image." << std::endl;
}
int main()
{
help();
box = cv::Rect(-1, -1, 0, 0);
cv::Mat image(200, 200, CV_8UC3);
cv::Mat temp;
image.copyTo(temp);
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(temp);
if (drawing_box)
{
draw_box(temp, box);
}
cv::imshow("Box Example", temp);
if (cv::waitKey(15) == 27)
{
break;
}
}
cv::destroyWindow("Box Example");
return 0;
}
void my_mouse_callback(int event, int x, int y, int flags, void* param) {
cv::Mat& image = *(cv::Mat*) param;
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);
}
break;
}
}
运行结果:
① 创建一个滑动条
int cv::createTrackbar(const string& trackbarName, const string& windowName, int* value, int count, cv::TrackbarCallback onChange, void* param)
其中:第一个参数是滑动条名称,第二个参函数是将要添加到的父窗口的名称,第三个参数是指向整数的指针,这个整数值会随着滑动钮的移动自动变化,第四个参数是滑动条可以滑动的最大值,第五个参数是回调函数,最后一个参数是传给回调函数的参数。
② 可获取或设置滑动条的位置值
int cv::getTrackbarPos(const string& trackbarName, const string& windowName)
void cv::setTrackbarPos(const string& trackbarName, const string& windowName, int pos)
③ 开关功能
开关是只有两个位置的滚动条,当它处于“开”状态的时候为1, 处于“关”状态的时候为0。
#include "stdafx.h"
#include
#include
using namespace std;
int g_switch_value = 1;
void switch_off_function() {
cout << "Pause\n";
}
void switch_on_function(){
cout << "run\n";
}
void switch_callback(int position, void*) {
if (position == 0)
{
switch_off_function();
}
else
{
switch_on_function();
}
}
void help() {
cout << "Call: my.avi" << endl;
cout << "Shows putting a pause button in a video." << endl;
}
// 使用滚动条来创建一个“开关”,用来控制视频的播放功能
int main()
{
cv::Mat frame;
cv::VideoCapture g_capture;
g_capture.open("D:\\mgtv\\123.mp4");
help();
cv::namedWindow("example", 1);
cv::createTrackbar("switch", "example", &g_switch_value, 1, switch_callback);
for (;;)
{
if (g_switch_value)
{
g_capture >> frame;
if (frame.empty())
{
break;
}
cv::imshow("example", frame);
}
if (cv::waitKey(10) == 27)
{
break;
}
}
cv::destroyWindow("example");
return 0;
}