【问题标题】:how can i draw lines using mouseclick in opencv in a webcam frame?如何在网络摄像头框架中使用 opencv 中的鼠标单击画线?
【发布时间】:2014-10-21 09:15:12
【问题描述】:

我想在网络摄像头框架中使用 Opencv 中的鼠标事件画一条线。我也想像 MS-Paint 中的橡皮擦一样擦除它。我该怎么做?我对此没有太多想法。但是我脑子里有这个加扰的伪代码,这可能是完全错误的,但无论如何我都会写下来。我想知道如何在 C++ 中实现它。 所以,我将有两个三鼠标事件- 事件 1- 鼠标左键向上——这将用于开始绘图 事件 2- 鼠标移动——这将用于移动鼠标进行绘制 事件 3:- 鼠标左键按下 - 这将用于停止绘图。 事件 4- 鼠标双击 - 这个事件我可以用来擦除绘图。

我还将为线条绘制函数,例如 line(Mat image,Point(startx,starty),Point(endx,endy),(0,0,255),1));

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

【问题讨论】:

  • 你试过什么。 “错误的结果”是什么意思?使用 opencv 的鼠标监听器来确定用户点击的位置。例子很多。
  • @user3791372:- 困扰我的事情是我无法弄清楚如何计算 Lbuttonup 中的开始位置和 Lbuttondown 中的结束位置。我使用 iplimages 在 google 上查看的大多数文章都让我很困惑,因为我遵循 Mat 格式。你能给我一些建议吗?
  • 一个二元数组、一个二元结构、一个简单的类等,不要过于复杂
  • @user3791372:- 我还是很困惑
  • 嗨 Rebecca,你是想在播放网络摄像头的视频上画图,还是只捕捉一帧然后在上面画图。

标签: opencv image-processing


【解决方案1】:

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

PS:在 main 函数中,我已将代码的默认 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;
}

【讨论】:

  • :- 非常感谢。对此,我真的非常感激。你帮了我很多。再次感谢。 bdw你能推荐我任何使用c++的Opencv书籍,这样我就可以学习一些复杂的程序。我基本上是一个自学者,因为我是大一新生,所以我需要一本书来清楚地解释这些概念。再次感谢
  • 我很高兴它有帮助。我假设你理解并从这段代码中学到了东西。关于进一步的学习,OpenCV 是一个了不起的图书馆和丰富的资源。如果你只是谷歌,你会发现很多书,代码等。我建议你从官方文档开始:opencv.org/documentation.html。此页面包含所有代码文档和参考资料、书籍、教程等的链接。你可以去oreilly书,它很快就会推出新版本。如果有帮助,您可以投票/接受此答案,它可以帮助其他读者查看答案的评分。
猜你喜欢
  • 2016-01-01
  • 1970-01-01
  • 2016-04-07
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
相关资源
最近更新 更多