opencv实现鼠标画矩形框、显示十字线、滚轮缩放

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

#define WINNAME "画板"

struct MouseParam
{
	Mat img; //用于画好一个后显示
	Mat imgZoomBackup; //用于zoom的还原备份
	Mat imgTmp; //用于实时显示
	Mat imgBackup; //清空,显示最初的图
	Point pt1;
	Point pt2;
	bool mouseLflag;
	float scale;
};

void draw_rectangle(Mat &img, const Point &pt1, const Point &pt2)
{
	//rectangle函数参数: 图片, 左上角, 右下角, 颜色, 线条粗细, 线条类型,点类型    
	rectangle(img, pt1, pt2, Scalar(0, 255, 0), 1, 0, 0);
}

void draw_crossline(Mat &img, const Point &pt)
{
	int width = img.cols;
	int height = img.rows;
	cv::Point ptv1;
	cv::Point ptv2;
	cv::Point pth1;
	cv::Point pth2;
	ptv1 = cv::Point(pt.x, 0);
	ptv2 = cv::Point(pt.x, height);
	pth1 = cv::Point(0, pt.y);
	pth2 = cv::Point(width, pt.y);

	cv::line(img, ptv1, ptv2, Scalar(255, 255, 0), 1);
	cv::line(img, pth1, pth2, Scalar(255, 255, 0), 1);
}

void zoom(Mat &img, const Mat &srcimg, const Point &pt, const float scale)
{
	int x1, y1, x2, y2;
	int width, height;
	width = (int)(srcimg.cols*scale / 2.0);
	height = (int)(srcimg.rows*scale / 2.0);
	x1 = max(pt.x - width, 0);
	y1 = max(pt.y - height, 0);
	x2 = min(pt.x + width, srcimg.cols);
	y2 = min(pt.y + height, srcimg.rows);
	Rect zoomRect(Point(x1, y1), Point(x2, y2));
	img = srcimg(zoomRect).clone();

}


void on_mouse(int event, int x, int y, int flags, void* param)
{
	MouseParam *par = (MouseParam*)param;
	Point pt(x, y);
	double value;
	float step = 0.05;

	if (event == EVENT_RBUTTONDOWN) //按下右键,重画
	{
		par->img = par->imgBackup.clone();
	}
	else if (event == EVENT_LBUTTONDOWN)
	{
		par->pt1 = pt;
		par->pt2 = pt;
		par->mouseLflag = true;
	}
	else if (event == CV_EVENT_MOUSEMOVE && flags == CV_EVENT_FLAG_LBUTTON)
	{
		par->pt2 = pt;
	}
	else if (event == CV_EVENT_LBUTTONUP)
	{
		par->pt2 = pt;
		draw_rectangle(par->img, par->pt1, par->pt2);
		//par->imgZoomBackup = par->img.clone();
		par->mouseLflag = false;
	}
	else if (event == CV_EVENT_MOUSEMOVE)
	{
		par->pt1 = pt;
	}
	else if (event == CV_EVENT_MOUSEWHEEL)
	{
		value = getMouseWheelDelta(flags);
		if (value>0)
			par->scale += step;
		else if (value<0)
			par->scale -= step;
		par->scale = max((float)0.3, par->scale);
		par->scale = min((float)1.0, par->scale);
		zoom(par->img, par->imgZoomBackup, par->pt1, par->scale);
	}
}

int main()
{
	//Mat img(512, 512, CV_8UC3, Scalar::all(255));
	Mat img = imread("E:\\bg.jpg");
	MouseParam mouseParam;
	mouseParam.img = img.clone();
	mouseParam.imgBackup = img.clone();
	mouseParam.imgZoomBackup = img.clone();
	mouseParam.mouseLflag = false;
	float step = 0.05;
	mouseParam.scale = 1.0;
	namedWindow(WINNAME, 0);
	setMouseCallback(WINNAME, on_mouse, &mouseParam);
	int key;
	while (1)
	{
		mouseParam.imgTmp = mouseParam.img.clone();
		draw_crossline(mouseParam.imgTmp, mouseParam.pt1);
		if (mouseParam.mouseLflag == true)
			draw_rectangle(mouseParam.imgTmp, mouseParam.pt1, mouseParam.pt2);
		imshow(WINNAME, mouseParam.imgTmp);
		key = waitKey(40);
		if (key == 27)
		{
			break;
		}
		else if (key == toascii('q'))
		{
			mouseParam.scale -= step;
			zoom(mouseParam.img, mouseParam.imgZoomBackup, mouseParam.pt1, mouseParam.scale);
		}
		else if (key == toascii('e'))
		{
			mouseParam.scale += step;
			zoom(mouseParam.img, mouseParam.imgZoomBackup, mouseParam.pt1, mouseParam.scale);
		}
	}

	return 0;
}

效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值