opencv鼠标操作

来源:互联网 发布:中原农险数据脱敏 编辑:程序博客网 时间:2024/06/05 05:08
  opencv中的鼠标操作和滑动条的消息映射方式很类似,都是通过一个中介函数配合一个回调函数来实现。opencv中提供了setMouseCallback()函数,这个函数的作用是为指定的窗口设置鼠标回调函数(跟createTrackBar函数一样都是依附于指定的窗口),通过这个函数可以实现画图的功能。下面是这个函数的原型:
void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata = 0);
第一个参数,const string&类型的winname,窗口的名字。
第二个参数,MouseCallback类型的函数指针onMouse,指定窗口里每次鼠标事件发生时,被调用的函数指针。这个MouseCallback类型的函数的原型为void xxx(int event, int x, int y, int flags, void* param)。
第三个参数,void*类型的userdata,用户定义的传递到回调函数的参数,有默认值0。
  对于MouseCallback类型的函数,event是EVENT_*变量之一,x和y是鼠标指针在图像坐标系(注意,不是窗口坐标系)中的坐标值,flag是CV_EVENT_FLAG的组合,param是用户定义的传递到setMouseCallback函数调用的参数。EVENT_*变量代表了一些鼠标事件的号码,每当鼠标有动作对应动作的事件号码就会被传入到onMouse()函数中,同时也会传入鼠标移动的坐标(也就是MouseCallback类型函数中的x、y参数),flags代表的是鼠标拖拽事件。下面是EVENT和flag鼠标事件的宏定义:
Event:
#define CV_EVENT_MOUSEMOVE 0             滑动
#define CV_EVENT_LBUTTONDOWN 1           左键点击
#define CV_EVENT_RBUTTONDOWN 2           右键点击
#define CV_EVENT_MBUTTONDOWN 3           中键点击
#define CV_EVENT_LBUTTONUP 4             左键放开
#define CV_EVENT_RBUTTONUP 5             右键放开
#define CV_EVENT_MBUTTONUP 6             中键放开
#define CV_EVENT_LBUTTONDBLCLK 7         左键双击
#define CV_EVENT_RBUTTONDBLCLK 8         右键双击
#define CV_EVENT_MBUTTONDBLCLK 9         中键双击
flags:
#define CV_EVENT_FLAG_LBUTTON 1          左键拖拽
#define CV_EVENT_FLAG_RBUTTON 2          右键拖拽
#define CV_EVENT_FLAG_MBUTTON 4          中键拖拽
#define CV_EVENT_FLAG_CTRLKEY 8         (8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16       (16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32         (32~39)按Alt不放事件

  下面是一个鼠标操纵的示例,通过鼠标可以画出各种颜色的矩形。
#include <opencv2/opencv.hpp>
using namespace cv;

#define WINDOW_NAME "【程序窗口】"        //为窗口标题定义的宏 

void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRectangle( cv::Mat& img, cv::Rect box );
void ShowHelpText( );

Rect g_rectangle;
bool g_bDrawingBox = false;//是否进行绘制
RNG g_rng(12345);

int main( int argc, char** argv ) 
{
    //【1】准备参数
    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);

    //【2】设置鼠标操作回调函数
    namedWindow( WINDOW_NAME );
    setMouseCallback(WINDOW_NAME,on_MouseHandle,(void*)&srcImage);

    //【3】程序主循环,当进行绘制的标识符为真时,进行绘制
    while(1)
   {
        srcImage.copyTo(tempImage);//拷贝源图到临时变量
        if( g_bDrawingBox ) DrawRectangle( tempImage, g_rectangle );//当进行绘制的标识符为真,则进行绘制
        imshow( WINDOW_NAME, tempImage );
        if( waitKey( 10 ) == 27 ) break;//按下ESC键,程序退出
    }
    return 0;
}

void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
    Mat& image = *(cv::Mat*) param;
    switch( event)
    {
        //鼠标移动消息
        case EVENT_MOUSEMOVE: 
        {
            if( g_bDrawingBox )//如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
            {
                 g_rectangle.width = x-g_rectangle.x;
                 g_rectangle.height = y-g_rectangle.y;
            }
        }
        break;


        //左键按下消息
        case EVENT_LBUTTONDOWN: 
        {
            g_bDrawingBox = true;
            g_rectangle =Rect( x, y, 0, 0 );//记录起始点
        }
        break;

        //左键抬起消息
        case EVENT_LBUTTONUP: 
        {
            g_bDrawingBox = false;//置标识符为false
            //对宽和高小于0的处理
            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;
    }
}

//自定义的矩形绘制函数
void DrawRectangle( cv::Mat& img, cv::Rect box )
{
    cv::rectangle(img,box.tl(),box.br(),cv::Scalar(g_rng.uniform(0, 255), g_rng.uniform(0,255),     g_rng.uniform(0,255)));//随机颜色
}


0 0
原创粉丝点击