realkate1

导航

OpenCV之响应鼠标(一):利用鼠标获取坐标

好久没有更新博客了,今天临时起意,将以前写的示例代码整理了一下,暂且发布一篇,希望对大家有用!

代码一:点击时显示坐标,鼠标移动时不显示。

#include <cv.h>
#include <highgui.h>
#include <stdio.h>

IplImage* src=0;
void on_mouse( int event, int x, int y, int flags, void* ustc)
{
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);
		
	if( event == CV_EVENT_LBUTTONDOWN )
	{
		CvPoint pt = cvPoint(x,y);
		char temp[16];
		sprintf(temp,"(%d,%d)",pt.x,pt.y);
		cvPutText(src,temp, pt, &font, cvScalar(255, 255, 255, 0));
		cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );
		cvShowImage( "src", src );
	} 
}

int main()
{
	src=cvLoadImage("lena.jpg",1);

	cvNamedWindow("src",1);
	cvSetMouseCallback( "src", on_mouse, 0 );
	
	cvShowImage("src",src);
	cvWaitKey(0); 
	cvDestroyAllWindows();
	cvReleaseImage(&src);

	return 0;
}

  代码二:鼠标移动时显示坐标,点击时不显示坐标

#include <cv.h>
#include <highgui.h>
#include <stdio.h>

IplImage* src=0;
IplImage* dst=0;
void on_mouse( int event, int x, int y, int flags, void* ustc)
{
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);
		
	if( event == CV_EVENT_MOUSEMOVE )
	{
		cvCopy(dst,src);

		CvPoint pt = cvPoint(x,y);

		char temp[16];
		sprintf(temp,"(%d,%d)",pt.x,pt.y);

		cvPutText(src,temp, pt, &font, cvScalar(255, 255, 255, 0));
		cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );
		cvShowImage( "src", src );
	} 
}

int main()
{
	src=cvLoadImage("lena.jpg",1);
	dst=cvCloneImage(src);

	cvNamedWindow("src",1);
	cvSetMouseCallback( "src", on_mouse, 0 );
	
	cvShowImage("src",src);
	cvWaitKey(0); 
	cvDestroyAllWindows();
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	return 0;
}

  代码三:鼠标移动和点击时均显示坐标

#include <cv.h>
#include <highgui.h>
#include <stdio.h>

IplImage* src=0;
IplImage* dst=0;
void on_mouse( int event, int x, int y, int flags, void* ustc)
{
	char temp[16];
	CvPoint pt;
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);
		
	if( event == CV_EVENT_MOUSEMOVE )
	{
		cvCopy(dst,src);		
		sprintf(temp,"(%d,%d)",x,y);
		pt = cvPoint(x,y);
		cvPutText(src,temp, pt, &font, cvScalar(255, 255, 255, 0));
		cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );
		cvShowImage( "src", src );
	} 
	else if( event == CV_EVENT_LBUTTONDOWN )
	{
		//cvCopy(dst,src);			
		sprintf(temp,"(%d,%d)",x,y);
		pt = cvPoint(x,y);
		cvPutText(src,temp, pt, &font, cvScalar(255, 255, 255, 0));
		cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );
		cvCopy(src,dst);
		cvShowImage( "src", src );
	} 
}

int main()
{
	src=cvLoadImage("lena.jpg",1);
	dst=cvCloneImage(src);

	cvNamedWindow("src",1);
	cvSetMouseCallback( "src", on_mouse, 0 );
	
	cvShowImage("src",src);
	cvWaitKey(0); 
	cvDestroyAllWindows();
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	return 0;
}

  代码四,上面的代码在边界处处理的不好,坐标值显示的不完全,下面是对代码三的改进。下面的代码还将点约束在图像的几何区域范围内。

#include <cv.h>
#include <highgui.h>
#include <stdio.h>

#define max(a,b)            (((a) > (b)) ? (a) : (b))
#define min(a,b)            (((a) < (b)) ? (a) : (b))

//注意参数是有符号短整型,该函数的作用是使i限定为[a,b]区间内
int bound(short i,short a,short b)
{
	return min(max(i,min(a,b)),max(a,b));
}

IplImage* src=0;
IplImage* dst=0;

void on_mouse( int event, int x, int y, int flags, void* ustc)
{
	char temp[16];
	CvPoint pt;
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);
	CvPoint tmp_pt = {-1,-1};
	CvSize text_size;
	int baseline;

	if( event == CV_EVENT_MOUSEMOVE )
	{
		cvCopy(dst,src);	

		x=bound(x,0,src->width-1);
		y=bound(y,0,src->height-1);
		pt = cvPoint(x,y);
		cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );

		sprintf(temp,"(%d,%d)",x,y);
		cvGetTextSize(temp,&font,&text_size,&baseline);
		tmp_pt.x = bound(pt.x,0,src->width-text_size.width);
		tmp_pt.y = bound(pt.y,text_size.height+baseline,src->height-1-baseline);
		cvPutText(src,temp, tmp_pt, &font, cvScalar(255, 255, 255, 0));

		cvShowImage( "src", src );
	} 
	else if( event == CV_EVENT_LBUTTONDOWN )
	{
		//cvCopy(dst,src);

		pt = cvPoint(x,y);
		cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );

		sprintf(temp,"(%d,%d)",x,y);
		cvGetTextSize(temp,&font,&text_size,&baseline);
		tmp_pt.x = bound(pt.x,0,src->width-text_size.width);
		tmp_pt.y = bound(pt.y,text_size.height+baseline,src->height-1-baseline);
		cvPutText(src,temp, tmp_pt, &font, cvScalar(255, 255, 255, 0));

		cvCopy(src,dst);
		cvShowImage( "src", src );
	} 
}

int main()
{
	src=cvLoadImage("lena.jpg",1);
	dst=cvCloneImage(src);

	cvNamedWindow("src",1);
	cvSetMouseCallback( "src", on_mouse, 0 );
	
	cvShowImage("src",src);
	cvWaitKey(0); 
	cvDestroyAllWindows();
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	return 0;
}

  代码五,上面的代码不能撤销选定的坐标,下面的代码对此进行了改进,右击撤销最近选择的点,并用互补的颜色表示选择的点和撤销选定的点。除此之外还将选择的坐标输出到文件。在点的坐标前还有一个数表示点的选定次序。

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <vector>
#include <fstream>
using namespace std;

#define max(a,b)            (((a) > (b)) ? (a) : (b))
#define min(a,b)            (((a) < (b)) ? (a) : (b))

//注意参数是有符号短整型,该函数的作用是使i限定为[a,b]区间内
int bound(short i,short a,short b)
{
	return min(max(i,min(a,b)),max(a,b));
}

CvScalar getInverseColor(CvScalar c)
{
	CvScalar s;
	for(int i=0;i<=2;++i)
	{
		s.val[i]=255-c.val[i];
	}
	return s;
}

IplImage* src=0;
IplImage* dst=0;
int n=0;
vector<CvPoint> points;

void on_mouse( int event, int x, int y, int flags, void* ustc)
{
	CvPoint pt;
	CvPoint tmp_pt = {-1,-1};
	CvFont font;
	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.4, 0.4, 0, 1, CV_AA);
	char temp[16];
	CvSize text_size;
	int baseline;

	CvScalar clrPoint=cvScalar(255,0,0,0);
	CvScalar clrText=cvScalar(255, 255, 255, 0);

	if( event == CV_EVENT_MOUSEMOVE )
	{
		cvCopy(dst,src);	

		x=bound(x,0,src->width-1);
		y=bound(y,0,src->height-1);
		pt = cvPoint(x,y);
		cvCircle( src, pt, 2,clrPoint ,CV_FILLED, CV_AA, 0 );

		sprintf(temp,"%d (%d,%d)",n+1,x,y);
		cvGetTextSize(temp,&font,&text_size,&baseline);
		tmp_pt.x = bound(pt.x,0,src->width-text_size.width);
		tmp_pt.y = bound(pt.y,text_size.height+baseline,src->height-1-baseline);
		cvPutText(src,temp, tmp_pt, &font, clrText);

		cvShowImage( "src", src );
	} 
	else if( event == CV_EVENT_LBUTTONDOWN)
	{
		pt = cvPoint(x,y);
		points.push_back(pt); n++;
		cvCircle( src, pt, 2, clrPoint ,CV_FILLED, CV_AA, 0 );

		sprintf(temp,"%d (%d,%d)",n,x,y);
		cvGetTextSize(temp,&font,&text_size,&baseline);
		tmp_pt.x = bound(pt.x,0,src->width-text_size.width);
		tmp_pt.y = bound(pt.y,text_size.height+baseline,src->height-1-baseline);
		cvPutText(src,temp, tmp_pt, &font, clrText);

		cvCopy(src,dst);
		cvShowImage( "src", src );
	} 
	else if( event == CV_EVENT_RBUTTONDOWN )
	{
		if(!points.empty())
		{
			cvCopy(dst,src);

			pt=points.back();
			points.pop_back(); 
			cvCircle( src, pt, 2, getInverseColor(clrPoint),CV_FILLED, CV_AA, 0 );

			sprintf(temp,"%d (%d,%d)",n,pt.x,pt.y); --n;
			cvGetTextSize(temp,&font,&text_size,&baseline);
			tmp_pt.x = bound(pt.x,0,src->width-text_size.width);
			tmp_pt.y = bound(pt.y,text_size.height+baseline,src->height-1-baseline);
			cvPutText(src,temp, tmp_pt, &font, getInverseColor(clrText));

			cvCopy(src,dst);
			cvShowImage( "src", src );
		}
	}
}

int main()
{
	src=cvLoadImage("lena.jpg",1);
	dst=cvCloneImage(src);

	cvNamedWindow("src",1);
	cvSetMouseCallback( "src", on_mouse, 0 );
	
	cvShowImage("src",src);
	cvWaitKey(0); 
	cvDestroyAllWindows();
	cvReleaseImage(&src);
	cvReleaseImage(&dst);

	ofstream file("sample.txt");
	if(!file)
	{
		cout << "open file error!";
		return 1;
	}
	vector<CvPoint>::iterator it=points.begin();
	for(;it!=points.end();++it)
	{
		file<< it->x<<','<<it->y<<endl;
	}
	file<<endl;
	file.close();

	return 0;
}

  其的演示如下:

sample.txt中的内容如下:

319,351
382,284
275,292
194,249
357,210
424,260
350,251
305,238
274,189
227,140
224,375

  

转自:http://blog.csdn.net/quarryman/article/details/8450387

posted on 2015-09-14 14:45  realkate1  阅读(4445)  评论(0编辑  收藏  举报