圓弧檢測之前都需要對數據進行分割,將一系列的點分割成不同的區域,然後計算圓弧的位置。Hough變換
不需要知道某區域是否有圓弧,以類似於投票的機制,某參數獲得的票數越多,則存在圓弧的可能性越大,
大於某閾值時,則可以認爲該處存在圓弧。
x - a = r*cos(theta)
y - b = r*sin(theta)
對於每一個點x y,有無數個點滿足上式,即有無數個圓在經過該點的,每個圓對應一組(a,b,r)參數,設立一
個票箱,裏面有所有可能的(a,b,r)參數,當某組參數出現一次,就將該票箱中的票數加1,所有的點都掃描之
後,查看票箱,票數最多的點即是圓出現概率最大的情況。此時應該設定一個閾值,如果最多的票數小於該閾值,
則認爲不存在圓,否則認爲有圓存在。
//這是一個簡化的Hough圓算法,假設半徑已知的情況,
- int HoughArc(int X[] , int Y[] , int Cnt ,int r, ArcPara * Arc){
- vector<iPoint>center;
- vector<int>VoteCnt;
- double theta;
- int a,b;
- int minA,maxA,minB,maxB;
- int VotedFlag = 0;
- double deltaTheta = PI/180;//間隔1度
- double startAngle = 150.0*PI/180;
- double endAngle = PI*2 + PI/6;
- center.clear();
- VoteCnt.clear();
- minA = maxA = X[0] - r;
- minB = maxB = X[0]; //theta = 0
- //計算a,b的最小和最大值
- for (int i = 0; i < Cnt;i++)
- {
- for (theta = startAngle; theta < endAngle;theta += deltaTheta)
- {
- a = (int)(X[i] - r*cos(theta) + 0.5);
- b = (int)(Y[i] - r*sin(theta) + 0.5);
- if (a > maxA)
- {
- maxA = a;
- }else if (a < minA)
- {
- minA = a;
- }
- if (b > maxB)
- {
- maxB = b;
- }else if (b < minB)
- {
- minB = b;
- }
- }
- }
- //確定a,b的範圍之後,即確定了票箱的大小
- int aScale = maxA - minA + 1;
- int bScale = maxB - minB + 1;
- int *VoteBox = new int[aScale*bScale];
- //VoteBox初始化爲0
- for (int i = 0; i < aScale*bScale;i++)
- {
- VoteBox[i] = 0;
- }
- //開始投票
- for (int i = 0; i < Cnt;i++)
- {
- //printf("%d ",i);
- for (theta = startAngle; theta < endAngle;theta += deltaTheta)
- {
- a = (int)(X[i] - r*cos(theta) + 0.5);
- b = (int)(Y[i] - r*sin(theta) + 0.5);
- VoteBox[(b - minB)*aScale + a - minA] = VoteBox[(b - minB)*aScale + a - minA] + 1;
- }
- }
- //篩選票箱
- int VoteMax = 0;
- int VoteMaxX,VoteMaxY;
- for (int i = 0; i < bScale ;i++)
- {
- for (int j = 0; j < aScale ;j++)
- {
- if (VoteBox[i*aScale + j] > VoteMax)
- {
- VoteMax = VoteBox[i*aScale + j];
- VoteMaxY = i;
- VoteMaxX = j;
- }
- }
- }
- int Count = 0;
- printf("VoteMax: %d",VoteMax);
- for (int i = 0; i < bScale ;i++)
- {
- for (int j = 0; j < aScale ;j++)
- {
- if (VoteBox[i*aScale + j] >= VoteMax)
- {
- Count++;
- }
- }
- }
- printf(" %d \n",Count);
- //釋放內存
- delete [] VoteBox;
- if (VoteMax > 3)
- {
- Arc->center.x = VoteMaxX + minA;
- Arc->center.y = VoteMaxY + minB;
- Arc->r = r;
- return 1;
- }else {
- return 0;
- }
- return 1;
- }