Hough检测直线,圆,椭圆的部分代码

时间:2021-04-05 06:44:14

Hough检测直线,圆,椭圆的部分代码

                                                                                                                                     深之JOHNCHEN

1.hough检测直线

typedef struct MAXVALUE{
 int iDist;
 int iAngle;
 int iMax;
}MAXVALUE;

/*
 * 检测直线
 */
void TraceBeeline(int ImageWidth,int ImageHeight,LPBYTE lpSrc,LPBYTE lpDest,int len)
{
// #define pi 3.1415927
 int iMaxAngle = 90;
 int iAngleNumber = 0;
 //最大值
 MAXVALUE MaxValue1;
 memset(&MaxValue1,0,sizeof(MAXVALUE));
 //循环变量
 int i;
 int j;
 int off = 0;
 int iMaxDistance = 0,iDistance = 0;
 iMaxDistance = (int)sqrt(ImageWidth * ImageWidth + ImageHeight * ImageHeight);
 int  *lpTrans = new int[iMaxDistance * iMaxAngle];
 memset(lpTrans,0,iMaxDistance * iMaxAngle * sizeof(int));
    //去掉孤立点
    for(j=1,off=0;j<ImageHeight-1;j++)
  for(i=1;i<ImageWidth-1;i++,off)
  {
   if(1==lpSrc[off])
   {
    if(lpSrc[off-1]==0&&lpSrc[off+1]==0&&lpSrc[off-ImageWidth]==0&&lpSrc[off+ImageWidth]==0 /
     lpSrc[off-ImageWidth-1]==0&&lpSrc[off-ImageWidth+1]==0&&lpSrc[off+ImageWidth-1]==0&&lpSrc[off+ImageWidth+1]==0)
     lpSrc[off]=0;
   }
  }
 //////////////////////////////

 for(j=0;j<ImageHeight;j++)
  for(i=0;i<ImageWidth;i++)
  {
   off = j * ImageWidth + i;
   if(1==lpSrc[off])
   {
    for(iAngleNumber=0;iAngleNumber<iMaxAngle;iAngleNumber++)
    {
     iDistance = (int)fabs(i * cos(iAngleNumber * 2 * PI/180.0) + j * sin(iAngleNumber * 2 * PI/180.0));
     if(iDistance>=0&&iDistance<iMaxDistance)
         lpTrans[iDistance * iMaxAngle + iAngleNumber]++;
    }
   }
  }

 //找到最大值
  for(i = 0;i < iMaxDistance;i++)
   for(iAngleNumber=0;iAngleNumber<iMaxAngle;iAngleNumber++)
   {
    if(lpTrans[i * iMaxAngle + iAngleNumber]>MaxValue1.iMax)
    {
     MaxValue1.iMax = (int)lpTrans[i * iMaxAngle + iAngleNumber];
                    MaxValue1.iAngle = iAngleNumber;
     MaxValue1.iDist = i;
    }
   }

 //  

   for(j=0;j<ImageHeight;j++)
    for(i=0;i<ImageWidth;i++)
    {
     off = j * ImageWidth + i;
                    iDistance = (int)fabs(i * cos(iAngleNumber * 2 * PI/180.0) + j * sin(iAngleNumber * 2 * PI/180.0));
     if(iDistance == MaxValue1.iMax)
      lpDest[off]=1;
    }


 if(lpTrans)
 {
  delete lpTrans;
  lpTrans = NULL;
 }
}

2.hough检测圆
根据园的方程(x-a)×(x-a)+(y-b)×(y-b)=R×R,将参数空间增加到a,b,R三维空间.
常用的hough变换计算量太大,然而随机hough变换虽然计算量相对小点,但是准确率没有前者高.现在使用
一种改进的方法:提取边缘图像,然后边缘跟踪,在边缘曲线上进行hough变换检测圆.

double x=0.0,y=0.0,x0=0.0,y0=0.0,cc=0.0,ss=0.0,temp1,temp2;
 int aa=0,bb=0,rr=0,saveaa=0,savebb=0,saverr=0,savexx0=0,saveyy0=0,saveQ=0;
 int pos = ptNumber/3;
    int i = 0,off = 0,k = 0,iBaseFlag = 100,jj = 0;
 int tt = 0,m=0,n=0; 
int firstBase = 5;
 int secendBase = (2*firstBase+1);
 int aaBase = (R.right+R.left)/2 - firstBase,bbBase = (R.bottom+R.top)/2 -firstBase;
 LONG minrr = 0;
 minrr = (R.right - R.left)>(R.bottom - R.top)?(R.bottom - R.top):(R.right - R.left);
    int memsize = (int)(minrr+2*firstBase) * secendBase *secendBase;
 BYTE * lpabr = new BYTE[memsize];
 memset(lpabr,0,sizeof(BYTE)*memsize);
 int maxcount = -1;


/* 局部hough变换检测圆曲线段的一部分*/
 for(k=0;k<ptNumber;k+=pos)
 {
  for(aa=(int)(R.left+R.right)/2 - firstBase;aa<=(int)(R.left+R.right)/2 + firstBase;aa++)
   {
       if(aa<0)
     continue;
    if(aa>ImageWidth)
     break;
    for(bb=(int)(R.top+R.bottom)/2 -firstBase;bb<=(int)(R.top+R.bottom)/2 + firstBase;bb++)
    {
     if(bb<0)
      continue;
     if(bb>ImageHeight)
      break;
     temp1 = (pt[k].x-aa)*(pt[k].x-aa) + (pt[k].y-bb)*(pt[k].y-bb);
         rr = (int)sqrt(temp1);
     if(rr>=10&&rr<=(int)(minrr/2) + firstBase)
     lpabr[rr*secendBase*secendBase+(aa-aaBase)*secendBase+(bb-bbBase)]++;
    }
    
   }
 
 }

 for(rr=10;rr<=(int)(minrr/2) + firstBase;rr++)
  for(aa=(int)(R.left+R.right)/2 - firstBase;aa<=(int)(R.left+R.right)/2 + firstBase;aa++)
  {
   if(aa<0)
    continue;
   if(aa>ImageWidth)
    break;
   for(bb=(int)(R.top+R.bottom)/2 - firstBase;bb<=(int)(R.top+R.bottom)/2 + firstBase;bb++)
   {
    if(bb<0)
     continue;
    if(bb>ImageHeight)
     break;
    if(maxcount<lpabr[rr*secendBase*secendBase+(aa-aaBase)*secendBase+(bb-bbBase)])
    {
     maxcount = lpabr[rr*secendBase*secendBase+(aa-aaBase)*secendBase+(bb-bbBase)];
     saverr = rr;
     saveaa = aa;
     savebb = bb;
    }
   }
  }
if(maxcount>=4)
{
//记录保存中心,半经
     saverr = rr;
     saveaa = aa;
     savebb = bb;

}

3.hough变换检测椭圆的程序
一个MATLAB程序,有些地方你自己修改以下就可以了。
[row col]=size(fedge);
minofa=a;
maxofa=round(row/2);
minofy0=round(col/2)-30;
maxofy0=round(col/2)+30;
minofb=round(col/2)-60;
maxofb=round(col/2);
maxofx=round(row/2);
scalor=4;
H=zeros(floor((maxofa-minofa)/scalor)+1,floor((maxofa-minofa)/scalor)+1,...
floor((maxofy0-minofy0)/scalor)+1,floor((maxofb-minofb)/scalor)+1);
for x=1:maxofx
for y=1:col
temp=fedge(x,y);
if temp==255
for a=minofa:scalor:maxofa
for x0=a:scalor:maxofa
for b=minofb:scalor:maxofb
for y0=minofy0:scalor:maxofy0
temp=((y-y0)/b)^2+((x-x0)/a)^2;
if abs(temp-1)<=0.01
xtemp=floor((x0-minofa)/scalor)+1;
atemp=floor((a-minofa)/scalor)+1;
ytemp=floor((y0-minofy0)/scalor)+1;
btemp=floor((b-minofb)/scalor)+1;
H(xtemp,atemp,ytemp,btemp)=H(xtemp,atemp,ytemp,btemp)+1;
end
end
end
end
end
end
end
end

maxofH=max(max(max(max(H))));
for i=1:floor((maxofa-minofa)/scalor)+1
for j=1:floor((maxofa-minofa)/scalor)+1
for m=1:floor((maxofy0-minofy0)/scalor)+1
for n=1:floor((maxofb-minofb)/scalor)+1
temp=H(i,j,m,n);
if temp==maxofH
xtemp=i;
atemp=j;
ytemp=m;
btemp=n;
break;
end
end
end
end
end

x0=(xtemp-1)*scalor+minofa;
a=(atemp-1)*scalor+minofa;
y0=(ytemp-1)*scalor+minofy0;
b=(btemp-1)*scalor+minofb;
figure;
imshow(fedge,[]);
hold on;
plot(y0,x0,'r+');
t=0:pi/180:2*pi;
plot(y0+b*sin(t),x0+a*cos(t),'r-');
hold off;