opencv学习笔记滑动条的创建和使用鼠标操作和键盘操作
Posted 非晚非晚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv学习笔记滑动条的创建和使用鼠标操作和键盘操作相关的知识,希望对你有一定的参考价值。
1. 滑动条的创建和使用
滑动条(Trackbar)是OpenCV动态调节参数特别好用的工具,它依附于窗口而存在。由于Opencv中没有按钮的功能,我们还可以使用0-1的滑动条来实现相应的功能。
1.1 相关的函数
主要有两个函数,一个是创建滑动条函数:createTrackbar(),另一个是获取当前轨迹条的位置函数:getTrackbarPos()。
- 创建滑动条
createTrackbar函数用于创建一个可以调整数值的滑动条,并将滑动条附加到指定的窗口上,它经常和一个回调函数配合使用。
函数原型如下:
int createTrackbar( const string & trackbarname, const string & winname,
int * value , int count, TrackbarCallback onChange= 0 , void * userdata= 0 )
参数解释:
- trackbarname:轨迹条的名字。
- winname:附加到的指定窗口名。
- value:滑块的位置,在创建时,即为初始位置。
- count:滑块的最大位置的值。滑块的最小值为0。
- onChange:指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。
回调的类型为:void xx(int, void*);//第一个参数表示轨迹条的位置,第二个参数表示用户数据userdata。- userdata:传给回调函数的数据,用来处理轨迹条事件。
- 获取当前轨迹条的位置
getTrackbarPos()用于获取当前轨迹条的位置,它的函数原型为:
int getTrackbarPos(const string& trackbarname, const string& winname);
参数解释:
- trackbarname:表示轨迹条的名字;
- winname:表示轨迹条的父窗口的名称。
1.2. 代码示例
下面的是线性混合的例子。
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#define WIN_NAME "Linear Blend"
using namespace cv;
using std::cout;
using std::endl;
char TrackbarName[50];//滑动条的名字
const int alpha_slider_max = 100;//滑动条的最大值
int alpha_slider;
double alpha;
double beta;
Mat src1;
Mat src2;
Mat dst;
//回调函数
void on_trackbar( int, void* )
{
alpha = (double) alpha_slider/alpha_slider_max ;
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);//线性混合,滑动条越大,则alpha越大,那么越偏向于src1
int pos = getTrackbarPos(TrackbarName, WIN_NAME);//获取当前滑动条位置
cout<<"当前滑动条位置:"<<pos<<endl;
imshow( WIN_NAME, dst );
}
int main( void )
{
src1 = imread("/home/liqiang/Data/vision/classic/LinuxLogo.jpg");
src2 = imread("/home/liqiang/Data/vision/classic/WindowsLogo.jpg");
//![load]
if( src1.empty() ) { cout << "Error loading src1 \\n"; return -1; }
if( src2.empty() ) { cout << "Error loading src2 \\n"; return -1; }
alpha_slider = 70;//滑动条的初始位置
namedWindow(WIN_NAME, WINDOW_AUTOSIZE); // Create Window
sprintf( TrackbarName, "Alpha x %d", alpha_slider_max );
//滑动条名字,窗口名,滑动条初始位置,滑动条最大值,回调函数
//滑动条改变,回调才起作用
createTrackbar( TrackbarName, WIN_NAME, &alpha_slider, alpha_slider_max, on_trackbar );
on_trackbar( alpha_slider, 0 );//一开始就调用,否则刚启动不显示图像
waitKey(0);
return 0;
}
运行示例:
2. 鼠标操作
2.1 鼠标函数
setMouseCallback()函数的作用是为指定窗口设置鼠标回调函数,原型如下:
void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata=0);
解释如下:
- winname:窗口的名字
- onMouse:鼠标事件的回调函数
回调函数的形式如下:
void Foo(int event, int x, int y, int flags, void* param);
- event:是EVENT+变量
- x,y是鼠标指针在
图像坐标系
中的坐标。- flags:是EVENT_FLAG的组合。
- param:是用户传递
2.2 代码示例
#include<opencv2/opencv.hpp>
using namespace cv;
#define WINNAME "程序窗口"
Rect g_rectangle;
bool g_bDrawingBox = false;//是否绘图
RNG g_rng(12345);
//矩形绘制
void DrawRectangle(Mat& img, Rect box)
{
rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0,255), g_rng.uniform(0,255),g_rng.uniform(0,255)));//随机颜色,tl,br左上角和右下角
}
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
Mat& image = *(cv::Mat*)param;
switch(event)
{
case CV_EVENT_MOUSEMOVE://鼠标移动
{
if(g_bDrawingBox)
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
}
break;
case CV_EVENT_LBUTTONDOWN://左键按下
{
g_bDrawingBox = true;
g_rectangle = Rect(x,y,0,0);//起点
}
break;
case CV_EVENT_LBUTTONUP://左键抬起
{
g_bDrawingBox = false;
if(g_rectangle.width < 0)
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if(g_rectangle.height < 0)
{
g_rectangle.y +=g_rectangle.height;
g_rectangle.height *=-1;
}
DrawRectangle(image, g_rectangle);
}
break;
}
}
int main(int argc, char ** argv)
{
//准备参数
g_rectangle = Rect(-1, -1, 0, 0);
Mat srcImage(600, 800, CV_8UC3), tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-1, -1, 0, 0);
srcImage = Scalar::all(0);
// 设置鼠标操作回调函数
namedWindow(WINNAME);
setMouseCallback(WINNAME, on_MouseHandle, (void *)&srcImage);
// 程序主循环,当进行绘制的标识符为真的时候进行绘制
while (1)
{
srcImage.copyTo(tempImage); // 复制源图到临时变量
if (g_bDrawingBox)
{
DrawRectangle(tempImage, g_rectangle); //进行绘制
}
imshow(WINNAME, tempImage);
if (waitKey(10) == 27) // 按下ESC键,程序退出
break;
}
return 0;
}
输出示例:
3. 键盘操作
3.1 键盘操作函数
实际上opencv没有相应的API函数,而是调用waiKey(delay)进行键盘操作。
int waitKey(int delay=0)
该函数的主要作用是,如果过了delay毫秒
,仍然没等到有按键事件发生,则返回-1,进而继续执行下面的程序,类似于延时的效果。返回的数值是按下的按键字符对应的ASCII编码。
waitKey()和waitKey(0)都表示无限等待
任意键盘输入。
注意:
如果没有图像显示,则不接受键盘输入,只作为延时作用。
常用编码键值表如下:
键盘 | 数字 |
---|---|
ESC | 27 |
回车键 | 10 |
shift | 225 |
Ctrl | 227 |
Alt | 233 |
Delete | 255 |
空格 | 32 |
左方向键 | 81 |
上方向键 | 82 |
右方向键 | 83 |
下方向键 | 84 |
A | 65 |
B | 66 |
小键盘0 | 48 |
小键盘9 | 57 |
3.2 代码示例
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat image = imread( "/home/liqiang/Data/vision/classic/lena.jpg", CV_LOAD_IMAGE_COLOR);
if(image.empty()){std::cout<<"没有图像输入"<<std::endl;return -1;}
Mat gray, hsv;
Mat dst = Mat::zeros(image.size(), image.type());
imshow("原图", image);
while (true)
{
int c = waitKey(100);
//if(c != -1)std::cout<<"你输入的键盘值为:"<<c<<std::endl;
if (c == 27)
{
std::cout << "你输入的是ESC" << std::endl;
break;
}
else if (c == 49)
{
std::cout << "你输入的是1" << std::endl;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("灰度图", gray); // 灰度图显示
}
else if (c == 50)
{
std::cout << "你输入的是2" << std::endl;
cvtColor(image, hsv, COLOR_HSV2BGR);
imshow("hsv", hsv); // HSV图显示
}
else if (c == 51)
{
std::cout << "你输入的是3" << std::endl;
dst = Scalar(50, 50, 50);
add(image, dst, dst);
imshow("dstImage", dst);
}
}
}
输出结果:
以上是关于opencv学习笔记滑动条的创建和使用鼠标操作和键盘操作的主要内容,如果未能解决你的问题,请参考以下文章