2014-10-26 13 views
5

Próbuję dopasować niektóre punkty danych, aby znaleźć środek okręgu. Wszystkie poniższe punkty są hałaśliwe punkty danych na całym obwodzie koła:Jak znaleźć środek koła za pomocą najmniejszego kwadratu mieszczącego się w pythonie?

data = [(2.2176383052987667, 4.218574252410221), 
(3.3041214516913033, 5.223500807396272), 
(4.280815855023374, 6.461487709813785), 
(4.946375258539319, 7.606952538212697), 
(5.382428804463699, 9.045717060494576), 
(5.752578028217334, 10.613667377465823), 
(5.547729017414035, 11.92662513852466), 
(5.260208374620305, 13.57722448066025), 
(4.642126672822957, 14.88238955729078), 
(3.820310290976751, 16.10605425390148), 
(2.8099420132544024, 17.22588), 
(1.5731539516426183, 18.17052077121059), 
(0.31752822350872545, 18.75261434891438), 
(-1.2408437559671106, 19.119355580780265), 
(-2.680901948575409, 19.15018791257732), 
(-4.190406775175328, 19.001321726517297), 
(-5.533990404926917, 18.64857428377178), 
(-6.903383826792998, 17.730112542165955), 
(-8.082883753215347, 16.928080323602334), 
(-9.138397388219254, 15.84088004983959), 
(-9.92610373064812, 14.380575762984085), 
(-10.358670204629814, 13.018017342781242), 
(-10.600053524240247, 11.387283417089911), 
(-10.463673966507077, 10.107554951600699), 
(-10.179820255235496, 8.429558128401448), 
(-9.572153386953028, 7.1976672709797676), 
(-8.641475289758178, 5.8312286526738175), 
(-7.665976739804268, 4.782663065707469), 
(-6.493033077746997, 3.8549965442534684), 
(-5.092340806635571, 3.384419909199452), 
(-3.6530364510489073, 2.992272643733981), 
(-2.1522365767310796, 3.020780664301393), 
(-0.6855406924835704, 3.0767643753777447), 
(0.7848958776292426, 3.6196842530995332), 
(2.0614188482646947, 4.32795711960546), 
(3.2705467984691508, 5.295836809444288), 
(4.359297538484424, 6.378324784240816), 
(4.981264502955681, 7.823851404553242)] 

starałem się wykorzystać niektóre biblioteki jak scipy http://wiki.scipy.org/Cookbook/Least_Squares_Circle ale mam problemy z korzystaniem z dostępnych funkcji.

Nie

to na przykład:

# == METHOD 2 == 
from scipy  import optimize 

method_2 = "leastsq" 

def calc_R(xc, yc): 
    """ calculate the distance of each 2D points from the center (xc, yc) """ 
    return sqrt((x-xc)**2 + (y-yc)**2) 

def f_2(c): 
    """ calculate the algebraic distance between the data points and the mean circle centered at c=(xc, yc) """ 
    Ri = calc_R(*c) 
    return Ri - Ri.mean() 

center_estimate = x_m, y_m 
center_2, ier = optimize.leastsq(f_2, center_estimate) 

xc_2, yc_2 = center_2 
Ri_2  = calc_R(*center_2) 
R_2  = Ri_2.mean() 
residu_2 = sum((Ri_2 - R_2)**2) 

Ale to wydaje się być za pomocą pojedynczego xy? Jakieś pomysły na podłączenie tej funkcji do mojego przykładu danych?

Odpowiedz

2

Twoje punkty danych wydają się dość czyste i nie widzę wartości odstających, więc wiele algorytmów dopasowywania okręgów zadziała.

polecam zacząć od metody Coope, która działa przez magicznie linearizing problem:

(X-Xc)^2+(Y-Yc)^2=R² jest przepisany jako

2XcX+2YcY+R²-Xc²-Yc²=X²+Y², następnie

AX+BY+C=X²+Y², rozwiązany przez liniowych najmniejszych kwadratów .

2

Nie mam żadnego doświadczenia w dopasowywaniu kółek, ale pracowałem z bardziej ogólnym przypadkiem dopasowania elips. Wykonanie tego we właściwy sposób z hałaśliwymi danymi nie jest banalne. W tym przypadku algorytm opisany w Numerically stable direct least squares fitting of ellipses autorstwa Halira i Flussera działa całkiem nieźle. Artykuł zawiera kod Matlab, który powinien być prosty do przetłumaczenia na Numpy. Być może mógłbyś użyć tego algorytmu do dopasowania elipsy, a następnie przyjąć średnią z dwóch osi jako promień. Niektóre z odniesień w artykule wspominają również o dopasowywaniu kręgów, możesz chcieć je sprawdzić.

+0

To rzeczywiście nie jest trywialne. Spojrzę na twoją sugestię. – mimoralea

3

jako uzupełnienie do Bas Swinckels post, pomyślałem, że po mojej kod implementujący metodę Halir i Flusser dopasowywania elipsę

https://github.com/bdhammel/least-squares-ellipse-fitting

Stosując powyższy kod można znaleźć centrum z następująca metoda.

from ellipses import LSqEllipse 
import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.patches import Ellipse 

lsqe = LSqEllipse() 
lsqe.fit(data) 
center, width, height, phi = lsqe.parameters() 

plt.close('all') 
fig = plt.figure(figsize=(6,6)) 
ax = fig.add_subplot(111) 
ax.axis('equal') 
ax.plot(data[0], data[1], 'ro', label='test data', zorder=1) 

ellipse = Ellipse(xy=center, width=2*width, height=2*height, angle=np.rad2deg(phi), 
       edgecolor='b', fc='None', lw=2, label='Fit', zorder = 2) 
ax.add_patch(ellipse) 

plt.legend() 
plt.show() 

enter image description here

Powiązane problemy