-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTesting_Code.py
More file actions
78 lines (64 loc) · 2.77 KB
/
Copy pathTesting_Code.py
File metadata and controls
78 lines (64 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import numpy as np
import math
def generate_data(size = 100, sigma = 0.02, x_transform = 1, y_transform = 1, center_x = 0, center_y = 0):
occlusion = np.random.uniform(0.2, 0.1)
data = np.zeros((size, 2))
for i in range(size):
theta = np.random.uniform(0, 2*math.pi*occlusion)
x = x_transform*(np.cos(theta) + np.random.normal(0, sigma)) + center_x
y = y_transform*(np.sin(theta) + np.random.normal(0, sigma)) + center_y
data[i] = [x, y]
transformation = np.zeros(())
return data
def conic_to_ellipse(a, b, c, d, e, f, tol=1e-12):
"""
Convert conic parameters a x^2 + b x y + c y^2 + d x + e y + f = 0
into ellipse parameters: (center=(cx, cy), width, height, angle_degrees).
Returns:
( (cx, cy), width, height, angle_degrees )
Raises:
ValueError if the conic is degenerate or not an ellipse.
"""
a = float(a); b = float(b); c = float(c); d = float(d); e = float(e); f = float(f)
# 1) Compute center by solving [2a b; b 2c] [cx; cy] = [-d; -e]
A = np.array([[2*a, b],
[b, 2*c]], dtype=float)
rhs = -np.array([d, e], dtype=float)
detA = np.linalg.det(A)
if abs(detA) < tol:
raise ValueError("Degenerate conic: cannot solve for center (det ~ 0).")
cx, cy = np.linalg.solve(A, rhs)
# 2) Quadratic form matrix
Q = np.array([[a, b/2.0],
[b/2.0, c]], dtype=float)
# 3) Constant at the center (translated conic)
# F_c = f + [cx cy] Q [cx; cy] + d*cx + e*cy
Fc = f + (cx* (a*cx + (b/2.0)*cy) + cy*((b/2.0)*cx + c*cy)) + d*cx + e*cy
# Because the conic parameters are scale-ambiguous, flip sign if needed
# We want Q positive definite and Fc < 0 for a valid ellipse.
# Check eigenvalues of Q
vals, vecs = np.linalg.eigh(Q) # vals sorted ascending
if Fc >= 0:
# Flip all signs (doesn't change the curve)
a, b, c, d, e, f = -a, -b, -c, -d, -e, -f
Q = -Q
Fc = -Fc
vals = -vals # since Q was negated
if vals[0] <= tol or vals[1] <= tol or Fc >= -tol:
raise ValueError("Not an ellipse: quadratic form must be positive definite and Fc < 0.")
# 4) Semi-axes from diagonalized form:
# λ1 x'^2 + λ2 y'^2 + Fc = 0 => x'^2/(−Fc/λ1) + y'^2/(−Fc/λ2) = 1
r1 = np.sqrt(-Fc / vals[0])
r2 = np.sqrt(-Fc / vals[1])
# 5) Orientation: eigenvectors columns correspond to vals.
# Major axis is the larger radius
if r1 >= r2:
major_r, minor_r = r1, r2
v = vecs[:, 0] # eigenvector of vals[0]
else:
major_r, minor_r = r2, r1
v = vecs[:, 1] # eigenvector of vals[1]
angle_deg = np.degrees(np.arctan2(v[1], v[0]))
width = 2.0 * major_r
height = 2.0 * minor_r
return (cx, cy), width, height, angle_deg