如何在网络摄像头框架中使用opencv中的鼠标单击绘制线?
我想在网络摄像头框架中使用Opencv中的鼠标事件画一条线。我也想像MS-Paint中的橡皮擦一样擦除它。我该怎么做?我不太清楚。但是我脑子里有一个乱码,它可能是完全错误的,但我还是要把它写下来。我想知道如何在C++中实现它。 所以,我将有两个三鼠标事件- 事件1-鼠标左键单击-这将用于启动绘图 事件2-鼠标移动-这将用于移动鼠标进行绘制 事件3:-鼠标左键向下这将用于停止绘图。 事件4-鼠标双击-我可以使用此事件擦除图形 我还将有一个绘制线的函数,比如线(Mat图像,点(startx,starty),点(endx,endy),(0,0255),1)如何在网络摄像头框架中使用opencv中的鼠标单击绘制线?,opencv,image-processing,Opencv,Image Processing,我想在网络摄像头框架中使用Opencv中的鼠标事件画一条线。我也想像MS-Paint中的橡皮擦一样擦除它。我该怎么做?我不太清楚。但是我脑子里有一个乱码,它可能是完全错误的,但我还是要把它写下来。我想知道如何在C++中实现它。 所以,我将有两个三鼠标事件- 事件1-鼠标左键单击-这将用于启动绘图 事件2-鼠标移动-这将用于移动鼠标进行绘制 事件3:-鼠标左键向下这将用于停止绘图。 事件4-鼠标双击-我可以使用此事件擦除图形 我还将有一个绘制线的函数,比如线(Mat图像,点(startx,star
现在,我不知道如何用代码格式实现这个。我试了很多次,但结果都错了。我有一个真诚的要求,请建议我在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格式。你能推荐我吗