使用 Hough 变换进行椭圆检测
Posted
技术标签:
【中文标题】使用 Hough 变换进行椭圆检测【英文标题】:Ellipse Detection using Hough Transform 【发布时间】:2011-09-12 12:44:09 【问题描述】:使用霍夫变换,我如何检测和获取二维空间中椭圆的 (x0,y0) 和“a”和“b”坐标?
这是 ellipse01.bmp:
I = imread('ellipse01.bmp');
[m n] = size(I);
c=0;
for i=1:m
for j=1:n
if I(i,j)==1
c=c+1;
p(c,1)=i;
p(c,2)=j;
end
end
end
Edges=transpose(p);
Size_Ellipse = size(Edges);
B = 1:ceil(Size_Ellipse(1)/2);
Acc = zeros(length(B),1);
a1=0;a2=0;b1=0;b2=0;
Ellipse_Minor=[];Ellipse_Major=[];Ellipse_X0 = [];Ellipse_Y0 = [];
Global_Threshold = ceil(Size_Ellipse(2)/6);%Used for Major Axis Comparison
Local_Threshold = ceil(Size_Ellipse(1)/25);%Used for Minor Axis Comparison
[Y,X]=find(Edges);
Limit=numel(Y);
Thresh = 150;
Para=[];
for Count_01 =1:(Limit-1)
for Count_02 =(Count_01+1):Limit
if ((Count_02>Limit) || (Count_01>Limit))
continue
end
a1=Y(Count_01);b1=X(Count_01);
a2=Y(Count_02);b2=X(Count_02);
Dist_01 = (sqrt((a1-a2)^2+(b1-b2)^2));
if (Dist_01 >Global_Threshold)
Center_X0 = (b1+b2)/2;Center_Y0 = (a1+a2)/2;
Major = Dist_01/2.0;Alpha = atan((a2-a1)/(b2-b1));
if(Alpha == 0)
for Count_03 = 1:Limit
if( (Count_03 ~= Count_01) || (Count_03 ~= Count_02))
a3=Y(Count_03);b3=X(Count_03);
Dist_02 = (sqrt((a3 - Center_Y0)^2+(b3 - Center_X0)^2));
if(Dist_02 > Local_Threshold)
Cos_Tau = ((Major)^2 + (Dist_02)^2 - (a3-a2)^2 - (b3-b2)^2)/(2*Major*Dist_02);
Sin_Tau = 1 - (Cos_Tau)^2;
Minor_Temp = ((Major*Dist_02*Sin_Tau)^2)/(Major^2 - ((Dist_02*Cos_Tau)^2));
if((Minor_Temp>1) && (Minor_Temp<B(end)))
Acc(round(Minor_Temp)) = Acc(round(Minor_Temp))+1;
end
end
end
end
end
Minor = find(Acc == max(Acc(:)));
if(Acc(Minor)>Thresh)
Ellipse_Minor(end+1)=Minor(1);Ellipse_Major(end+1)=Major;
Ellipse_X0(end+1) = Center_X0;Ellipse_Y0(end+1) = Center_Y0;
for Count = 1:numel(X)
Para_X = ((X(Count)-Ellipse_X0(end))^2)/(Ellipse_Major(end)^2);
Para_Y = ((Y(Count)-Ellipse_Y0(end))^2)/(Ellipse_Minor(end)^2);
if (((Para_X + Para_Y)>=-2)&&((Para_X + Para_Y)<=2))
Edges(X(Count),Y(Count))=0;
end
end
end
Acc = zeros(size(Acc));
end
end
end
【问题讨论】:
?en.wikipedia.org/wiki/… 我尝试用 MATLAB 实现该算法,但它不能正常工作。我认为我没有正确实施它。请重新检查问题。 这个实现是从en.wikipedia.org/wiki/Hough_transform#复制过来的 【参考方案1】:虽然这是一个老问题,但也许我的发现可以帮助某人。
使用普通 Hough 变换检测椭圆的主要问题是累加器的维度,因为我们需要为 5 个变量投票(方程解释为 here):
有一个很好的algorithm,例如,累加器可以是一个简单的一维数组,并在 中运行。如果你想看代码,你可以看here(用于测试的图像是上面发布的)。
【讨论】:
【参考方案2】:如果您使用圆形进行粗略变换,则给出为 rho = xcos(theta) + ysin(theta) 对于椭圆,因为它是
您可以将等式转换为 rho = axcos(theta) + bysin(theta) 虽然我不确定您是否使用标准霍夫变换,但对于类似椭圆的变换,您可以操作第一个给定函数。
【讨论】:
如您所知,我们有一个图像,其中只有一个椭圆,没有任何信息。 (我们不知道 "a","b" 和 "(x0,y0)" )。我们应该使用霍夫变换来计算这些参数。【参考方案3】:如果你的椭圆是提供的,是一个真正的椭圆,而不是一个嘈杂的点样本; 对两个最远点的搜索给出了主轴的末端, 对两个最近点的搜索给出了短轴的末端, 这些线的交点(你可以检查它是一个直角)出现在中心。
【讨论】:
你需要检测椭圆段【参考方案4】:如果您知道椭圆的“a”和“b”,那么您可以在一个方向上按 a/b 因子重新缩放图像并寻找圆形。我还在思考a和b未知的时候怎么办。
如果您知道它是圆形,则对圆形使用 Hough 变换。这是一个示例代码:
int accomulatorResolution = 1; // for each pixel
int minDistBetweenCircles = 10; // In pixels
int cannyThresh = 20;
int accomulatorThresh = 5*_accT+1;
int minCircleRadius = 0;
int maxCircleRadius = _maxR*10;
cvClearMemStorage(storage);
circles = cvHoughCircles( gryImage, storage,
CV_HOUGH_GRADIENT, accomulatorResolution,
minDistBetweenCircles,
cannyThresh , accomulatorThresh,
minCircleRadius,maxCircleRadius );
// Draw circles
for (int i = 0; i < circles->total; i++)
float* p = (float*)cvGetSeqElem(circles,i);
// Draw center
cvCircle(dstImage, cvPoint(cvRound(p[0]),cvRound(p[1])),
1, CV_RGB(0,255,0), -1, 8, 0 );
// Draw circle
cvCircle(dstImage, cvPoint(cvRound(p[0]),cvRound(p[1])),
cvRound(p[2]),CV_RGB(255,0,0), 1, 8, 0 );
【讨论】:
其实我们不知道'a'和'b'。但是现在,让我们假设它是一个圆圈(a=b)。我们应该遵循哪种算法来计算半径和 (x0,y0)?以上是关于使用 Hough 变换进行椭圆检测的主要内容,如果未能解决你的问题,请参考以下文章
基于hough霍夫变换的铁栏栅断裂处的检测算法matlab仿真