基于opencv的动画操作

opencv动画操作

大家应该熟悉opencv是一个图像处理或者说是计算机视觉库,但是在opencv中有这么一个头文件highgui.h。这个头文件中封装了很多类似windowsGUI的操作,甚至有时候调用起来逻辑更加清晰。

首先这个头文件中封装了一些简单的图形绘画操作:

cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color, int thickness=1, int line_type=8, int shift=0 );


cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 );


cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,int thickness=1, int line_type=8, int shift=0 ;CvSize min_size=cvSize(0,0);CvSize max=cvSize(0,0));


看名字就能看出来,就是一些按照定点画出圆,线,矩形。


那么我们怎么才能用这些基本操作画出复杂的动画UI呢?


我们知道,动画就是一帧一帧渐变的图像,我们是不是可以这么想,如果我每一帧图像都变一点,最后把所有帧都连起来就是个动画呢。


opencv提供这一基础的函数就是cvWaitkey;


char cvWaitkey(int);

这个函数将返回一个char型的值,作为瞬间响应按钮,我们可以利用这个值对动画的动作进行控制。

而括号里的int值就是等待时间,也就是帧和帧之间的间隔时间,单位是ms;

如果int值为0则表示一直等待char类型按键的响应;


那么首先,我们先画两个可以一直变大的圆锥形;

圆锥其实就是由无数个圆组成的,让圆在特定的直线上慢慢变大就可以形成一个圆锥。


	IplImage *img0;
	img0=cvLoadImage("test0.jpg");

		cvNamedWindow("My Window");//建立窗口
		int a=0;
		int b=0;
		int t=0;
		int k=1;

	while(true){
	
		cvCircle(img0,cvPoint(b,a),k,CV_RGB(255,0,255),3);//画圆 
		cvShowImage("My Window", img0);
		cvWaitKey(20); //20ms一帧图像
		a+=2;
		b+=1;	
		k++;//改变控制圆大小

	}
	

基于opencv的动画操作_第1张图片

这就可以动态显示一个类似圆锥的图像动画。


接下来我们就可以玩一些高难度的操作。

opencv中没有定义清除函数,这让非常多的动画方案都难以实现,比如说我要显示下雨,但是画了线以后线就留在了那里,没有消失,会越变越多,不能控制。

那么opencv又可以怎么样去显示可清除动态呢?

这里的核心算法就是cvCloneImage。

我把显示的原图作为克隆源,每显示一张就销毁一张,每次画的都是新的图像,这样就可以成功的绕开所谓的清除函数。


还是以原来的那个圆锥举例,现在就可以显示一个慢慢放大的圆形了;

	IplImage *img0;
	img0=cvLoadImage("test0.jpg");
	IplImage *img1=cvCreateImage(cvGetSize(img0),img0->depth,img0->nChannels);
	

	cvNamedWindow("My Window");
	int a=0;
	int b=0;
	int t=0;
	int k=1;

	while(true){
	
		img1=cvCloneImage(img0);
	
		cvCircle(img1,cvPoint(b,a),k,CV_RGB(255,0,255),3);
		cvShowImage("My Window", img1);
		cvWaitKey(20); 
		a+=2;
		b+=1;
		k++;

	}


下面是效果图

基于opencv的动画操作_第2张图片


最后我们要做一个炫酷的,那就是放大镜。

我们知道放大镜可以跟着鼠标移动,并显示鼠标周围的图像然后放大,这个操作就有些难度了。


我们首先要熟悉鼠标操作,我的另外一篇博客中有写opencv鼠标操作,

这样利于鼠标我们就可以完成这件事了。


首先读入一张图像。

在鼠标函数中复制这张图像,以免在操作时候画在圆图像上。

IplImage *imgx=cvLoadImage("test.jpg");
IplImage *imgcopyx=cvCreateImage(cvGetSize(imgx),imgx->depth,imgx->nChannels);

void onMouse(int Event,int x,int y,int flags,void* param )//====================================响应鼠标点击事件
{
	imgcopyx=cvCloneImage(imgx);
}


设置鼠标回调函数,并且实时获取xy坐标。


我们再设置一个区域作为放大区域,这个区域是围绕着xy坐标的;

cvSetImageROI(imgcopyx , cvRect(x-100,y-100,200,200));


这个区域设置必须加上条件,否则就会让区域超出图像导致程序崩溃;

if (x>=100&&y>=100&&x<=imgcopyx->width-100&&y<=imgcopyx->height-100&&edgeshow);



最后我们再将已经设置好区域的图像拷贝到新的,长宽一致的图像中,画上一些标准线就行了;

cvCircle(rectimg,cvPoint(rectimg->width/2,rectimg->height/2),10,CV_RGB(255,255,255),2);
cvLine(rectimg,cvPoint(0,rectimg->height/2),cvPoint(rectimg->width,rectimg->height/2),CV_RGB(255,0,0),1);
cvLine(rectimg,cvPoint(rectimg->width/2,0),cvPoint(rectimg->width/2,imgx->height),CV_RGB(255,0,0),1);


整个程序大致是这样

IplImage *imgx=cvLoadImage("test.jpg");
IplImage *imgcopyx=cvCreateImage(cvGetSize(imgx),imgx->depth,imgx->nChannels);

void onMouse(int Event,int x,int y,int flags,void* param )//====================================响应鼠标点击事件
{
	/*printf("( %d, %d) ",x,y);
	printf("The Event is : %d ",Event);
	printf("The flags is : %d ",flags);
	printf("The param is : %d\n",param);*/
	imgcopyx=cvCloneImage(imgx);
	IplImage *rectimg=cvCreateImage(cvSize(200,200),imgcopyx->depth,imgcopyx->nChannels);
	if (x>=100&&y>=100&&x<=imgcopyx->width-100&&y<=imgcopyx->height-100&&edgeshow)
	{
		cvSetImageROI(imgcopyx , cvRect(x-100,y-100,200,200));
		
		cvCopy(imgcopyx,rectimg); 
		cvCircle(rectimg,cvPoint(rectimg->width/2,rectimg->height/2),10,CV_RGB(255,255,255),2);
		cvLine(rectimg,cvPoint(0,rectimg->height/2),cvPoint(rectimg->width,rectimg->height/2),CV_RGB(255,0,0),1);
		cvLine(rectimg,cvPoint(rectimg->width/2,0),cvPoint(rectimg->width/2,imgx->height),CV_RGB(255,0,0),1);

		cvNamedWindow("辅助操作窗口",0);
		cvResizeWindow("辅助操作窗口",rectimg->width*1.5,rectimg->height*1.5);
		cvMoveWindow("辅助操作窗口",x+100,y-300);
		//cvMoveWindow("辅助操作窗口",imgcopyx->width+200,imgcopyx->height-300);
		cvShowImage("辅助操作窗口",rectimg);
		
	}
	cvReleaseImage(&rectimg);
	cvReleaseImage(&imgcopyx);
}

效果有些像某些输入法的放大功能,如下:

 基于opencv的动画操作_第3张图片

炫酷吧,其实opencv里面的GUI操作并不少,就看怎么样去结合,去实现自己想要的算法。

很多动画很多事情分解开来其实都很简单。


reference:

http://baike.baidu.com/







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