Я пытаюсь наложить эллипс на мои разные наборы 2D точек, используя matplotlib. Я использую функции подбора эллипса из здесь , и вот код.
from matplotlib.patches import Ellipse
import matplotlib.pyplot as plt
import numpy
def fitEllipse(x,y):
x = x[:,np.newaxis]
y = y[:,np.newaxis]
D = np.hstack((x*x, x*y, y*y, x, y, np.ones_like(x)))
S = np.dot(D.T,D)
C = np.zeros([6,6])
C[0,2] = C[2,0] = 2; C[1,1] = -1
E, V = eig(np.dot(inv(S), C))
n = np.argmax(np.abs(E))
a = V[:,n]
return a
def ellipse_center(a):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
num = b*b-a*c
x0=(c*d-b*f)/num
y0=(a*f-b*d)/num
return np.array([x0,y0])
def ellipse_axis_length( a ):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
up = 2*(a*f*f+c*d*d+g*b*b-2*b*d*f-a*c*g)
down1=(b*b-a*c)*( (c-a)*np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
down2=(b*b-a*c)*( (a-c)*np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
res1=np.sqrt(up/down1)
res2=np.sqrt(up/down2)
return np.array([res1, res2])
def ellipse_angle_of_rotation2( a ):
b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
if b == 0:
if a > c:
return 0
else:
return np.pi/2
else:
if a > c:
return np.arctan(2*b/(a-c))/2
else:
return np.pi/2 + np.arctan(2*b/(a-c))/2
Однако, когда я строю эллипс, используя matplotlib, иногда эллипс хорошо подогнан, а иногда Мне нужно повернуть эллипс на 90 градусов, чтобы он уместился (синий эллипс повернут на 90, красный эллипс не требует дополнительного вращения) Вот мой код.
def plot_ellipse(x, y):
a = fitEllipse(x, y)
center = ellipse_center(a)
phi = ellipse_angle_of_rotation2(a)
axes = ellipse_axis_length(a)
a, b = axes
ell = Ellipse(center, 2*a, 2*b, phi*180 / np.pi, facecolor=(1,0,0,0.2), edgecolor=(0,0,0,0.5))
ell_rotated = Ellipse(center, 2*a, 2*b, phi*180 / np.pi + 90, facecolor=(0,0,1,0.2), edgecolor=(0,0,0,0.5))
fig, ax = plt.subplots()
ax.add_patch(ell)
ax.add_patch(ell_rotated)
plt.scatter(x, y)
plt.show()
x1 = np.array([238, 238, 238, 237, 237, 237, 237, 237, 236, 236, 236, 236, 237, 238,
239, 240, 240, 241, 242, 243, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254, 255, 255, 256, 257, 258, 259, 260, 261, 262, 263,
264, 265, 266, 266, 267, 267, 268, 268, 269, 269, 270, 270, 271, 271,
271, 271, 271, 272, 272, 272, 272, 272, 273, 273, 273, 273, 273, 273,
274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275,
275, 275, 274, 274, 274, 274, 274, 274, 274, 274, 274, 273, 273, 273,
272, 272, 272, 272, 271, 271, 271, 270, 270, 269, 268, 268, 267, 266,
266, 265, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 256, 255,
254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 245, 244, 243, 242,
241, 240, 239, 238, 237, 236, 235, 235, 235, 234, 234, 233, 233, 232,
232, 232, 231, 231, 230, 230, 229, 229, 229, 229, 229, 229, 229, 229,
228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230, 230,
231, 231, 231, 232, 232, 232, 232, 233, 233, 233, 234, 235, 236, 237,
238, 239, 240, 241, 242])
y1 = np.array([283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 293, 294, 295,
296, 297, 298, 299, 300, 301, 301, 301, 301, 301, 301, 301, 301, 301,
301, 301, 301, 301, 301, 301, 301, 300, 300, 299, 299, 298, 298, 297,
297, 296, 296, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286,
286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 276, 275, 274,
273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261,
260, 259, 258, 257, 256, 255, 254, 253, 252, 252, 251, 250, 249, 248,
247, 246, 245, 244, 243, 242, 242, 241, 240, 239, 238, 237, 236, 235,
234, 233, 233, 232, 232, 231, 230, 230, 229, 228, 228, 227, 227, 227,
227, 226, 226, 226, 226, 226, 226, 225, 225, 225, 225, 226, 226, 227,
228, 229, 229, 230, 231, 231, 232, 232, 233, 234, 235, 236, 237, 238,
239, 240, 241, 242, 243, 244, 245, 246, 246, 247, 248, 249, 250, 251,
252, 253, 254, 255, 256, 257, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 273, 274, 275, 276, 277,
278, 279, 280, 281, 282, 283, 284, 285, 285, 286, 287, 288, 289, 290,
291, 292, 293, 294, 295, 296, 297, 298, 299, 299, 300, 301, 301, 302,
303, 304, 304, 305, 306])
x2 = np.array( [235, 236, 237, 238, 239, 240, 241, 242, 243, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 266, 267, 268, 269, 270, 270, 271, 272,
273, 274, 274, 274, 275, 275, 276, 276, 277, 277, 278, 278, 279, 279,
279, 279, 280, 280, 280, 280, 281, 281, 281, 281, 282, 282, 282, 282,
282, 282, 282, 282, 282, 281, 281, 281, 281, 281, 281, 281, 281, 281,
280, 280, 280, 280, 280, 279, 279, 279, 279, 278, 278, 277, 277, 276,
276, 275, 275, 274, 274, 274, 273, 272, 271, 270, 269, 268, 267, 266,
265, 264, 263, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
252, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240,
240, 239, 238, 237, 236, 235, 234, 233, 232, 232, 231, 231, 230, 230,
229, 229, 228, 228, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 227,
227, 227, 227, 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 229,
229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 235,
236, 237, 238, 239, 240, 241, 242, 243, 244])
y2 = np.array(
[279, 280, 281, 282, 283, 284, 285, 286, 287, 287, 287, 288, 288, 289,
289, 290, 290, 290, 291, 291, 292, 292, 292, 292, 291, 291, 290, 290,
289, 289, 288, 288, 287, 287, 287, 286, 285, 284, 283, 282, 281, 280,
279, 278, 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, 268, 267,
267, 266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 255,
254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 244, 243, 242,
241, 240, 239, 238, 237, 236, 235, 234, 234, 233, 232, 231, 230, 229,
228, 227, 226, 225, 224, 224, 223, 222, 222, 221, 220, 219, 218, 217,
217, 216, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214,
214, 214, 214, 215, 215, 216, 216, 217, 217, 217, 218, 218, 219, 219,
219, 220, 221, 222, 223, 223, 224, 225, 226, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 236, 237, 238, 239, 240, 241, 242, 243,
244, 245, 246, 247, 248, 249, 250, 251, 251, 252, 253, 254, 255, 256,
257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 268, 269,
270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 282,
283, 284, 284, 285, 286, 287, 287, 288, 289])
plot_ellipse(x1, y1)
plot_ellipse(x2, y2)
А вот скриншоты графиков:
x1, график y1
x2, график y2
Как видите, не повернутый (красный) Эллипс хорошо подходит для данных x1, y1, но повернутый эллипс (синий) подходит для данных x2, y2.
Я запутался, если что-то здесь упустил, когда мне нужно повернуть эллипс на 90º а когда мне не нужно?