opencv学习笔记滑动条的创建和使用鼠标操作和键盘操作

Posted 非晚非晚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv学习笔记滑动条的创建和使用鼠标操作和键盘操作相关的知识,希望对你有一定的参考价值。

1. 滑动条的创建和使用

滑动条(Trackbar)是OpenCV动态调节参数特别好用的工具,它依附于窗口而存在。由于Opencv中没有按钮的功能,我们还可以使用0-1的滑动条来实现相应的功能。

1.1 相关的函数

主要有两个函数,一个是创建滑动条函数:createTrackbar(),另一个是获取当前轨迹条的位置函数:getTrackbarPos()。

  1. 创建滑动条

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:传给回调函数的数据,用来处理轨迹条事件。
  1. 获取当前轨迹条的位置

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)都表示无限等待任意键盘输入。

注意:如果没有图像显示,则不接受键盘输入,只作为延时作用。

常用编码键值表如下:

键盘数字
ESC27
回车键10
shift225
Ctrl227
Alt233
Delete255
空格32
左方向键81
上方向键82
右方向键83
下方向键84
A65
B66
小键盘048
小键盘957

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学习笔记滑动条的创建和使用鼠标操作和键盘操作的主要内容,如果未能解决你的问题,请参考以下文章

HighGUI图形图像界面初步——滑动条的创建和使用

滑动条的创建

《OpenCV3编程入门》学习笔记三:HighGUI图形用户界面

OPENCV中滑动条的使用

python opencv:使用滑动条做调色板

opencv学习之路鼠标截图,滑动条播放视频