📄 aglrothim.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 + -