⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aglrothim.cpp

📁 用于系统跟踪的程序
💻 CPP
字号:
#include "stdafx.h"
#include "aglrothim.h"
#include "cv.h"
#include "ConnArea.h"

//计算角度
double getAngle(CvPoint pt1,CvPoint pt2,CvPoint pt3)
{
	double c=getDistance(pt1,pt2);
	double b=getDistance(pt2,pt3);
	double a=getDistance(pt3,pt1);

	double A=acos((b*b+c*c-a*a)/(2*b*c));
	return A;
}


//平均化数据处理
double DataProc(double NewValue,double* Values,int ProcNumber,double errThr,double pocThr)
{
	double diff=abs(NewValue-Values[ProcNumber-1]);
	if(diff<pocThr)
	{
		double avgValue=0;
		for(int i=0;i<ProcNumber-1;i++)
		{
			Values[i]=Values[i+1];
			avgValue=avgValue+Values[i];
		}
		Values[ProcNumber-1]=NewValue;
		avgValue=avgValue+NewValue;
		avgValue=avgValue/ProcNumber;
		return  avgValue;
	}else if(diff<errThr)
	{
		double avgValue=0;
		for(int i=0;i<ProcNumber;i++)
		{
			Values[i]=Values[ProcNumber-1]+(NewValue-Values[ProcNumber-1])/3;
		}
		return Values[ProcNumber-1];
	}
	
}
//计算两个直线交点
CvPoint getPointOfIntersection(double wx1,double wy1,double x01,double y01,double wx2,double wy2,double x02,double y02)
{
	CvPoint Pt; 
	Pt.x=(int)(wx2*(wy1*(x01-x02)+wx1*(y02-y01))/(wx2*wy1-wy2*wx1)+x02);
	Pt.y=(int)(wy2*(wy1*(x01-x02)+wx1*(y02-y01))/(wx2*wy1-wy2*wx1)+y02);
	return Pt;
}

//实现从wx,wy,x,y 到k,b 的转换
void getKB(double wx,double wy,double x,double y,double &k, double &b)
{
	k=wy/wx;
	b=y-k*x;
}
//计算点到直线距离
double getDistanceToLine(double x,double y,double k,double b)
{  
	return abs(k*x-y+b)/sqrt(k*k+1);
}

//计算距离
double getDistance(double x1,double y1,double x2,double y2)
{
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double getDistance(CvPoint p1,CvPoint p2)
{
	return(getDistance(p1.x,p1.y,p2.x,p2.y));
}

// 返回多边形面积(unsigned)
double GetAreaOfPolygon(int vcount,CvPoint polygon[]) 
{ 
	int i; 
	double s; 
	if (vcount<3) return 0; 
	s=polygon[0].y*(polygon[vcount-1].x-polygon[1].x); 
	for (i=1;i<vcount;i++) 
	s+=polygon[i].y*(polygon[(i-1)].x-polygon[(i+1)%vcount].x); 
	return s/2; 
}

double getAreaOfRectangle(double x0,double y0,double x1,double y1,double x2,double y2,double x3,double y3)
{
	CvPoint polygon[4];
	polygon[0].x=(int)x0;
	polygon[0].y=(int)y0;

	polygon[1].x=(int)x1;
	polygon[1].y=(int)y1;

	polygon[2].x=(int)x2;
	polygon[2].y=(int)y2;

	polygon[3].x=(int)x3;
	polygon[3].y=(int)y3;

	return abs(GetAreaOfPolygon(4,polygon));
}
//计算三角形面积
double getAreaOfTriangle(CvPoint Pt1,CvPoint Pt2,CvPoint Pt3)
{
	return getAreaOfTriangle(Pt1.x,Pt1.y,Pt2.x,Pt2.y,Pt3.x,Pt3.y);
}
double getAreaOfTriangle(double x0,double y0,double x1,double y1,double x2,double y2)
{
	CvPoint polygon[3];

	polygon[0].x=(int)x0;
	polygon[0].y=(int)y0;

	polygon[1].x=(int)x1;
	polygon[1].y=(int)y1;

	polygon[2].x=(int)x2;
	polygon[2].y=(int)y2;

	return  GetAreaOfPolygon(3,polygon);
	 
}

//计算三角形面积,包含正负
double getAreaOfTriangleNoAbs(double x0,double y0,double x1,double y1,double x2,double y2)
{
	CvPoint polygon[3];

	polygon[0].x=(int)x0;
	polygon[0].y=(int)y0;

	polygon[1].x=(int)x1;
	polygon[1].y=(int)y1;

	polygon[2].x=(int)x2;
	polygon[2].y=(int)y2;

	return GetAreaOfPolygon(3,polygon);
	 
}


//点是否在四边形内

bool inArea(double x,double y,double x0,double y0,double x1,double y1,double x2,double y2,double x3,double y3)
{
	double s=getAreaOfRectangle(x0,y0,x1,y1,x2,y2,x3,y3);
	double s1=0;
	s1=s1+getAreaOfTriangle(x,y,x0,y0,x1,y1);
	s1=s1+getAreaOfTriangle(x,y,x1,y1,x2,y2);
	s1=s1+getAreaOfTriangle(x,y,x2,y2,x3,y3);
	s1=s1+getAreaOfTriangle(x,y,x3,y3,x0,y0);
 
	/*if(abs(s-s1)<5)
		return true;
	else
		return false;*/
	if(abs(s-s1)<15)
		return true;
	else
		return false;
}

bool inArea4(CvPoint pt,CvPoint* pts)
{
	return inArea(pt.x,pt.y,pts[0].x,pts[0].y,pts[1].x,pts[1].y,pts[2].x,pts[2].y,pts[3].x,pts[3].y);
}

//OpenCV直线拟合
void GetLine(CvPoint*  points,long lCount,float &wx,float &wy,float &x0,float &y0)
{    
	if(lCount==0)return; 
	CvPoint2D32f* points2D = new CvPoint2D32f[lCount];
	for(int i=0;i<lCount;i++)
	{
		points2D[i].x=(float)points[i].x; 
		points2D[i].y=(float)points[i].y; 
	}

	CvDisType distType = CV_DIST_L12;
    float reps = 0.0f, aeps = 0.0f;
	float line[6];
	cvFitLine2D(points2D, lCount, distType, 0, reps, aeps, line);
	delete points2D;

	wx=line[0];
	wy=line[1];
	x0=line[2];
	y0=line[3];
	
}
//最小二乘法直线拟合
//
//void GetLine(CvPoint*  points,long lCount,double &k,double &b,bool isTurnXY)
//{
//	//最小二乘法直线拟合
//	//m_FoldList为关键点(x,y)的链表
//	//拟合直线方程(Y=kX+b)
// 	if(lCount<2)return ;
//	 
//  
//	double mX,mY,mXX,mXY,n;
//	mX=mY=mXX=mXY=0;
//	n=lCount;
//
//	double posX=0;
//	double posY=0;
//
//	if(!isTurnXY)
//	{
//		posX=points[0].x;
//		posY=points[0].y;
//	
//
//	}
//	else
//	{
//		posX=points[0].y;
//		posY=points[0].x;
//	}
//
//	int i=0;
//	while(i<n)
//	{
//		if(!isTurnXY)
//		{
//			posX=points[i].x;
//			posY=points[i].y;
//			
//			//if(xMin>points[i].x)xMin=points[i].x;
//			//	if(xMax<points[i].x)xMax=points[i].x;
//			//	if(yMin>points[i].y)yMin=points[i].y;
//			//	if(yMax<points[i].y)yMax=points[i].y;
// 
//		}
//		else
//		{
//			posX=points[i].y;
//			posY=points[i].x;
//
//			//if(xMin>points[i].y)xMin=points[i].y;
//			//	if(xMax<points[i].y)xMax=points[i].y;
//			//	if(yMin>points[i].x)yMin=points[i].x;
//			//	if(yMax<points[i].x)yMax=points[i].x;
// 
//		}
//		
//		mX+=posX;
//		mY+=posY;
//		mXX+=posX*posX;
//		mXY+=posX*posY;
//		i+=1;
//	}
// 
//	//if(abs(yMax-yMin)<10)
//	//{
//	//	k=0;
//	//	b=0;
//	//	return; 
//	//}
//
// 
//
//
//	if(abs(mX*mX)>10000000000000000000)
//	{
//		k=0;
//		b=0;
//		return;
//	}
//	k=(mY*mX-mXY*n)/(mX*mX-mXX*n);
//	b=(mY-mX*k)/n;
//	if(k==0)
//	{
//		k=0;
//	}
//	return ;
//}

//寻找4连通区域_1
void FindPoint1(IplImage* img,int x,int y,float &SumX,float &SumY,double &CountPixel,int Threshold,CvPoint& ptT,CvPoint& ptB,CvPoint& ptL,CvPoint& ptR) 
{ 
	if(x<=1 ||y<=1 || x>=img->width-1  || y>= img->height-1  || CountPixel>CONTENTPOINTMAXNUMBER ) 
		return;
	if((unsigned char)(*(img->imageData+(img->width*y+x)*4+2))>Threshold) 
	{

		if(ptT.y>y)
		{
			ptT.x=x;
			ptT.y=y;
		}
		if(ptB.y<y)
		{
			ptB.x=x;
			ptB.y=y;
		}
		if(ptL.x>x)
		{
			ptL.x=x;
			ptL.y=y;
		}
		if(ptR.x<x)
		{
			ptR.x=x;
			ptR.y=y;
		}
		//if((unsigned char)(*(img->imageData+(img->width*y+x)*4+2))>Threshold+20)
		//{
			SumX=SumX+x;
			SumY=SumY+y;
			CountPixel++;
		//}

		(*(img->imageData+(img->width*y+x)*4+3))=0;
		(*(img->imageData+(img->width*y+x)*4+2))=0;
		(*(img->imageData+(img->width*y+x)*4+1))=0;
		(*(img->imageData+(img->width*y+x)*4+0))=255;
		


		FindPoint1(img,x,y+1,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x,y-1,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x-1,y,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x+1,y,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x+1,y+1,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x-1,y-1,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x-1,y+1,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
		FindPoint1(img,x+1,y-1,SumX,SumY,CountPixel,Threshold,ptT,ptB,ptL,ptR); 
	}
}

//寻找4连通区域_2

void FindPoint(IplImage* img,int x,int y,int index,float &SumX,float &SumY,double &CountPixel,CvPoint*  Points,int &BorderCount,CvPoint*  Borderpoints) 
{ 
 
	if(x<=1 ||y<=1 || x>=img->width-1  || y>= img->height-1  || CountPixel>CONTENTPOINTMAXNUMBER ) 
		return;

	if((unsigned char)(*(img->imageData+(img->width*y+x)))==255) 
	{
		int value=0;
		if((unsigned char)(*(img->imageData+(img->width*(y+1)+(x))))>0)value++;
		if((unsigned char)(*(img->imageData+(img->width*(y-1)+(x))))>0)value++;
		if((unsigned char)(*(img->imageData+(img->width*(y)+(x+1))))>0)value++;
		if((unsigned char)(*(img->imageData+(img->width*(y)+(x-1))))>0)value++;

 
		

		//不能是255-index,否则index=0时会出错
		//现在不用255-index,因为index 可能大于255
		(*(img->imageData+(img->width*y+x)))=100;
		SumX=SumX+x;
		SumY=SumY+y;


		Points[(int)CountPixel].x=x;
		Points[(int)CountPixel].y=y;

		if(value!=4)
		{
			if(BorderCount<BORDERPOINTMAXNUMBER)
			{
				Borderpoints[(int)BorderCount].x=x;
				Borderpoints[(int)BorderCount].y=y;
				BorderCount++;
			}
		}
		CountPixel++;
		FindPoint(img,x,y+1,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x,y-1,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x-1,y,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x+1,y,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x+1,y+1,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x-1,y-1,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x-1,y+1,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
		FindPoint(img,x+1,y-1,index,SumX,SumY,CountPixel,Points,BorderCount,Borderpoints); 
	} 
	return;
}
//相对直线旋转,整合到x,y轴
void Rotate(double &x,double &y,double theta)
{
	double temp_x=x,temp_y=y;
	x=temp_x*cos(theta)-temp_y*sin(theta);
	y=temp_x*sin(theta)+temp_y*cos(theta);
}

//寻找直线区域首尾和长度
void procLine(CvPoint*  points,int Count,float wx,float wy,int LineLength,CvPoint  &p1,CvPoint  &p2,double &len,bool &isLine)
{
	CvPoint P1,P2;
	P1.x=-100000;P1.y=-100000;
	P2.x=100000;P2.y=100000;

	int iBegin=0;
	int iEnd=0;
	float k=0;
 
	for(int i=0;i<Count;i++)
	{
		double x=0;double y=0;
		x=points[i].x;
		y=points[i].y;
		if(abs(wx)>abs(wy))
		{	
			k=wy/wx;
			Rotate(x,y,-atan(k));
			if(P1.x<x)
			{
				iBegin=i;
				P1.x=(int)x;
				P1.y=(int)y;
			}

			if(P2.x>x)
			{
				iEnd=i;
				P2.x=(int)x;
				P2.y=(int)y;
			}
			len=abs(P2.x-P1.x);
		}
		else
		{
			k=wx/wy;
			Rotate(x,y,atan(k));
			if(P1.y<y)
			{
				iBegin=i;
				P1.x=(int)x;
				P1.y=(int)y;
			}

			if(P2.y>y)
			{
				iEnd=i;
				P2.x=(int)x;
				P2.y=(int)y;
			}
			len=abs(P2.y-P1.y);

		}

		
	}
	
	
	if(len>=LineLength)
	{
		isLine=true;
	}
	else
	{
		isLine=false;
	}
	p1=points[iBegin];
	p2=points[iEnd];

	
}




//细化算法
#define  COLOR	0

void FastThin(IplImage* list0)
{

	int Dx=list0->width ;
	int Dy=list0->height;
	int  i,j,k,l,flag;
	int  f[11],ap1,bp1;
	char *buf,**list;
 
	buf =(char*)  malloc(Dx*Dy*sizeof(char));
	list=(char**) malloc(Dy*sizeof(char*));

	for(k=0;k<Dy;k++) {
		list[k]=buf+k*Dx;

		for(l=0;l<Dx;l++) 
		{
			if((unsigned char)(*(list0->imageData+(Dx*k+l)))==255)
				list[k][l]=1;
			else
				list[k][l]=0;
		}
	}

	do {	
		flag=0;
		for (j=1; j<Dy-1; j++) 
		{
			for (i=1; i<Dx-1; i++) 
			{
				if  (list[j][i] != 1)  continue;
				f[1]=list[j][i];
				f[2]=list[j][i-1];
				f[3]=list[j+1][i-1];
				f[4]=list[j+1][i];
				f[5]=list[j+1][i+1];
				f[6]=list[j][i+1];
				f[7]=list[j-1][i+1];
				f[8]=list[j-1][i];
				f[9]=list[j-1][i-1];
				f[10]=f[2];

				for (k=2; k<=10; k++)
					f[k] = (f[k]>0) ? 1 : 0;
				if (f[4]&&f[6])
					if (f[2]||f[8])  continue;
				bp1=0;
				for (k=2; k<=9; k++)
					bp1+=f[k];
				if ((bp1<2)||(bp1>6))  continue;
				ap1=0;
				for (k=2; k<=9; k++)
					if ((f[k]==0) && (f[k+1]==1))
				ap1++;
				if (ap1!=1)  continue;
				list[j][i]=3;
			}
		}
		for (j=1; j<Dy-1; j++) 
		{
			for (i=1; i<Dx-1; i++) 
			{
				if (list[j][i] == 3) 
				{
					list[j][i] = 0;
					(*(list0->imageData+(Dx*j+i)))= COLOR;
					flag=1;
				}
			}
		}

		if (flag==0)  break;
		flag=0;
		for (j=1; j<Dy-1; j++) 
		{
			for (i=1; i<Dx-1; i++) 
			{
				if  (list[j][i] != 1)  continue;
				f[1]=list[j][i];
				f[2]=list[j][i-1];
				f[3]=list[j+1][i-1];
				f[4]=list[j+1][i];
				f[5]=list[j+1][i+1];
				f[6]=list[j][i+1];
				f[7]=list[j-1][i+1];
				f[8]=list[j-1][i];
				f[9]=list[j-1][i-1];
				f[10]=f[2];

				for (k=2; k<=10; k++)
					f[k] = (f[k]>0) ? 1 : 0;
				if (f[2]&&f[8])
				if (f[4]||f[6])  continue;
				bp1=0;
				for (k=2; k<=9; k++)
					bp1+=f[k];
				if ((bp1<2)||(bp1>6))  continue;
				ap1=0;
				for (k=2; k<=9; k++)
					if ((f[k]==0) && (f[k+1]==1))
				ap1++;
				if (ap1!=1)  continue;
				list[j][i] = 3;
			}
		}
		for (j=1; j<Dy-1; j++) 
		{
			for (i=1; i<Dx-1; i++) 
			{
				if (list[j][i] == 3) 
				{
					list[j][i] = 0;
					  (*(list0->imageData+(Dx*j+i))) =COLOR;
					  flag=1;
				}
			}	
		}
	}
	while(flag==1);

	free(list);                   
	free(buf);
}

//校正四边形区域到矩形区域
 void CaculateXY(double &x,double &y,int w,int h,double x_Known,double y_Known,double x_0,double y_0,double x_1,double y_1,double x_2,double y_2,double x_3,double y_3)  
 {
 
   double m1=x_Known-x_0; 
   double m2=(x_0-x_3)/h;
   double m3=(x_2-x_1-x_3+x_0)/h; 
   double m4=x_1-x_0;
   double m5=y_Known-y_0;
   double m6=(y_0-y_3)/h; 
   double m7=(y_2-y_1-y_3+y_0)/h;
   double m8=y_1-y_0;
   
   
   double a=m2*m7-m3*m6;
   double b=m1*m7+m2*m8-m4*m6-m3*m5; 
   double c=m1*m8-m4*m5;
   
   if(a!=0)
   {
	   double Y=(-b+sqrt(b*b-4*a*c))/(2*a); 
       double Y1=(-b-sqrt(b*b-4*a*c))/(2*a);
	   if(Y>=0&&Y<=h)
	       y=Y;
	   else if(Y1>=0&&Y1<=h)
		   y=Y1;
	   else if(abs(Y)<abs(Y1))
           y=Y;
	   else y=Y1;
   }
   else
   {
	   y=-c/b;
   }

   double m9=x_Known-x_0; 
   double m10=(x_0-x_1)/w;
   double m11=(x_2-x_3-x_1+x_0)/w;
   double m12=x_3-x_0;
   double m13=y_Known-y_0;
   double m14=(y_0-y_1)/w;
   double m15=(y_2-y_3-y_1+y_0)/w;
   double m16=y_3-y_0;
   
   double a1=m10*m15-m11*m14;
   double b1=m9*m15+m10*m16-m12*m14-m11*m13;
   double c1=m9*m16-m12*m13;
    

   if (a1!=0)
   {
	   double X=(-b1+sqrt(b1*b1-4*a1*c1))/(2*a1);
	   double X1=(-b1-sqrt(b1*b1-4*a1*c1))/(2*a1);

	   if(X>=0&&X<=w)
		   x=X;
	   else if(X1>=0&&X1<=w) 
		   x=X1;
	   else if(abs(X)<abs(X1))
		   x=X;
	   else x=X1;

   }
   else
   {
	   x=-c1/b1;
   }
 }
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -