标签: 机器视觉
使用鼠标对关键点BGR进行采集,采集的数据有正数据和负数据,正数据是需要收集的数据,使用鼠标左键采集,采集后用绿色的圆圈表示;负数据是摈弃的数据,使用鼠标右键采集,采集后用红色的圆圈表示。
主要通过OpenCV中的回调函数实现,采集的数据存储在data.txt中。需要注意的是,窗口横轴为X轴,竖轴为Y轴,坐标是(x, y),而矩阵坐标是按照(row, col),故窗口中的点(x, y)对应的值在矩阵中为(y, x)
void mouseHandler(int event, int x,int y ,int flags,void *p)
{
Mat img0(*(Mat*)p);
static Mat img1= img0.clone();//不改变源图像,并且能够显示已标记的点
if(event==CV_EVENT_LBUTTONDOWN)//鼠标左键按下,正数据
{
Point point(x, y);
circle(img1, point, 3, Scalar(0, 255, 0));
//记录数据,显示img1,数据却从原始图像采集,窗口的x, y轴和图像的行和列相反
ofstream file("data.txt", fstream::out | fstream::app);
int b = img0.at<Vec3b>(y, x)[0];
int g = img0.at<Vec3b>(y, x)[1];
int r = img0.at<Vec3b>(y, x)[2];
file<<b<<","<<g<<","<<r<<","<<"1"<<endl;
cout<<b<<","<<g<<","<<r<<","<<"0"<<endl;
//显示图像
imshow("CollectSamplePoints",img1);
}
else if (event==CV_EVENT_RBUTTONDOWN)//鼠标右键按下,负数据
{
Point point(x, y);
circle(img1, point, 3, Scalar(0, 0, 255));
//记录数据
ofstream file("data.txt", fstream::out | fstream::app);
int b = img0.at<Vec3b>(y, x)[0];
int g = img0.at<Vec3b>(y, x)[1];
int r = img0.at<Vec3b>(y, x)[2];
file<<b<<","<<g<<","<<r<<","<<"0"<<endl;
cout<<b<<","<<g<<","<<r<<","<<"0"<<endl;
//显示图像
imshow("CollectSamplePoints",img1);
}
}
void collect_sample_points(string fileName)
{
Mat img = imread(fileName);
namedWindow("CollectSamplePoints");
cvSetMouseCallback("CollectSamplePoints", mouseHandler, (void*)&img);
mouseHandler(0, 0, 0, 0, &img);
imshow("CollectSamplePoints", img);
waitKey();
}
通过代码可以发现,鼠标事件通过枚举变量来区分,那么我们右键查看一下定义,看看都有哪些枚举变量。
enum
{
CV_EVENT_MOUSEMOVE =0,//移动
CV_EVENT_LBUTTONDOWN =1,//左键按下
CV_EVENT_RBUTTONDOWN =2,//右键按下
CV_EVENT_MBUTTONDOWN =3,//中键按下
CV_EVENT_LBUTTONUP =4,//左键弹起
CV_EVENT_RBUTTONUP =5,//右键弹起
CV_EVENT_MBUTTONUP =6,//中键弹起
CV_EVENT_LBUTTONDBLCLK =7,//左键点击
CV_EVENT_RBUTTONDBLCLK =8,//右键点击
CV_EVENT_MBUTTONDBLCLK =9 //中键点击
};
鼠标事件一共有10个,其实还有双击事件,不过这里并没有提供相应的枚举变量。
试想如果想要在窗口上面画一个矩形,是一个什么过程?左键按下->移动->左键弹起。
那么回调函数中需要做3个判断分支,分别表示这些事件发生