34
34
_range = range
35
35
36
36
37
- def elliptic_fourier_descriptors (contour , order = 10 , normalize = False ):
37
+ def elliptic_fourier_descriptors (
38
+ contour , order = 10 , normalize = False , return_transformation = False
39
+ ):
38
40
"""Calculate elliptical Fourier descriptors for a contour.
39
41
40
42
:param numpy.ndarray contour: A contour array of size ``[M x 2]``.
41
43
:param int order: The order of Fourier coefficients to calculate.
42
44
:param bool normalize: If the coefficients should be normalized;
43
45
see references for details.
44
- :return: A ``[order x 4]`` array of Fourier coefficients.
45
- :rtype: :py:class:`numpy.ndarray`
46
+ :param bool return_transformation: If the normalization parametres should be returned.
47
+ Default is ``False``.
48
+ :return: A ``[order x 4]`` array of Fourier coefficients and optionally the
49
+ transformation parametres ``scale``, ``psi_1`` (rotation) and ``theta_1`` (phase)
50
+ :rtype: ::py:class:`numpy.ndarray` or (:py:class:`numpy.ndarray`, (float, float, float))
46
51
47
52
"""
48
53
dxy = np .diff (contour , axis = 0 )
49
54
dt = np .sqrt ((dxy ** 2 ).sum (axis = 1 ))
50
- t = np .concatenate ([([0. ]), np .cumsum (dt )])
55
+ t = np .concatenate ([([0.0 ]), np .cumsum (dt )])
51
56
T = t [- 1 ]
52
57
53
58
phi = (2 * np .pi * t ) / T
@@ -74,21 +79,24 @@ def elliptic_fourier_descriptors(contour, order=10, normalize=False):
74
79
)
75
80
76
81
if normalize :
77
- coeffs = normalize_efd (coeffs )
82
+ coeffs = normalize_efd (coeffs , return_transformation = return_transformation )
78
83
79
84
return coeffs
80
85
81
86
82
- def normalize_efd (coeffs , size_invariant = True ):
87
+ def normalize_efd (coeffs , size_invariant = True , return_transformation = False ):
83
88
"""Normalizes an array of Fourier coefficients.
84
89
85
90
See [#a]_ and [#b]_ for details.
86
91
87
92
:param numpy.ndarray coeffs: A ``[n x 4]`` Fourier coefficient array.
88
93
:param bool size_invariant: If size invariance normalizing should be done as well.
89
94
Default is ``True``.
90
- :return: The normalized ``[n x 4]`` Fourier coefficient array.
91
- :rtype: :py:class:`numpy.ndarray`
95
+ :param bool return_transformation: If the normalization parametres should be returned.
96
+ Default is ``False``.
97
+ :return: The normalized ``[n x 4]`` Fourier coefficient array and optionally the
98
+ transformation parametres ``scale``, :math:`psi_1` (rotation) and :math:`theta_1` (phase)
99
+ :rtype: :py:class:`numpy.ndarray` or (:py:class:`numpy.ndarray`, (float, float, float))
92
100
93
101
"""
94
102
# Make the coefficients have a zero phase shift from
@@ -136,11 +144,15 @@ def normalize_efd(coeffs, size_invariant=True):
136
144
)
137
145
).flatten ()
138
146
147
+ size = coeffs [0 , 0 ]
139
148
if size_invariant :
140
149
# Obtain size-invariance by normalizing.
141
- coeffs /= np .abs (coeffs [ 0 , 0 ] )
150
+ coeffs /= np .abs (size )
142
151
143
- return coeffs
152
+ if return_transformation :
153
+ return coeffs , (size , psi_1 , theta_1 )
154
+ else :
155
+ return coeffs
144
156
145
157
146
158
def calculate_dc_coefficients (contour ):
@@ -153,7 +165,7 @@ def calculate_dc_coefficients(contour):
153
165
"""
154
166
dxy = np .diff (contour , axis = 0 )
155
167
dt = np .sqrt ((dxy ** 2 ).sum (axis = 1 ))
156
- t = np .concatenate ([([0. ]), np .cumsum (dt )])
168
+ t = np .concatenate ([([0.0 ]), np .cumsum (dt )])
157
169
T = t [- 1 ]
158
170
159
171
xi = np .cumsum (dxy [:, 0 ]) - (dxy [:, 0 ] / dt ) * t [1 :]
@@ -199,7 +211,7 @@ def reconstruct_contour(coeffs, locus=(0, 0), num_points=300):
199
211
return reconstruction
200
212
201
213
202
- def plot_efd (coeffs , locus = (0. , 0. ), image = None , contour = None , n = 300 ):
214
+ def plot_efd (coeffs , locus = (0.0 , 0.0 ), image = None , contour = None , n = 300 ):
203
215
"""Plot a ``[2 x (N / 2)]`` grid of successive truncations of the series.
204
216
205
217
.. note::
0 commit comments