找圓的中心座標~~ |
尚未結案
|
黑輪
中階會員 發表:135 回覆:188 積分:64 註冊:2004-01-29 發送簡訊給我 |
|
auslk
初階會員 發表:35 回覆:77 積分:32 註冊:2003-02-17 發送簡訊給我 |
黑輪兄, 看來你也在寫作業喔! 沒關係,提供以下程式碼給你用!
不過你要有'數位圓概念'喔!
用pixel的小格去想像 電腦上的圓形 是長的的如何
Best Regards,
Pauli
02/12/04'
int DetectCircleRand1(XYPoint *EdgePoint,int EdgeNum, int ThresholdRnd, int ThresholdCoCircleDist, int Threshold2PDist, int ThresholdCircleRatio, int ThresholdCirclePoint, CIRCLE *CircleData) { XYPoint TempEdgePoint[6000] ; /*存所抓到之隨機四點在存一維邊點的 TempEdgePoint 一維陣列中的位置*/ int p[5]; /*用於抓點時餘多少邊點用, 點 1 到 RestEdgeNum 是未視為線點之邊點*/ int RestEdgeNum ; /*在沒有確定所抓之點真的是為一條線上之點前,RestEdgeNum 不能變*/ /*所以用 TempRestNum 來暫時存臨時改變之所餘要處理的邊點數*/ int TempRestNum ; /*記錄目前已進行抓多少次之三點失敗及抓多少次三點其外積皆不成功[不符合為線]便結束程式之門檻*/ int RndCount; /*用於迴圈控制指標用*/ int i; /*用於在邊點中隨機抓四點之迴圈控制指標*/ int i4; /*隨機抓後, 若有要交換時, 用此來暫存交換之邊點 [存邊點 x,y 座標]*/ XYPoint SwapTemp; /*存用 random 抓出之整數值, 用此值來抓出一維邊點陣列中之某點*/ int RndValue; /*存四點中 4 組之任三點之所得之圓心的 x,y 座標*/ float Cx123,Cy123, Cx124,Cy124, Cx134,Cy134, Cx234,Cy234; /*/為方便方程式計算, 先求出圓心(a,b)及TempD, 再求半徑 r*/ float TempD123, TempD124, TempD134, TempD234; /*存四點中 4 組之任三點所求出之圓半徑*/ float Radius123, Radius124, Radius134, Radius234; /*存隨機抓 4 點中, 第四點到前三點組成之圓周上的距離*/ float Dist4To123, Dist3To124, Dist2To134, Dist1To234; /*分別存所求某認其為圓之 圓心(a=CenterX,b=CenterY) 及半徑 r=RadiusR*/ float CenterX,CenterY,RadiusR; /*存 X1^2 Y1^2 用, 即第一點和原點之距離的平方*/ int Square1; /*存 Xi^2 Yi^2 用, 即第 2,3,4 點和原點之距離的平方*/ int Square2,Square3,Square4; /*為程式中表達方便, 把所抓到之隨機 4 個點座標值放在此變數上*/ int X1,Y1, X2,Y2, X3,Y3, X4,Y4; /*存第2,3,4點到第一點之 x,y 上的差值*/ int X21,Y21; int X31,Y31; int X41,Y41; int X32,Y32; int X42,Y42; int X43,Y43; int denom123; /* denom234 = 2[(X3-X2)(Y4-Y2)-(Y3-Y2)(X4-X2)], 為解 123 圓心 a,b 時要用到之分母 */ int denom124,denom134,denom234 ; /*固定某為圓之三點下, 記錄目前有多少第四點和這三點共圓*/ int CountCirclePoint; /*找到圓時, 存其它第四點和所找到之三點組成之圓周上的距離多少用*/ float DistToCircle; /*用來記錄找到幾個圓*/ int CountCircle; /*存所找到之線要畫出時之顏色*/ int DrawColor; /*為每次取亂數時皆不同, 所以用此指令*/ randomize(); /*把EdgePoint在TempEdgePoint上備份, 以作為後面處理時之可能改變*/ for( i = 1;i<=EdgeNum;i ) TempEdgePoint[i] = EdgePoint[i]; /*對一些變數值初時化*/ CountCircle = 0; RndCount = 0; RestEdgeNum = EdgeNum; TempRestNum = RestEdgeNum; while ( RndCount <= ThresholdRnd && RestEdgeNum >= ThresholdCirclePoint ) { /*抓四點來看是否有為圓之證據*/ for(i4 = 1; i4<=4;i4 ) { /*記錄下所抓之第i4點為目前TempEdgePoint邊點陣列的那裡*/ /*因為所抓之點換到後面, 所以其為目前最後之點*/ p[i4] = TempRestNum; RndValue = ( rand() % TempRestNum 1); /*抓到之點放到後面的三點上*/ SwapTemp.X = TempEdgePoint[RndValue].X; SwapTemp.Y = TempEdgePoint[RndValue].Y; TempEdgePoint[RndValue].X = TempEdgePoint[TempRestNum].X; TempEdgePoint[RndValue].Y = TempEdgePoint[TempRestNum].Y; TempEdgePoint[TempRestNum].X = SwapTemp.X; TempEdgePoint[TempRestNum].Y = SwapTemp.Y; TempRestNum = TempRestNum - 1; /*臨時性的邊點數少一*/ } /*所抓之四點存在 TempEdgePoint 之 p[1],p[2],p[3],p[4] 位置上*/ X1=TempEdgePoint[p[1]].X; Y1=TempEdgePoint[p[1]].Y; X2=TempEdgePoint[p[2]].X; Y2=TempEdgePoint[p[2]].Y; X3=TempEdgePoint[p[3]].X; Y3=TempEdgePoint[p[3]].Y; X4=TempEdgePoint[p[4]].X; Y4=TempEdgePoint[p[4]].Y; /*存所抓之四點之 X^2 Y^2 值*/ Square1= TempEdgePoint[p[1]].X*TempEdgePoint[p[1]].X TempEdgePoint[p[1]].Y*TempEdgePoint[p[1]].Y; Square2= TempEdgePoint[p[2]].X*TempEdgePoint[p[2]].X TempEdgePoint[p[2]].Y*TempEdgePoint[p[2]].Y; Square3= TempEdgePoint[p[3]].X*TempEdgePoint[p[3]].X TempEdgePoint[p[3]].Y*TempEdgePoint[p[3]].Y; Square4= TempEdgePoint[p[4]].X*TempEdgePoint[p[4]].X TempEdgePoint[p[4]].Y*TempEdgePoint[p[4]].Y; /*求第2,3,4點到第1點之X與Y方向上的差值*/ X21=X2-X1; Y21=Y2-Y1; X31=X3-X1; Y31=Y3-Y1; X41=X4-X1; Y41=Y4-Y1; X32=X3-X2; Y32=Y3-Y2; X42=X4-X2; Y42=Y4-Y2; X43=X4-X3; Y43=Y4-Y3; /*存兩點間之距離用*/ int SquareDist21 = (X21*X21) (Y21*Y21); int SquareDist31 = (X31*X31) (Y31*Y31); int SquareDist41 = (X41*X41) (Y41*Y41); int SquareDist32 = (X32*X32) (Y32*Y32); int SquareDist42 = (X42*X42) (Y42*Y42); int SquareDist43 = (X43*X43) (Y43*Y43); /*解由123,124,134,234,點組成之圓的圓心*/ denom123 = 2*(X21*Y31 - X31*Y21); denom124 = 2*(X21*Y41 - X41*Y21); denom134 = 2*(X31*Y41 - X41*Y31); denom234 = 2*(X32*Y42 - X42*Y32); /*下面計算 123 123 找圓, 求第4 點和所算出之圓之差的過程*/ if (denom123==0)// 分母為 0 表示, 234 三點共線, 不會為圓 Dist4To123= 1000; else { Cx123=((Square2-Square1)*(Y31)-(Square3-Square1)*(Y21))/denom123; Cy123=((Square3-Square1)*(X21)-(Square2-Square1)*(X31))/denom123; /*2*X1*a 2*Y1*b TempD123=X1^2 Y1^2 [由方程式可得]*/ TempD123= Square1- 2*X1*Cx123 - 2*Y1*Cy123; Radius123= sqrt(TempD123 Cx123 * Cx123 Cy123 * Cy123); /*TempD= r^2-a^2-b^2 , or r^2 = TempD a^2 b^2*/ Dist4To123=sqrt((X4-Cx123)*(X4-Cx123) (Y4-Cy123)*(Y4-Cy123))- Radius123; /*第四點和圓周之距離為 和圓心之距離跟圓半徑 之差的絕對值*/ if (Dist4To123<0) Dist4To123 = -1 * Dist4To123; } /*下面計算 124 124 找圓, 求第 3 點和所算出之圓之差的過程*/ if (denom124==0) // 分母為 0 表示, 234 三點共線, 不會為圓 Dist3To124= 1000 ; else { Cx124=((Square2-Square1)*(Y41)-(Square4-Square1)*(Y21))/denom124; Cy124=((Square4-Square1)*(X21)-(Square2-Square1)*(X41))/denom124; TempD124= Square1- 2*X1*Cx124 - 2*Y1*Cy124; Radius124= sqrt(TempD124 Cx124 * Cx124 Cy124 * Cy124); Dist3To124=sqrt((X3-Cx124)*(X3-Cx124) (Y3-Cy124)*(Y3-Cy124))- Radius124; if (Dist3To124<0) Dist3To124 = -1 * Dist3To124 ; } /*下面計算 134 134 找圓, 求第 2 點和所算出之圓之差的過程*/ if (denom134==0) /*分母為 0 表示, 234 三點共線, 不會為圓*/ Dist2To134= 1000; else { Cx134=((Square3-Square1)*(Y41)-(Square4-Square1)*(Y31))/denom134; Cy134=((Square4-Square1)*(X31)-(Square3-Square1)*(X41))/denom134; TempD134= Square1- 2*X1*Cx134 - 2*Y1*Cy134; Radius134= sqrt(TempD134 Cx134 * Cx134 Cy134 * Cy134); Dist2To134 = sqrt((X2-Cx134)*(X2-Cx134) (Y2-Cy134)*(Y2-Cy134))- Radius134; if (Dist2To134<0) Dist2To134 = -1 * Dist2To134; } /*下面計算 234 234 找圓, 求第 1 點和所算出之圓之差的過程*/ if (denom234==0)/*分母為 0 表示, 234 三點共線, 不會為圓*/ Dist1To234= 1000; else { Cx234=((Square3-Square2)*(Y42)-(Square4-Square2)*(Y32))/denom234; Cy234=((Square4-Square2)*(X32)-(Square3-Square2)*(X42))/denom234; TempD234= Square2- 2*X2*Cx234 - 2*Y2*Cy234; Radius234= sqrt(TempD234 Cx234 * Cx234 Cy234 * Cy234); Dist1To234 = sqrt((X1-Cx234)*(X1-Cx234) (Y1-Cy234)*(Y1-Cy234))- Radius234; if (Dist1To234<0) Dist1To234 = -1 * Dist1To234; } /*上面四組資料皆算好了, 下面開始判斷那一組之圓, 可使另一點也在圓上, 即該組為可能之圓*/ /*本指令對三點組成之圓的三點間距離有限制*/ if ((Dist4To123>ThresholdCoCircleDist || SquareDist21 <=Threshold2PDist || SquareDist31 <=Threshold2PDist || SquareDist32<=Threshold2PDist) && (Dist3To124>ThresholdCoCircleDist || SquareDist21<=Threshold2PDist || SquareDist41<=Threshold2PDist || SquareDist42<=Threshold2PDist) && (Dist2To134>ThresholdCoCircleDist || SquareDist31<=Threshold2PDist || SquareDist41<=Threshold2PDist || SquareDist43<=Threshold2PDist) && (Dist1To234>ThresholdCoCircleDist || SquareDist32<=Threshold2PDist || SquareDist42<=Threshold2PDist || SquareDist43<=Threshold2PDist) ) { /* 第四點離任三點之圓過大, 表示這次所找之四點不存在共圓之證明, 記錄下多一次抓四點之失敗次數 */ RndCount = RndCount 1; /*抽樣的四點不成功, 所以TempRestNum要移到重移向前推四點*/ TempRestNum = TempRestNum 4; } else /*找到一組三點之圓和第 4 點很近, 即這圓可能真是存在圖上之圓*/ { /*存符合條件之圓, 其和第 4 點距離最近者*/ float MinDist=ThresholdCoCircleDist; if ( Dist4To123 <= ThresholdCoCircleDist && SquareDist21>Threshold2PDist && SquareDist31>Threshold2PDist && SquareDist32>Threshold2PDist ) { /*123 三點共圓 記下找到之圓心和半徑*/ CenterX=Cx123; CenterY=Cy123; RadiusR=Radius123; MinDist = Dist4To123; } if (Dist3To124 < MinDist && SquareDist21>Threshold2PDist && SquareDist41>Threshold2PDist && SquareDist42>Threshold2PDist ) { /*124 三點共圓*/ CenterX=Cx124; CenterY=Cy124; RadiusR=Radius124; MinDist = Dist3To124; } if ( Dist2To134 < MinDist && SquareDist31>Threshold2PDist && SquareDist41>Threshold2PDist && SquareDist43>Threshold2PDist ) {/*134 三點共圓*/ CenterX=Cx134; CenterY=Cy134; RadiusR=Radius134; MinDist = Dist2To134; } if ( Dist1To234 < MinDist && SquareDist32>Threshold2PDist && SquareDist42>Threshold2PDist && SquareDist43>Threshold2PDist ) { /* 234 三點共圓*/ CenterX=Cx234; CenterY=Cy234; RadiusR=Radius234; } CountCirclePoint=0; /*三點視為共圓時, 繼續判斷其它點是否為此線上點*/ for(i = TempRestNum ; i >=1 ; i-- ) { DistToCircle = sqrt((TempEdgePoint[i].X - CenterX)*(TempEdgePoint[i].X - CenterX) (TempEdgePoint[i].Y-CenterY)* (TempEdgePoint[i].Y-CenterY))- RadiusR; /*求其它點到所找圓周上之距離, 依此來判斷這些點是否在圓上*/ if (DistToCircle <0 ) DistToCircle = -1 * DistToCircle; /*可視目前這個邊點在這圓周上*/ if ( DistToCircle <= ThresholdCoCircleDist ) { CountCirclePoint = CountCirclePoint 1; /*抓到之點為圓上點時, 放到後面上以表示已處理找到了*/ /*把抓到可視為找到之圓上點之其它點和最後面之點交換*/ SwapTemp.X = TempEdgePoint[i].X; SwapTemp.Y = TempEdgePoint[i].Y; TempEdgePoint[i].X = TempEdgePoint[TempRestNum].X; TempEdgePoint[i].Y = TempEdgePoint[TempRestNum].Y; TempEdgePoint[TempRestNum].X = SwapTemp.X; TempEdgePoint[TempRestNum].Y = SwapTemp.Y; TempRestNum = TempRestNum - 1; } } /*要超過理論圓之點數之某百分比才算其為找到之圓*/ if(CountCirclePoint <= 4*sqrt(2)*RadiusR*ThresholdCircleRatio/100) { TempRestNum = RestEdgeNum; RndCount = RndCount 1; } else /*前面所找到符合組成線之點數夠大認為其為圓時*/ { CircleData[CountCircle].CCX=CenterX; CircleData[CountCircle].CCY=CenterY; CircleData[CountCircle].Rr=RadiusR; CountCircle = CountCircle 1; RndCount = 0 ; /*組成線之點皆向後移了, 所以最後點位置 RestEdgeNum 向前推*/ RestEdgeNum = TempRestNum; } } } return CountCircle; } |
taishyang
站務副站長 發表:377 回覆:5490 積分:4563 註冊:2002-10-08 發送簡訊給我 |
|
黑輪
中階會員 發表:135 回覆:188 積分:64 註冊:2004-01-29 發送簡訊給我 |
|
taishyang
站務副站長 發表:377 回覆:5490 積分:4563 註冊:2002-10-08 發送簡訊給我 |
黑輪您好:
引言: 之前我是看過成大的一篇論文(人臉追蹤法),其中有用到樣版匹對(template matching)的方法,我想我可以利用一下,可是我不了解template matching那再參考這篇 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=29170 順心 |
黑輪
中階會員 發表:135 回覆:188 積分:64 註冊:2004-01-29 發送簡訊給我 |
|
auslk
初階會員 發表:35 回覆:77 積分:32 註冊:2003-02-17 發送簡訊給我 |
我的做法來至 "影像處理與電腦視覺" 鐘國亮著 東華書局出版
第六章 圓與橢圓偵測 內容有敘述為何要取四點:(擷取部份內容說明) 若三邊點不幸滿足不等式(x2-x1)(y3-y1)-(x3-x1)(y2-y1)=0
表示這三點是共線... 所以在取出第四點 做法:
1.取邊點集合
2.依照 圓形 的判斷式判斷
3.找出假圓
4.設定數位圓的閥值
5.若滿足圓ㄉ邊緣閥值,就判定為真正圓.
6.畫出圓形並紀錄數量
7.完畢 Best Regards,
Pauli
02/25/04'
引言: auslk兄: 你pose的程式,我知道它是利用捉四個點,再來判斷它是否符合在圓上的條件,可是為什要捉四個點?(是不是捉的點愈多,愈準,而捉四個點,是為了效率問題),可以說明一下符合在圓上的條件是什麼嗎?這個是不是一個副程式,還是不是完整的程式,裡面好像有一些一東西沒有定義~~ taishyang兄: 你說的東西,我看了,還是不太了解,請問一下,樣版跟sobel(遮罩)是同樣的原理嗎? 可以把您給newken的資料給我嗎?~~我想了解一下~~~發表人 - auslk 於 2004/02/25 12:22:44 |
黑輪
中階會員 發表:135 回覆:188 積分:64 註冊:2004-01-29 發送簡訊給我 |
|
dac
一般會員 發表:14 回覆:24 積分:7 註冊:2005-01-06 發送簡訊給我 |
|
slife100
一般會員 發表:13 回覆:15 積分:5 註冊:2005-01-26 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |