我们在做小型项目的时候,有时为了实现良好的交互,或者更方便实时观察输入数据,通常需要使用到下列几项功能:
1.利用鼠标在所显示的图像/视频中选取ROI区域
2.实时显示鼠标所点击位置处的坐标信息
本文贴出的代码实现了上述功能,代码如下:
/*利用鼠标的响应函数实现功能*/
//在图片上画框并且鼠标放置画面位置处显示坐标
#include<iostream>
#include<opencv2/opencv.hpp>
#include <string>
using namespace cv;
using namespace std;
Rect box;//矩形对象
bool drawing_box=false;//记录是否在画矩形对象
Point leftTop;
Point mouseOn;
void help(){
cout<<"/************************************************/"<<endl;
cout<<"draw a rect using mouse and return a location when your mouse putted on it"<<endl;
}
void onmouse(int event, int x, int y, int flag, void *img)//鼠标事件回调函数,鼠标点击后执行的内容应在此
{
if(drawing_box){
box.width = x-leftTop.x;//获取矩形宽度
box.height=y-leftTop.y;//获取矩形高度
}
switch (event)
{
case CV_EVENT_LBUTTONDOWN://鼠标左键按下事件
drawing_box = true;
leftTop.x=x;
leftTop.y=y;
box = Rect(x, y, 0, 0);
break;
case CV_EVENT_MOUSEMOVE://鼠标移动事件
mouseOn.x=x;
mouseOn.y=y;
break;
case CV_EVENT_LBUTTONUP://鼠标左键松开事件
drawing_box = false;//不在画矩形
if (box.width<0){//排除宽为负的情况,在这里判断是为了优化计算,不用再移动时每次更新都要计算长宽的绝对值
box.x = box.x + box.width;//更新原点位置,使之始终符合左上角为原点
box.width = -1 * box.width;//宽度取正
}
if (box.height<0){//同上
box.y = box.y + box.height;
box.height = -1 * box.width;
}
break;
default:
break;
}
}
int main()
{
help();
Mat img = imread("mini.jpeg");//读取图像
Mat temp;
namedWindow("鼠标画个框");//窗口
setMouseCallback("鼠标画个框", onmouse,&img);
imshow("鼠标画个框", img);
while (1)
{
if (drawing_box){//不断更新正在画的矩形
img.copyTo(temp);//这句放在这里是保证了每次更新矩形框都是在没有原图的基础上更新矩形框。
rectangle(temp,Point(box.x, box.y),Point(box.x+box.width,box.y+box.height),Scalar(255,255,255));
stringstream sx;
stringstream sy;
sx<<mouseOn.x;
sy<<mouseOn.y;
string txt="("+sx.str()+","+sy.str()+")";
circle(temp,mouseOn,1,Scalar(0,255,0),1);
putText(temp,txt,mouseOn-Point(2,2), FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,255),2);
imshow("鼠标画个框",temp);//显示
waitKey(10);
}
if (waitKey(30) == 27) {//检测是否有按下退出键
break;//退出程序
}
}
return 0;
}
代码粘贴可用,实时效果图如下: