OpenCV之鼠标画图

本文记录了使用OpenCV通过鼠标实现画线和画矩形的功能。作者参照MoreWindows的博客,设置了画图标志位和坐标点,实现了鼠标按下到释放期间的动态画线,并详细介绍了如何在鼠标事件中画矩形,包括如何处理背景图像以保留绘制结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习OpenCV,网上关于OpenCV编程的介绍有很多,今天学习了MoreWindows博客中的鼠标绘图(http://blog.youkuaiyun.com/morewindows/article/details/8426283),自己动手按照教程一步步学习,并做了些改动,相当于是自己举一反三吧。所有代码均验证通过。

1.鼠标画线

这里就按照MoreWindows博客的介绍进行处理,只不过为了偷懒,有些变量名字就自己随便取了。

设计思想是鼠标按下之后,设置画图标志位有效,鼠标移动时调用回调函数进行画线,鼠标恢复之后画图标志位无效,鼠标移动时不再画线。

为了实现这样的功能,需要设置全局标志位draw_flag以及画线的起始点和终点point_start和point_end,每一次画线结束后将point_start用point_end的值进行更新。

#include <opencv2/opencv.hpp>
#include <cv.h>
#include <highgui.h>
bool img_flag=false;
char *window_name="test";
void mousecallback(int event,int x,int y,int flags,void *param)
{
	static CvPoint point_start,point_end;
	static bool draw_flag=false;
	switch(event)
	{
	case CV_EVENT_LBUTTONDOWN:
		{
			draw_flag=true;point_start=cvPoint(x,y);
			break;
		}
	case CV_EVENT_LBUTTONUP:
		{
			draw_flag=false;
			break;
		}
	case CV_EVENT_MOUSEMOVE:
		{
			if(draw_flag==true)
			{
				point_end=cvPoint(x,y);
				cvLine((IplImage *)param,point_start,point_end,CV_RGB(0,255,0));
				cvShowImage(window_name,(IplImage *)param);
				point_start=point_end;
				break;
			}
		}
	}
}
int main(int argc, char* argv[])
{
	IplImage *img=cvCreateImage(cvSize(800,600),IPL_DEPTH_8U,3);
	cvRectangle(img,cvPoint(0,0),cvPoint(img->width,img->height),cvScalar(0xff,0xff,0xff));
	cvNamedWindow(window_name,CV_WINDOW_AUTOSIZE);
	cvShowImage(window_name,img);
	cvSetMouseCallback(window_name,mousecallback,img);
	while(1)
	{
		if(cvWaitKey(15)==27)
			break;
	}
	cvDestroyWindow(window_name);
	cvReleaseImage(&img);
	return 0;
}

2.鼠标画单个矩形

这里与画线的改变在于,画完之后不保存在背景中,因此要复制背景的副本img_clone,并在该副本上进行操作。

#include "stdafx.h"

#include <opencv2/opencv.hpp>
#include <cv.h>
#include <highgui.h>

bool img_flag=false;
char *window_name="test";
void mousecallback(int event,int x,int y,int flags,void *param)
{
	static CvPoint point_start,point_end;
	static bool draw_flag=false;
	IplImage *img_clone=cvCloneImage((IplImage*)param);
	switch(event)
	{
		case CV_EVENT_LBUTTONDOWN:
			{
				draw_flag=true;
				point_start=cvPoint(x,y);
				break;
			}
		case CV_EVENT_LBUTTONUP:
			{
				draw_flag=false;
				break;
			}
		case CV_EVENT_MOUSEMOVE:
			{
				if(draw_flag==true)
					{
						point_end=cvPoint(x,y);
						cvRectangle(img_clone,point_start,point_end,CV_RGB(0,255,0));
						cvShowImage(window_name,img_clone);
						break;
					}
			}
	}
}
int main(int argc, char* argv[])
{

	IplImage *img=cvCreateImage(cvSize(800,600),IPL_DEPTH_8U,3);
	cvRectangle(img,cvPoint(0,0),cvPoint(img->width,img->height),cvScalar(0xff,0xff,0xff));

	cvNamedWindow(window_name,CV_WINDOW_AUTOSIZE);
	cvShowImage(window_name,img);

	cvSetMouseCallback(window_name,mousecallback,img);

	while(1)
	{
		if(cvWaitKey(15)==27)
			break;
	}
	cvDestroyWindow(window_name);
	cvReleaseImage(&img);

	return 0;

}

3.鼠标画矩形并保留

这里与第2个改动在于,在CV_EVENT_BUTTONUP事件发生后,将矩形画在背景中,而不是副本上。同时,CV_EVENT_MOUSEMOVE事件中的操作仍然是对副本进行。

#include "stdafx.h"

#include <opencv2/opencv.hpp>
#include <cv.h>
#include <highgui.h>

bool img_flag=false;
char *window_name="test";
void mousecallback(int event,int x,int y,int flags,void *param)
{
	static CvPoint point_start,point_end;
	static bool draw_flag=false;
	IplImage *img_clone=cvCloneImage((IplImage*)param);
	switch(event)
	{
		case CV_EVENT_LBUTTONDOWN:
			{
				draw_flag=true;
				point_start=cvPoint(x,y);
				break;
			}
		case CV_EVENT_LBUTTONUP:
			{
				draw_flag=false;
				point_end=cvPoint(x,y);
				cvRectangle((IplImage *)param,point_start,point_end,CV_RGB(0,255,0));
				break;
			}
		case CV_EVENT_MOUSEMOVE:
			{
				if(draw_flag==true)
					{
						point_end=cvPoint(x,y);
						cvRectangle(img_clone,point_start,point_end,CV_RGB(0,255,0));
						cvShowImage(window_name,img_clone);
						break;
					}
			}
	}
}
int main(int argc, char* argv[])
{

	IplImage *img=cvCreateImage(cvSize(800,600),IPL_DEPTH_8U,3);
	cvRectangle(img,cvPoint(0,0),cvPoint(img->width,img->height),cvScalar(0xff,0xff,0xff));

	cvNamedWindow(window_name,CV_WINDOW_AUTOSIZE);
	cvShowImage(window_name,img);

	cvSetMouseCallback(window_name,mousecallback,img);

	while(1)
	{
		if(cvWaitKey(15)==27)
			break;
	}
	cvDestroyWindow(window_name);
	cvReleaseImage(&img);

	return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值