Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在网络摄像头框架中使用opencv中的鼠标单击绘制线?_Opencv_Image Processing - Fatal编程技术网

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

如何在网络摄像头框架中使用opencv中的鼠标单击绘制线?,opencv,image-processing,Opencv,Image Processing,我想在网络摄像头框架中使用Opencv中的鼠标事件画一条线。我也想像MS-Paint中的橡皮擦一样擦除它。我该怎么做?我不太清楚。但是我脑子里有一个乱码,它可能是完全错误的,但我还是要把它写下来。我想知道如何在C++中实现它。 所以,我将有两个三鼠标事件- 事件1-鼠标左键单击-这将用于启动绘图 事件2-鼠标移动-这将用于移动鼠标进行绘制 事件3:-鼠标左键向下这将用于停止绘图。 事件4-鼠标双击-我可以使用此事件擦除图形 我还将有一个绘制线的函数,比如线(Mat图像,点(startx,star

我想在网络摄像头框架中使用Opencv中的鼠标事件画一条线。我也想像MS-Paint中的橡皮擦一样擦除它。我该怎么做?我不太清楚。但是我脑子里有一个乱码,它可能是完全错误的,但我还是要把它写下来。我想知道如何在C++中实现它。 所以,我将有两个三鼠标事件- 事件1-鼠标左键单击-这将用于启动绘图 事件2-鼠标移动-这将用于移动鼠标进行绘制 事件3:-鼠标左键向下这将用于停止绘图。 事件4-鼠标双击-我可以使用此事件擦除图形

我还将有一个绘制线的函数,比如线(Mat图像,点(startx,starty),点(endx,endy),(0,0255),1)


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

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

PS:在主功能中,我已将defauld 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;
}
#包括
#包括
#包括
#包括
类网络地图
{
公众:
int cam_id;
std::字符串win_name;
视频捕捉网络摄像机;
cv::尺寸框架尺寸;
cv::Mat cam_框架、绘图画布;
cv::指向当前\u指针,最后一个\u指针;
cv::标量擦除颜色、绘制颜色;
int指针大小;
//!构造函数将基本成员初始化为默认值
网络绘画()
{
cam_id=0;
指针大小=5;
win_name=std::string(“CamView”);
当前指针=最后一个指针=cv::Point(0,0);
擦除颜色=cv::标量(0,0,0);
油漆颜色=cv::标量(250,10,10);
}
//!init函数用于设置某些成员,以防需要更改默认成员。
boolinit()
{
//!使用指定的凸轮id打开凸轮
网络摄像头打开(摄像头id);
//!检查打开视频是否有问题
如果(!webCam.isOpened())
{
返回false;
}
//!读取单帧并提取属性
网络摄像头>>摄像头框架;
//!检查阅读视频是否有问题
if(cam_frame.empty())
{
返回false;
}
框架尺寸=凸轮框架尺寸();
图纸画布=cv::Mat(框架尺寸,cv\u 8UC3);
//!正在创建活动/界面窗口
cv::namedWindow(win_name);
cv::imshow(win_名称、cam_框架);
//!正在重置绘图画布
绘制画布=擦除颜色;
//!初始化成功;)
返回true;
}
//!此功能处理所有处理、绘制和向用户显示ie主界面的操作
void startAcivity()
{
//!继续操作,直到用户按键盘上的“Esc”,等待20毫秒,等待用户输入
对于(char user_input=cv::waitKey(20);user_input!=27;user_input=cv::waitKey(20))
{
网络摄像头>>摄像头画面;//从网络摄像头读取画面
cam_frame |=drawing_canvas;//与实际绘图画布或绘图板合并,尝试不同的操作以合并,以防需要不同的效果或实体效果
cv::imshow(win_name,cam_frame);//向用户显示图像
//!使用键盘+/-更改指针的大小,听起来有趣吗;)
如果(用户输入=='+'&&指针大小<25)
{
指针大小++;
}
else if(用户输入=='-'&&指针大小>1)
{
指针大小--;
}
}
}
//!应该在main中注册到opencv鼠标事件回调的函数
静态void onMouseCallback(int事件、int x、int y、int标志、void*userdata)
{
/*注意:由于它将注册为鼠标回调函数,所以如果鼠标发生任何事情,将调用此函数
*事件:鼠标按钮事件
*x,y:鼠标指针相对于窗口的位置
*标志:鼠标按钮的当前状态,即左/右/中键是否已按下
*userdata:指向在设置回调时可以提供的任何数据的指针,
*我们在这里使用它来告诉这个静态函数它应该操作的this/object指针
*/
WebCamPaint*对象=(WebCamPaint*)用户数据;
对象->最后一个\u指针=对象->当前\u指针;
对象->当前指针=cv::点(x,y);
//!如果左键关闭,则在绘图画布上绘制一条线
如果(事件==1 | |标志==1)
{
cv::line(对象->绘制画布,对象->最后一个指针,对象->当前指针,对象->绘制颜色,对象->指针大小);
}
//!如果右键关闭,则在绘图画布上绘制一条线
如果(事件==2 | |标志==2)
{
cv::line(对象->绘制画布,对象->最后一个指针,对象->当前指针,对象->擦除颜色,对象->指针大小);
}
}
};
int main(int argc,char*argv[])
{
网络摄像头;
myCam.cam_id=1;
myCam.init();
cv::setMouseCallback(myCam.win_名称、网络捕获::onMouseCallback和myCam);
myCam.startAcivity();
返回0;
}

您尝试了什么。你所说的“错误结果”是什么意思?使用opencv的鼠标侦听器确定用户单击的位置。有很多例子。@user3791372:-让我非常困扰的是,我不知道如何计算Lbuttonup中的开始位置和Lbuttondown中的结束位置。我在谷歌上查看的大多数文章都使用了iplimages,这让我很困惑,因为我遵循Mat格式。你能推荐我吗