2016年3月15日 星期二

Mouse Control on OpenCV GUI

Mouse Control on OpenCV GUI

使用OpenCV寫介面時,經常會使用滑鼠的操作,OpenCV有提供一個APIsetMousecallback方便操作。

void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)

  • winname : 建立視窗的名稱
  • onMouse : 滑鼠的callback函式
  • userdate:傳遞的參數
  • void on_Mouse(int event, int x, int y, int flags, void* param);
  • event : CV_EVENT_*變數
  • x : 指定視窗的滑鼠x位置
  • y : 指定視窗的滑鼠y位置
  • flags : CV_EVENT_FLAG的组合
  • param : callback函式傳遞的參數。

Event

#defineCV_EVENT_MOUSEMOVE      0
#defineCV_EVENT_LBUTTONDOWN    1
#defineCV_EVENT_RBUTTONDOWN    2
#defineCV_EVENT_MBUTTONDOWN    3
#defineCV_EVENT_LBUTTONUP      4
#defineCV_EVENT_RBUTTONUP      5
#defineCV_EVENT_MBUTTONUP      6
#defineCV_EVENT_LBUTTONDBLCLK  7
#defineCV_EVENT_RBUTTONDBLCLK  8
#defineCV_EVENT_MBUTTONDBLCLK  9 
#defineCV_EVENT_FLAG_LBUTTON   1
#defineCV_EVENT_FLAG_RBUTTON   2
#defineCV_EVENT_FLAG_MBUTTON   4
#defineCV_EVENT_FLAG_CTRLKEY   8
#defineCV_EVENT_FLAG_SHIFTKEY  16
#defineCV_EVENT_FLAG_ALTKEY    32

簡單的範例:

main.cpp

include "MouseManipulator.h"#
include < iostream >

int main(int argc, char ** argv) 
{
    cv::VideoCapture cap;
    cap.open(0);

    cv::namedWindow("Demo", 1);
    MouseManipulator mouseHandler;
    mouseHandler.initialize("Demo");

    cv::Mat image;

    for (;;) {
        cv::Mat frame;
        cap >> frame;
        if (frame.empty())
            break;

        frame.copyTo(image);

        if (mouseHandler.hasSelection()) {
            cv::Rect rect = mouseHandler.getSelectRect();
            std::cout << "x = " << rect.x << ", y = " << rect.y << ", width = " << rect.width << ", height = " << rect.height << std::endl;
            mouseHandler.clear();
        } else {
            cv::Rect rect = mouseHandler.getSelectRect();
            cv::Mat roi(image, rect);
            cv::bitwise_not(roi, roi);
        }

        cv::imshow("Demo", image);
        cv::waitKey(30);
    }
    return 0;
}

MouseManipulator.h

#ifndef MOUSEMANIPULATOR_H
#define MOUSEMANIPULATOR_H
#include "opencv2/opencv.hpp"

struct MouseHandle
{
public:
    MouseHandle();
    ~MouseHandle();
    cv::Rect selecRect;
    cv::Point2f point;
    bool selectObject;
    bool processing;
};

class MouseManipulator
{
public:
    MouseManipulator();
    ~MouseManipulator();
    void initialize( const std::string &windowName );

    bool hasSelection();
    cv::Rect getSelectRect();
    void clear();

    static void onMouse( int event, int x, int y, int, void *ptr);

private:
    MouseHandle *mouseHandler;
};

#endif // MOUSEMANIPULATOR_H

MouseManipulator.cpp

#include "MouseManipulator.h"


MouseHandle::MouseHandle()
{
    this->selectObject = false;
    this->processing   = false;
}
MouseHandle::~MouseHandle()
{

}

MouseManipulator::MouseManipulator()
{
    mouseHandler = new MouseHandle();
}

MouseManipulator::~MouseManipulator()
{
    if( mouseHandler != NULL ){
        delete mouseHandler;
    }
}

void MouseManipulator::initialize( const std::string &windowName )
{
    if( mouseHandler == NULL ){
        return;
    }
    cv::setMouseCallback( windowName, onMouse, mouseHandler );
}

bool MouseManipulator::hasSelection()
{
    if( mouseHandler->selectObject ){
        return true;
    }
    else{
        return false;
    }
}

cv::Rect MouseManipulator::getSelectRect()
{
    return mouseHandler->selecRect;
}

void MouseManipulator::clear()
{
    mouseHandler->processing   = false;
    mouseHandler->selecRect    = cv::Rect();
    mouseHandler->selectObject = false;

}

void MouseManipulator::onMouse( int event, int x, int y, int, void *ptr )
{
    MouseHandle *mouseHandler = (MouseHandle*)ptr;
    if( mouseHandler->processing ){
        mouseHandler->selecRect.x      = MIN( x, mouseHandler->point.x );
        mouseHandler->selecRect.y      = MIN( y, mouseHandler->point.y );
        mouseHandler->selecRect.width  = std::abs( x - mouseHandler->point.x );
        mouseHandler->selecRect.height = std::abs( y - mouseHandler->point.y );
    }
    switch( event )
    {
    case CV_EVENT_LBUTTONDOWN:
        mouseHandler->point        = cv::Point( x, y );
        mouseHandler->selecRect    = cv::Rect( x, y, 0, 0 );
        mouseHandler->processing   = true;
        mouseHandler->selectObject = false;
        break;
    case CV_EVENT_LBUTTONUP:
        mouseHandler->processing = false;
        if( mouseHandler->selecRect.width > 0 &&
            mouseHandler->selecRect.height > 0 ){
            mouseHandler->selectObject = true;
        }
        break;
    }
}

更多OpenCV文章請參考:OpenCV Tutorial (學習筆記)

0 意見:

張貼留言