机器视觉学习笔记(10)——使用鼠标获取像素点信息

机器视觉学习笔记(10)——使用鼠标获取像素点信息

标签: 机器视觉

1.目标

使用鼠标对关键点BGR进行采集,采集的数据有正数据和负数据,正数据是需要收集的数据,使用鼠标左键采集,采集后用绿色的圆圈表示;负数据是摈弃的数据,使用鼠标右键采集,采集后用红色的圆圈表示。

2.代码实现

主要通过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();
}

采集了几个点,效果如下:
机器视觉学习笔记(10)——使用鼠标获取像素点信息_第1张图片

3.拓展

通过代码可以发现,鼠标事件通过枚举变量来区分,那么我们右键查看一下定义,看看都有哪些枚举变量。

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个判断分支,分别表示这些事件发生

  • 左键按下分支:记录矩形起点
  • 鼠标移动分支:画出起点到当前点的矩形
  • 左键弹起分支:结束画矩形,起点清零

4.总结

  • 使用鼠标在窗口中对图像进行操作通过OpenCV在该窗口下的回调函数实现
  • 可以通过OpenCV提供的事件枚举变量任意组合自己想要的功能
  • 如果不想改变源图像,常常深拷贝一份数据来操作
  • 窗口坐标与其对应的矩阵坐标刚好是相反的
  • 在MFC和Qt中可以利用控件的特性来实现

你可能感兴趣的:(机器视觉)