www.pudn.com > circleDetection.rar > circledetection.cpp


// readbmp.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
#include  
 
#include "ipl.h" 
#include "cv.h" 
#include "_cv.h" 
#include "vlgrfmts.h" 
 
//----------------------------- 
////////UTILITY FUNCTIONS 
// 
// Read in a BMP and convert it into an IPL 
// fin The file name of the BMP with path 
// plannar If set, convert the image to plannar 
// flip If set, mirror the image around the horizontal axis, set 
// IPL_ORIGIN_BL) 
IplImage * readBMP2IPL(char *fin, int plannar = 0, int flip = 0) 
{ 
	int filter; 
	int width=0,height=0,color=55,hdr_ret=0,close_ret = 0,rd_ret = 0; 
	IplImage *I; 
	filter = gr_fmt_find_filter(fin ); //Get file type 
	hdr_ret = gr_fmt_read_header( filter, &width, &height, &color );//image params 
	I = cvCreateImageHeader( cvSize(width, height), IPL_DEPTH_8U, 3); //create image header 
	I->align = IPL_ALIGN_QWORD; //fix the problem that cvCreateImage uses align 4 
	I->depth != IPL_DEPTH_32F ? iplAllocateImage( I, 0, 0 ) :iplAllocateImageFP( I, 0, 0 ); 
	rd_ret = gr_fmt_read_data(filter, I->imageData, I->widthStep, color); //read in the data, origin TL 
	close_ret = gr_fmt_close_filter( filter ); 
	if(plannar) //If plannar order desired, turn it into plannar order 
	{ 
		IplImage *Ip = iplCreateImageHeader(3, 0, IPL_DEPTH_8U, "RGB","BGR", IPL_DATA_ORDER_PLANE, I->origin, IPL_ALIGN_QWORD, width, height, NULL,NULL,NULL,NULL); 
		iplAllocateImage(Ip, 0,0); 
		iplConvert(I,Ip); 
		cvReleaseImage( &I ); 
		I = Ip;  
	} 
	if(flip) //User wants IPL_ORIGIN_BL 
	{ 
		iplMirror(I, I, 0); //flipporuni 
		I->origin = IPL_ORIGIN_BL; 
	} 
	return I; 
} 
 
////////////////////////////////////////// 
// Write IPL image to disk as a BMP image (not optimized but step by step simplistic) 
// fout Path\filename to write to 
// I IPL image to be written 
// 
// Image fomat may be any of: 
// dataOrder Plane or Pixel 
// 1 channel (GRAY) or 3 (RGB) 
// 8U, 8S, 32F 
// Origin TL or BL (if BL, image is flipped to conform to TL bmps) 
// 
// If image is not RGB or GRAY, RGB is simply imposed on the Image. E.g. if it's YUV, 
// the image will be stored as BGR with B=Y, G=U, and R=V 
void writeIPL2BMP(char *fout, IplImage *I) 
{ 
	IplImage *Isav,*Itmp; 
	Isav = iplCloneImage(I); 
	//Convert to pixel order if needed 
	if(I->dataOrder == IPL_DATA_ORDER_PLANE) 
	{ 
		Itmp = iplCreateImageHeader(I->nChannels, 
			I->alphaChannel, I->depth, I->colorModel, 
			I->channelSeq, IPL_DATA_ORDER_PIXEL, I->origin, 
			I->align, 
			I->width, I->height, NULL, NULL,NULL,NULL); 
		if(I->depth == IPL_DEPTH_32F) 
			iplAllocateImageFP(Itmp, 1,0.0); 
		else 
			iplAllocateImage(Itmp, 1,0); 
		iplConvert(I, Itmp); 
		iplDeallocate (I, IPL_IMAGE_ALL); 
		I = Itmp; 
	} 
	//Image is now pixel order. Convert to 8U if needed. 
	if(I->depth == IPL_DEPTH_8S) 
		I->depth = IPL_DEPTH_8U; 
	else if(I->depth == IPL_DEPTH_32F) 
	{  
		float min,max; 
		iplMinMaxFP (I, &min, &max); 
		Itmp = iplCreateImageHeader(I->nChannels, 
			I->alphaChannel, IPL_DEPTH_8U, I->colorModel, 
			I->channelSeq, IPL_DATA_ORDER_PIXEL, I->origin, 
			I->align, 
			I->width, I->height, NULL, NULL,NULL,NULL); 
		iplAllocateImage(Itmp, 1,0); 
		if(min >= max) max = (float)(min + 1.0); 
		iplScaleFP (I, Itmp, min, max); 
		iplDeallocate (I, IPL_IMAGE_ALL); 
		I = Itmp; 
	} 
	//Image is now pixel order, 8U. Convert to RGB if needed 
	if(I->nChannels == 3) 
	{ 
		strcpy(I->colorModel,"RGB"); 
		strcpy(I->channelSeq,"BGR"); 
	} 
	else if(I->nChannels == 1) 
	{ 
		Itmp = iplCreateImageHeader(3, 
			I->alphaChannel, IPL_DEPTH_8U, "RGB", 
			"BGR", IPL_DATA_ORDER_PIXEL, I->origin, I->align, 
			I->width, I->height, NULL, NULL,NULL,NULL); 
		iplAllocateImage(Itmp, 1,0); 
		iplGrayToColor (I, Itmp, 1.0, 1.0, 1.0); 
		iplDeallocate (I, IPL_IMAGE_ALL); 
		I = Itmp; 
	} 
	else 
		return; 
	//Image is now pixel order, 8U, RGB, flip it if the origin is BL 
	if(I->origin == IPL_ORIGIN_BL) 
	{ 
		iplMirror(I, I, 0); 
	} 
	//FINALLY, WRITE THE IMAGE: 
	int write_ret = gr_fmt_write_image( I->imageData, I->widthStep,  
		I->width, I->height, I->colorModel[0] =='R'?1:0,fout, "bmp"); 
	//Return image to its original state 
	iplDeallocate(I, IPL_IMAGE_ALL); 
	I = Isav; 
} 
 
//----------------------------- 
 
void main() 
{ 
	IplImage * input_img=NULL; 
	int plannar=0; 
	int flip=0; 
	char fin[]="circles.bmp"; 
	char fout[]="result.bmp"; 
	 
	 
	//作一些声明 
	CvMemStorage *storage; 
	int header_size, i, count,length, width; 
	CvSeq *contour; 
	CvBox2D * myBox;  //用于画圆和椭圆 
	CvPoint *PointArray; 
	CvPoint2D32f *PointArray32f; 
	CvPoint myCenter; 
	 
	// 分配内存        
	myBox= (CvBox2D *) malloc(sizeof(CvBox2D)); 
	header_size = sizeof(CvContour); 
	storage = cvCreateMemStorage (1000); // For FindContours. 
	 
	// 读入图象input_img并转换为IPLIMAGE格式 
	//已经定义	char fin[]="circles.bmp"; 
	input_img=readBMP2IPL(fin,plannar, flip); 
 
	cout<<" The following is the attribute for current image:\n"; 
	cout<<"Num of channels: "<< input_img->nChannels<depth<colorModel<channelSeq<dataOrder<origin<width<height<width; 
	int h = input_img->height; 
	//创建临时图象,m_tmp8uC1用于"CANNY",m_tmp8uC3用于预处理 
	 
	//这个m_tmp8uC1用于CANNY - 1 CHANNEL (灰度) 
	//与输入的input_img大小一样 
	IplImage* m_tmp8uC1= cvCreateImage( 
		cvSize(w ,h ),    
		IPL_DEPTH_8U,1); //灰度图象 
	 
	//这个用于预处理- 3 CHANNEL (彩色) 
	//大小同输入的input_img 
	IplImage* m_tmp8uC3= cvCreateImage(                           
		cvSize( w ,h),   
		IPL_DEPTH_8U,3); //彩色图象 
	 
	 
	//预处理 
	//这里使用简单的BLUR来去除噪声,使用简单的邻域平均方法进行线性滤波 
	iplBlur(input_img,m_tmp8uC3, 2,2,1,1); 
	 
	//将结果转换为灰度图象m_tmp8uC1 
	iplColorToGray(m_tmp8uC3, m_tmp8uC1); 
	 
	//释放临时的彩色图象m_tmp8uC3 
	cvReleaseImage(&m_tmp8uC3); 
	 
	// 第一个关键方程 
	// CANNY边缘检测,结果是黑白图象,其中白色表示轮廓 
	 
 
	 
	//第二个关键方程,该方程分离出所有轮廓。查看文档说明 
	int number_of_c=cvFindContours (m_tmp8uC1 , storage, &contour, 
		header_size, CV_RETR_EXTERNAL, 
		CV_CHAIN_APPROX_SIMPLE); 
	 
	cout<<"number: "<total;//序列元素的总数,即轮廓上点的总数 
			 
			//分配内存 
			PointArray = (CvPoint *)malloc(count * sizeof(CvPoint)); 
			 
			//COPY THE POINTS TO A ARRAY 
			//将序列拷入一个连续的缓存中 
			cvCvtSeqToArray(contour, PointArray, CV_WHOLE_SEQ); 
			 
			// ALLOC MEM 
			PointArray32f = (CvPoint2D32f *) 
				malloc((count + 1) * sizeof(CvPoint2D32f)); 
			 
			//CONVERT THE ARRAY TO A 2ND (32FLOAT) 
			// 这个用于cvFitELLIPSE 
			 
			for (i=0; i=7) 
			{ 
				//FIND THE BEST FITTING ELLIPSE IN THIS CONTOUR 
				//找出在这个轮廓中最适合的椭圆 
				cvFitEllipse(PointArray32f, count,myBox); 
				 
				//从"myBox"中提出结果 
 
				//CENTER 
				//中心 
				myCenter.x = (int) myBox->center.x; 
				myCenter.y = (int) myBox->center.y; 
				 
				//HEIGHT AND WITH (THE 2 AXES OF THE ELLIPSE) 
				length  =(int)myBox->size.height; 
				width = (int)myBox->size.width; 
				 
				//AND THE ANGLE 
				float myAngle= myBox->angle; 
				 
				// 检查这个椭圆是否在图象内 
				if ((myCenter.x > 0) && (myCenter.y >0)) 
				{       
					//画圆 
					cvCircle(input_img,myCenter,(int)length/2 ,RGB(255,0,0),1); 
					 
					//画椭圆 
					cvEllipse(input_img, 
						myCenter, 
						cvSize ((int)width/2,(int)length/2) , 
						myBox->angle, 
						0,360,RGB(255,0,255),1); 
				} 
				 
			} 
			free(PointArray32f ); 
			free(PointArray ); 
		} 
		// GOT TO THE NEXT CONTOUR (IF ANY) 
		//取下一个轮廓 
		contour = contour->h_next; 
	} 
				 
				 
	free (contour); 
	free (myBox);             
	cvReleaseImage(&m_tmp8uC1); 
	cvReleaseMemStorage(&storage); 
 
	writeIPL2BMP(fout,input_img);//已定义	char fout[]="result.bmp"; 
				 
}