本文可能与图像处理不是有太大的关联,是openCV的HighGUI中关于Mouse Event的一些学习与练习,可能更偏向于编程吧。之前的程序中,也常常会使用cvWaitKey()
去等待键盘的动作。与之相同的,Mouse Event也算是一个很典型的Callback机制了,对于Mouse Event的设置openCV中需要调用以下函数去实现。
void cvSetMouseCallback(const char* window_name,
CvMouseCallback on_mouse,
void* param=NULL )
const char* window_name
当在特定的窗口下Mouse Event被触发的话,会调用Callback函数。CvMouseCallback on_mouse
这里放置Callback函数void* param=NULL
这里可以放置一个任意的参数,可以为NULL。若程序中有需要调用别的参数的时候,可以由这里转交给Callback函数。对于上述的Callback函数,需要使用以下这种结构去进行申明。
void mouse_paint_callback(int event,
int x,
int y,
int flags,
void* param);
int event
表示Enent事件的类型。(由下表给出,尝试使用下表格)Event | Value | 说明 |
---|---|---|
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_LBUTTONDBLCLK | 7 | 左键双击 |
CV_EVENT_RBUTTONDBLCLK | 8 | 右键双击 |
CV_EVENT_MBUTTONDBLCLK | 9 | 中键双击 |
int x, int y
Mouse Event触发瞬间,Mouse位于特定窗口的位置(坐标)。
int flags
这个是事件的标志位,和单片机的寄存器比较类似。发生某个时间后,该事件对应的标志位置位。
flags | Value | 说明 |
---|---|---|
CV_EVENT_FLAG_LBUTTON | 1 (0x01 << 0) | 左键被压下 |
CV_EVENT_FLAG_RBUTTON | 2 (0x01 << 1) | 右键被压下 |
CV_EVENT_FLAG_MBUTTON | 4 (0x01 << 2) | 中建被压下 |
CV_EVENT_FLAG_CTRLKEY | 8 (0x01 << 3) | CTRL键被压下 |
CV_EVENT_FLAG_SHIFTKEY | 16 (0x01 << 4) | SHIFT键被压下 |
CV_EVENT_FLAG_ALTKEY | 32 (0x01 << 5) | ALT键被压下 |
void* param
和之前的说明一样,如果需要外部的参数的话,可以把那个参数(结构体)的指针给过来。这里使用了openCV的一些功能,实现了一个简单的Paint。当然,openCV没有Button的设置,让我不想去做更复杂的功能了。我实现以下功能。
//------------------------------------------------------
// 内容:
// Paintの実現
//
//
//
//
// 2015.5.21
// by zhou fan
// ------------------------------------------------------
#include "stdafx.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
CvRect box;
bool drawing_box = false;
CvRect Eraser;
bool drawing_eraser = false;
int Eraser_Size = 5;
void mouse_paint_callback(int event,
int x,
int y,
int flags,
void* param);
void draw_box( IplImage* img, CvRect box)
{
cvRectangle(img,
cvPoint(box.x,box.y),
cvPoint(box.x+box.width,box.y+box.height),
cvScalar(0x00,0xff,0x00) //Green
);
}
void draw_Eraser( IplImage* img, CvRect Eraser)
{
cvRectangle(img,
cvPoint(Eraser.x - Eraser_Size,Eraser.y - Eraser_Size),
cvPoint(Eraser.x + Eraser_Size,Eraser.y + Eraser_Size),
cvScalar(0xff,0xff,0xff),
CV_FILLED
);
}
void show_Eraser( IplImage* img, CvRect Eraser)
{
cvRectangle(img,
cvPoint(Eraser.x - Eraser_Size,Eraser.y - Eraser_Size),
cvPoint(Eraser.x + Eraser_Size,Eraser.y + Eraser_Size),
cvScalar(0x00,0x00,0x00),
CV_FILLED
);
}
int main(int argc, char** argv[])
{
box = cvRect(-1,-1,0,0);
Eraser = cvRect(-1,-1,0,0);
IplImage* image = cvCreateImage(cvSize(500,500),
IPL_DEPTH_8U,
3);
cvZero(image);
cvAddS(image,cvScalarAll(255),image);
IplImage* temp = cvCloneImage(image);
cvNamedWindow("Paint");
cvSetMouseCallback("Paint",
mouse_paint_callback,
(void*) image);
while(1)
{
cvCopy(image,temp);
if(drawing_box) draw_box(temp,box);
if(drawing_eraser) show_Eraser(temp,Eraser);
cvShowImage("Paint",temp);
if(cvWaitKey(15) == 27) break; //wait ESC key
}
return (int)0;
}
void mouse_paint_callback(int event,
int x,
int y,
int flags,
void* param)
{
IplImage* image = (IplImage*) param;
switch(event)
{
case CV_EVENT_MOUSEMOVE:
{
if(drawing_box)
{
//cout<< (flags & CV_EVENT_FLAG_SHIFTKEY) << "\n";
if((flags & CV_EVENT_FLAG_SHIFTKEY) == CV_EVENT_FLAG_SHIFTKEY)
{
if (box.x>box.y)
{
box.width = x - box.x;
box.height= (y - box.y > 0)?abs(x - box.x):-abs(x - box.x);
}
else
{
box.width = (x - box.x > 0)?abs(y - box.y):-abs(y - box.y);
box.height= y - box.y;
}
//cout<< "TURE" << "\n";
}
else
{
box.width = x - box.x;
box.height= y - box.y;
}
}
if(drawing_eraser)
{
Eraser = cvRect(x,y,0,0);
draw_Eraser(image,Eraser);
}
}
break;
case CV_EVENT_LBUTTONDOWN:
{
drawing_box = true;
box = cvRect(x,y,0,0);
}
break;
case CV_EVENT_RBUTTONDOWN:
{
drawing_eraser = true;
Eraser = cvRect(x,y,0,0);
draw_Eraser(image,Eraser);
}
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;
case CV_EVENT_RBUTTONUP:
{
drawing_eraser = false;
}
break;
}
}
图中黑块位置为橡皮擦
原文发于博客:http://blog.csdn.net/thnh169/
2015 - 5 - 21 初版
[openCV]基于Mouse Event的Paint的实现
原文地址:http://blog.csdn.net/zhoufan900428/article/details/45890053