如何在网络摄像头框架中使用opencv中的鼠标单击绘制线条?

时间:2014-08-27 17:04:20

标签: opencv image-processing

我想在网络摄像头框架中使用Opencv中的鼠标事件绘制一条线。我也想把它擦掉就像MS-Paint中的橡皮擦一样。我怎么能这样做?我对此并不太了解。但是我的头脑中有这个混乱的pseduo代码,这可能是完全错误但无论如何我会写下来。我想知道如何在c ++中实现它。 所以,我将有两个三鼠标事件 - 事件1-鼠标leftbuttonup--这将用于开始绘图 事件2-鼠标移动 - 这将用于移动鼠标进行绘制 事件3: - 鼠标左键按钮 - 这将用于停止绘图。 事件4-鼠标双击 - 此事件我可以用来擦除图纸。

我还有一个线条的绘制函数,如线条(Mat图像,Point(startx,starty),Point(endx,endy),(0,0,255),1));

现在,我不知道如何以代码格式实现它。我尝试了很多,但结果错了。我有一个真诚的要求,请建议我Mat格式的代码而不是Iplimage格式。感谢。

1 个答案:

答案 0 :(得分:1)

请在下面找到工作代码,并使用Mat内联解释说明;) 如有任何问题,请告诉我。

PS:在主要功能中,我已经为我的代码更改了默认的cam id为1,你应该保持它适合你的PC,可能是0.祝你好运。

#include <iostream>

#include <opencv\cv.h>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>


class WebCamPaint
{
public:

    int cam_id;
    std::string win_name;
    cv::VideoCapture webCam;

    cv::Size frame_size;
    cv::Mat cam_frame, drawing_canvas;

    cv::Point current_pointer, last_pointer;
    cv::Scalar erase_color, paint_color;
    int pointer_size;

    //! Contructor to initialize basic members to defaults
    WebCamPaint()
    {
        cam_id = 0;
        pointer_size = 5;

        win_name = std::string("CamView");
        current_pointer = last_pointer = cv::Point(0, 0);

        erase_color = cv::Scalar(0, 0, 0);
        paint_color = cv::Scalar(250, 10, 10);
    }

    //! init function is required to set some members in case default members needed to change. 
    bool init()
    {
        //! Opening cam with specified cam id
        webCam.open(cam_id);
        //! Check if problem opening video
        if (!webCam.isOpened())
        {
            return false;
        }

        //! Reading single frame and extracting properties
        webCam >> cam_frame;
        //! Check if problem reading video
        if (cam_frame.empty())
        {
            return false;
        }
        frame_size = cam_frame.size();
        drawing_canvas = cv::Mat(frame_size, CV_8UC3);

        //! Creating Activity / Interface window
        cv::namedWindow(win_name);
        cv::imshow(win_name, cam_frame);

        //! Resetting drawing canvas
        drawing_canvas = erase_color;

        //! initialization went successful ;)
        return true;
    }

    //! This function deals wih all processing, drawing and displaying ie main UI to user
    void startAcivity()
    {
        //! Keep doing until user presses "Esc" from Keyboard, wait for 20ms for user input
        for (char user_input = cv::waitKey(20); user_input != 27; user_input = cv::waitKey(20))
        {
            webCam >> cam_frame;    //Read a frame from webcam

            cam_frame |= drawing_canvas;    //Merge with actual drawing canvas or drawing pad, try different operation to merge incase you want different effect or solid effect
            cv::imshow(win_name, cam_frame);    //Display the image to user

            //! Change size of pointer using keyboard + / -, don't they sound fun ;)
            if (user_input == '+' && pointer_size < 25)
            {
                pointer_size++;
            }
            else if (user_input == '-' && pointer_size > 1)
            {
                pointer_size--;
            }
        }
    }

    //! Our function that should be registered in main to opencv Mouse Event Callback
    static void onMouseCallback(int event, int x, int y, int flags, void* userdata)
    {
        /* NOTE: As it will be registered as mouse callback function, so this function will be called if anything happens with mouse
         *          event   :   mouse button event
         *          x, y    :   position of mouse-pointer relative to the window
         *          flags   :   current status of mouse button ie if left / right / middle button is down
         *          userdata:   pointer o any data that can be supplied at time of setting callback,
         *                      we are using here to tell this static function about the this / object pointer at which it should operate
        */

        WebCamPaint *object = (WebCamPaint*)userdata;

        object->last_pointer = object->current_pointer;
        object->current_pointer = cv::Point(x, y);

        //! Drawing a line on drawing canvas if left button is down
        if (event == 1 || flags == 1)
        {
            cv::line(object->drawing_canvas, object->last_pointer, object->current_pointer, object->paint_color, object->pointer_size);
        }

        //! Drawing a line on drawing canvas if right button is down
        if (event == 2 || flags == 2)
        {
            cv::line(object->drawing_canvas, object->last_pointer, object->current_pointer, object->erase_color, object->pointer_size);
        }
    }

};


int main(int argc, char *argv[])
{
    WebCamPaint myCam;
    myCam.cam_id = 1;
    myCam.init();
    cv::setMouseCallback(myCam.win_name, WebCamPaint::onMouseCallback, &myCam);
    myCam.startAcivity();

    return 0;
}