Merge pull request #840 from ahojnnes/estimator-params

Make estimator class parameters public
This commit is contained in:
Stefan van der Walt
2014-01-22 16:28:49 -08:00
7 changed files with 166 additions and 88 deletions
+5
View File
@@ -3,6 +3,11 @@ Version 0.11
* Remove deprecated `reverse_map` parameter of `skimage.transform.warp`
* Change depecrated `enforce_connectivity=False`on skimage.segmentation.slic
and set it to True as default
* Remove deprecated `skimage.measure.fit.BaseModel._params` attribute
* Remove deprecated `skimage.measure.fit.BaseModel._params`,
`skimage.transform.ProjectiveTransform._matrix`,
`skimage.transform.PolynomialTransform._params`,
`skimage.transform.PiecewiseAffineTransform.affines_*` attributes
Version 0.10
------------
+2 -2
View File
@@ -33,14 +33,14 @@ First we create a transformation using explicit parameters:
tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 2,
translation=(0, 1))
print(tform._matrix)
print(tform.params)
"""
Alternatively you can define a transformation by the transformation matrix
itself:
"""
matrix = tform._matrix.copy()
matrix = tform.params.copy()
matrix[1, 2] = 2
tform2 = tf.SimilarityTransform(matrix)
+37 -22
View File
@@ -1,4 +1,5 @@
import math
import warnings
import numpy as np
from scipy import optimize
@@ -11,7 +12,13 @@ def _check_data_dim(data, dim):
class BaseModel(object):
def __init__(self):
self._params = None
self.params = None
@property
def _params(self):
warnings.warn('`_params` attribute is deprecated, '
'use `params` instead.')
return self.params
class LineModel(BaseModel):
@@ -30,12 +37,13 @@ class LineModel(BaseModel):
min{ sum((dist - x_i * cos(theta) + y_i * sin(theta))**2) }
The ``_params`` attribute contains the parameters in the following order::
dist, theta
A minimum number of 2 points is required to solve for the parameters.
Attributes
----------
params : tuple
Line model parameters in the following order `dist`, `theta`.
"""
def estimate(self, data):
@@ -68,7 +76,7 @@ class LineModel(BaseModel):
# line always passes through mean
dist = X0[0] * math.cos(theta) + X0[1] * math.sin(theta)
self._params = (dist, theta)
self.params = (dist, theta)
def residuals(self, data):
"""Determine residuals of data to model.
@@ -89,7 +97,7 @@ class LineModel(BaseModel):
_check_data_dim(data, dim=2)
dist, theta = self._params
dist, theta = self.params
x = data[:, 0]
y = data[:, 1]
@@ -114,7 +122,7 @@ class LineModel(BaseModel):
"""
if params is None:
params = self._params
params = self.params
dist, theta = params
return (dist - y * math.sin(theta)) / math.cos(theta)
@@ -136,7 +144,7 @@ class LineModel(BaseModel):
"""
if params is None:
params = self._params
params = self.params
dist, theta = params
return (dist - x * math.cos(theta)) / math.sin(theta)
@@ -154,12 +162,13 @@ class CircleModel(BaseModel):
min{ sum((r - sqrt((x_i - xc)**2 + (y_i - yc)**2))**2) }
The ``_params`` attribute contains the parameters in the following order::
xc, yc, r
A minimum number of 3 points is required to solve for the parameters.
Attributes
----------
params : tuple
Circle model parameters in the following order `xc`, `yc`, `r`.
"""
def estimate(self, data):
@@ -203,7 +212,7 @@ class CircleModel(BaseModel):
params0 = (xc0, yc0, r0)
params, _ = optimize.leastsq(fun, params0, Dfun=Dfun, col_deriv=True)
self._params = params
self.params = params
def residuals(self, data):
"""Determine residuals of data to model.
@@ -224,7 +233,7 @@ class CircleModel(BaseModel):
_check_data_dim(data, dim=2)
xc, yc, r = self._params
xc, yc, r = self.params
x = data[:, 0]
y = data[:, 1]
@@ -249,7 +258,7 @@ class CircleModel(BaseModel):
"""
if params is None:
params = self._params
params = self.params
xc, yc, r = params
x = xc + r * np.cos(t)
@@ -279,12 +288,18 @@ class EllipseModel(BaseModel):
Thus you have ``2 * N`` equations (x_i, y_i) for ``N + 5`` unknowns (t_i,
xc, yc, a, b, theta), which gives you an effective redundancy of ``N - 5``.
The ``_params`` attribute contains the parameters in the following order::
The ``params`` attribute contains the parameters in the following order::
xc, yc, a, b, theta
A minimum number of 5 points is required to solve for the parameters.
Attributes
----------
params : tuple
Ellipse model parameters in the following order `xc`, `yc`, `a`,
`b`, `theta`.
"""
def estimate(self, data):
@@ -353,7 +368,7 @@ class EllipseModel(BaseModel):
params, _ = optimize.leastsq(fun, params0, Dfun=Dfun, col_deriv=True)
self._params = params[:5]
self.params = params[:5]
def residuals(self, data):
"""Determine residuals of data to model.
@@ -374,7 +389,7 @@ class EllipseModel(BaseModel):
_check_data_dim(data, dim=2)
xc, yc, a, b, theta = self._params
xc, yc, a, b, theta = self.params
ctheta = math.cos(theta)
stheta = math.sin(theta)
@@ -436,7 +451,7 @@ class EllipseModel(BaseModel):
"""
if params is None:
params = self._params
params = self.params
xc, yc, a, b, theta = params
ct = np.cos(t)
@@ -550,7 +565,7 @@ def ransac(data, model_class, min_samples, residual_threshold,
>>> model = EllipseModel()
>>> model.estimate(data)
>>> model._params # doctest: +SKIP
>>> model.params # doctest: +SKIP
array([ -3.30354146e+03, -2.87791160e+03, 5.59062118e+03,
7.84365066e+00, 7.19203152e-01])
@@ -558,7 +573,7 @@ def ransac(data, model_class, min_samples, residual_threshold,
Estimate ellipse model using RANSAC:
>>> ransac_model, inliers = ransac(data, EllipseModel, 5, 3, max_trials=50)
>>> ransac_model._params
>>> ransac_model.params
array([ 20.12762373, 29.73563063, 4.81499637, 10.4743584 , 0.05217117])
>>> inliers
array([False, False, False, False, True, True, True, True, True,
+23 -15
View File
@@ -10,7 +10,7 @@ def test_line_model_invalid_input():
def test_line_model_predict():
model = LineModel()
model._params = (10, 1)
model.params = (10, 1)
x = np.arange(-10, 10)
y = model.predict_y(x)
assert_almost_equal(x, model.predict_x(y))
@@ -19,7 +19,7 @@ def test_line_model_predict():
def test_line_model_estimate():
# generate original data without noise
model0 = LineModel()
model0._params = (10, 1)
model0.params = (10, 1)
x0 = np.arange(-100, 100)
y0 = model0.predict_y(x0)
data0 = np.column_stack([x0, y0])
@@ -33,16 +33,16 @@ def test_line_model_estimate():
model_est.estimate(data)
# test whether estimated parameters almost equal original parameters
assert_almost_equal(model0._params, model_est._params, 1)
assert_almost_equal(model0.params, model_est.params, 1)
def test_line_model_residuals():
model = LineModel()
model._params = (0, 0)
model.params = (0, 0)
assert_equal(abs(model.residuals(np.array([[0, 0]]))), 0)
assert_equal(abs(model.residuals(np.array([[0, 10]]))), 0)
assert_equal(abs(model.residuals(np.array([[10, 0]]))), 10)
model._params = (5, np.pi / 4)
model.params = (5, np.pi / 4)
assert_equal(abs(model.residuals(np.array([[0, 0]]))), 5)
assert_almost_equal(abs(model.residuals(np.array([[np.sqrt(50), 0]]))), 0)
@@ -59,7 +59,7 @@ def test_circle_model_invalid_input():
def test_circle_model_predict():
model = CircleModel()
r = 5
model._params = (0, 0, r)
model.params = (0, 0, r)
t = np.arange(0, 2 * np.pi, np.pi / 2)
xy = np.array(((5, 0), (0, 5), (-5, 0), (0, -5)))
@@ -69,7 +69,7 @@ def test_circle_model_predict():
def test_circle_model_estimate():
# generate original data without noise
model0 = CircleModel()
model0._params = (10, 12, 3)
model0.params = (10, 12, 3)
t = np.linspace(0, 2 * np.pi, 1000)
data0 = model0.predict_xy(t)
@@ -82,12 +82,12 @@ def test_circle_model_estimate():
model_est.estimate(data)
# test whether estimated parameters almost equal original parameters
assert_almost_equal(model0._params, model_est._params, 1)
assert_almost_equal(model0.params, model_est.params, 1)
def test_circle_model_residuals():
model = CircleModel()
model._params = (0, 0, 5)
model.params = (0, 0, 5)
assert_almost_equal(abs(model.residuals(np.array([[5, 0]]))), 0)
assert_almost_equal(abs(model.residuals(np.array([[6, 6]]))),
np.sqrt(2 * 6**2) - 5)
@@ -101,7 +101,7 @@ def test_ellipse_model_invalid_input():
def test_ellipse_model_predict():
model = EllipseModel()
r = 5
model._params = (0, 0, 5, 10, 0)
model.params = (0, 0, 5, 10, 0)
t = np.arange(0, 2 * np.pi, np.pi / 2)
xy = np.array(((5, 0), (0, 10), (-5, 0), (0, -10)))
@@ -111,7 +111,7 @@ def test_ellipse_model_predict():
def test_ellipse_model_estimate():
# generate original data without noise
model0 = EllipseModel()
model0._params = (10, 20, 15, 25, 0)
model0.params = (10, 20, 15, 25, 0)
t = np.linspace(0, 2 * np.pi, 100)
data0 = model0.predict_xy(t)
@@ -124,13 +124,13 @@ def test_ellipse_model_estimate():
model_est.estimate(data)
# test whether estimated parameters almost equal original parameters
assert_almost_equal(model0._params, model_est._params, 0)
assert_almost_equal(model0.params, model_est.params, 0)
def test_ellipse_model_residuals():
model = EllipseModel()
# vertical line through origin
model._params = (0, 0, 10, 5, 0)
model.params = (0, 0, 10, 5, 0)
assert_almost_equal(abs(model.residuals(np.array([[10, 0]]))), 0)
assert_almost_equal(abs(model.residuals(np.array([[0, 5]]))), 0)
assert_almost_equal(abs(model.residuals(np.array([[0, 10]]))), 5)
@@ -141,7 +141,7 @@ def test_ransac_shape():
# generate original data without noise
model0 = CircleModel()
model0._params = (10, 12, 3)
model0.params = (10, 12, 3)
t = np.linspace(0, 2 * np.pi, 1000)
data0 = model0.predict_xy(t)
@@ -155,7 +155,7 @@ def test_ransac_shape():
model_est, inliers = ransac(data0, CircleModel, 3, 5)
# test whether estimated parameters equal original parameters
assert_equal(model0._params, model_est._params)
assert_equal(model0.params, model_est.params)
for outlier in outliers:
assert outlier not in inliers
@@ -204,5 +204,13 @@ def test_ransac_is_model_valid():
assert_equal(inliers, None)
def test_deprecated_params_attribute():
model = LineModel()
model.params = (10, 1)
x = np.arange(-10, 10)
y = model.predict_y(x)
assert_equal(model.params, model._params)
if __name__ == "__main__":
np.testing.run_module_suite()
+74 -33
View File
@@ -1,5 +1,6 @@
import six
import math
import warnings
import numpy as np
from scipy import ndimage, spatial
@@ -103,6 +104,11 @@ class ProjectiveTransform(GeometricTransform):
matrix : (3, 3) array, optional
Homogeneous transformation matrix.
Attributes
----------
params : (3, 3) array
Homogeneous transformation matrix.
"""
_coeffs = range(8)
@@ -113,11 +119,17 @@ class ProjectiveTransform(GeometricTransform):
matrix = np.eye(3)
if matrix.shape != (3, 3):
raise ValueError("invalid shape of transformation matrix")
self._matrix = matrix
self.params = matrix
@property
def _matrix(self):
warnings.warn('`_matrix` attribute is deprecated, '
'use `params` instead.')
return self.params
@property
def _inv_matrix(self):
return np.linalg.inv(self._matrix)
return np.linalg.inv(self.params)
def _apply_mat(self, coords, matrix):
coords = np.array(coords, copy=False, ndmin=2)
@@ -133,7 +145,7 @@ class ProjectiveTransform(GeometricTransform):
return dst[:, :2]
def __call__(self, coords):
return self._apply_mat(coords, self._matrix)
return self._apply_mat(coords, self.params)
def inverse(self, coords):
"""Apply inverse transformation.
@@ -235,7 +247,7 @@ class ProjectiveTransform(GeometricTransform):
H.flat[list(self._coeffs) + [8]] = - V[-1, :-1] / V[-1, -1]
H[2, 2] = 1
self._matrix = H
self.params = H
def __add__(self, other):
"""Combine this transformation with another.
@@ -248,7 +260,7 @@ class ProjectiveTransform(GeometricTransform):
tform = self.__class__
else:
tform = ProjectiveTransform
return tform(other._matrix.dot(self._matrix))
return tform(other.params.dot(self.params))
else:
raise TypeError("Cannot combine transformations of differing "
"types.")
@@ -284,6 +296,11 @@ class AffineTransform(ProjectiveTransform):
translation : (tx, ty) as array, list or tuple, optional
Translation parameters.
Attributes
----------
params : (3, 3) array
Homogeneous transformation matrix.
"""
_coeffs = range(6)
@@ -299,7 +316,7 @@ class AffineTransform(ProjectiveTransform):
elif matrix is not None:
if matrix.shape != (3, 3):
raise ValueError("Invalid shape of transformation matrix.")
self._matrix = matrix
self.params = matrix
elif params:
if scale is None:
scale = (1, 1)
@@ -311,34 +328,34 @@ class AffineTransform(ProjectiveTransform):
translation = (0, 0)
sx, sy = scale
self._matrix = np.array([
self.params = np.array([
[sx * math.cos(rotation), -sy * math.sin(rotation + shear), 0],
[sx * math.sin(rotation), sy * math.cos(rotation + shear), 0],
[ 0, 0, 1]
])
self._matrix[0:2, 2] = translation
self.params[0:2, 2] = translation
else:
# default to an identity transform
self._matrix = np.eye(3)
self.params = np.eye(3)
@property
def scale(self):
sx = math.sqrt(self._matrix[0, 0] ** 2 + self._matrix[1, 0] ** 2)
sy = math.sqrt(self._matrix[0, 1] ** 2 + self._matrix[1, 1] ** 2)
sx = math.sqrt(self.params[0, 0] ** 2 + self.params[1, 0] ** 2)
sy = math.sqrt(self.params[0, 1] ** 2 + self.params[1, 1] ** 2)
return sx, sy
@property
def rotation(self):
return math.atan2(self._matrix[1, 0], self._matrix[0, 0])
return math.atan2(self.params[1, 0], self.params[0, 0])
@property
def shear(self):
beta = math.atan2(- self._matrix[0, 1], self._matrix[1, 1])
beta = math.atan2(- self.params[0, 1], self.params[1, 1])
return beta - self.rotation
@property
def translation(self):
return self._matrix[0:2, 2]
return self.params[0:2, 2]
class PiecewiseAffineTransform(GeometricTransform):
@@ -349,13 +366,20 @@ class PiecewiseAffineTransform(GeometricTransform):
a Delaunay triangulation of the points to form a mesh. Each triangle is
used to find a local affine transform.
Attributes
----------
affines : list of AffineTransform objects
Affine transformations for each triangle in the mesh.
inverse_affines : list of AffineTransform objects
Inverse affine transformations for each triangle in the mesh.
"""
def __init__(self):
self._tesselation = None
self._inverse_tesselation = None
self.affines = []
self.inverse_affines = []
self.affines = None
self.inverse_affines = None
def estimate(self, src, dst):
"""Set the control points with which to perform the piecewise mapping.
@@ -488,6 +512,11 @@ class SimilarityTransform(ProjectiveTransform):
translation : (tx, ty) as array, list or tuple, optional
x, y translation parameters.
Attributes
----------
params : (3, 3) array
Homogeneous transformation matrix.
"""
def __init__(self, matrix=None, scale=None, rotation=None,
@@ -501,7 +530,7 @@ class SimilarityTransform(ProjectiveTransform):
elif matrix is not None:
if matrix.shape != (3, 3):
raise ValueError("Invalid shape of transformation matrix.")
self._matrix = matrix
self.params = matrix
elif params:
if scale is None:
scale = 1
@@ -510,16 +539,16 @@ class SimilarityTransform(ProjectiveTransform):
if translation is None:
translation = (0, 0)
self._matrix = np.array([
self.params = np.array([
[math.cos(rotation), - math.sin(rotation), 0],
[math.sin(rotation), math.cos(rotation), 0],
[ 0, 0, 1]
])
self._matrix[0:2, 0:2] *= scale
self._matrix[0:2, 2] = translation
self.params[0:2, 0:2] *= scale
self.params[0:2, 2] = translation
else:
# default to an identity transform
self._matrix = np.eye(3)
self.params = np.eye(3)
def estimate(self, src, dst):
"""Set the transformation matrix with the explicit parameters.
@@ -585,7 +614,7 @@ class SimilarityTransform(ProjectiveTransform):
# singular value
a0, a1, b0, b1 = - V[-1, :-1] / V[-1, -1]
self._matrix = np.array([[a0, -b0, a1],
self.params = np.array([[a0, -b0, a1],
[b0, a0, b1],
[ 0, 0, 1]])
@@ -593,18 +622,18 @@ class SimilarityTransform(ProjectiveTransform):
def scale(self):
if math.cos(self.rotation) == 0:
# sin(self.rotation) == 1
scale = self._matrix[0, 1]
scale = self.params[0, 1]
else:
scale = self._matrix[0, 0] / math.cos(self.rotation)
scale = self.params[0, 0] / math.cos(self.rotation)
return scale
@property
def rotation(self):
return math.atan2(self._matrix[1, 0], self._matrix[1, 1])
return math.atan2(self.params[1, 0], self.params[1, 1])
@property
def translation(self):
return self._matrix[0:2, 2]
return self.params[0:2, 2]
class PolynomialTransform(GeometricTransform):
@@ -619,6 +648,12 @@ class PolynomialTransform(GeometricTransform):
Polynomial coefficients where `N * 2 = (order + 1) * (order + 2)`. So,
a_ji is defined in `params[0, :]` and b_ji in `params[1, :]`.
Attributes
----------
params : (2, N) array
Polynomial coefficients where `N * 2 = (order + 1) * (order + 2)`. So,
a_ji is defined in `params[0, :]` and b_ji in `params[1, :]`.
"""
def __init__(self, params=None):
@@ -627,7 +662,13 @@ class PolynomialTransform(GeometricTransform):
params = np.array([[0, 1, 0], [0, 0, 1]])
if params.shape[0] != 2:
raise ValueError("invalid shape of transformation parameters")
self._params = params
self.params = params
@property
def _params(self):
warnings.warn('`_params` attribute is deprecated, '
'use `params` instead.')
return self.params
def estimate(self, src, dst, order=2):
"""Set the transformation matrix with the explicit transformation
@@ -700,7 +741,7 @@ class PolynomialTransform(GeometricTransform):
# singular value
params = - V[-1, :-1] / V[-1, -1]
self._params = params.reshape((2, u / 2))
self.params = params.reshape((2, u / 2))
def __call__(self, coords):
"""Apply forward transformation.
@@ -718,7 +759,7 @@ class PolynomialTransform(GeometricTransform):
"""
x = coords[:, 0]
y = coords[:, 1]
u = len(self._params.ravel())
u = len(self.params.ravel())
# number of coefficients -> u = (order + 1) * (order + 2)
order = int((- 3 + math.sqrt(9 - 4 * (2 - u))) / 2)
dst = np.zeros(coords.shape)
@@ -726,8 +767,8 @@ class PolynomialTransform(GeometricTransform):
pidx = 0
for j in range(order + 1):
for i in range(j + 1):
dst[:, 0] += self._params[0, pidx] * x ** (j - i) * y ** i
dst[:, 1] += self._params[1, pidx] * x ** (j - i) * y ** i
dst[:, 0] += self.params[0, pidx] * x ** (j - i) * y ** i
dst[:, 1] += self.params[1, pidx] * x ** (j - i) * y ** i
pidx += 1
return dst
@@ -1046,14 +1087,14 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1,
# inverse_map is a homography
elif isinstance(inverse_map, HOMOGRAPHY_TRANSFORMS):
matrix = inverse_map._matrix
matrix = inverse_map.params
# inverse_map is the inverse of a homography
elif (hasattr(inverse_map, '__name__')
and inverse_map.__name__ == 'inverse'
and get_bound_method_class(inverse_map) \
in HOMOGRAPHY_TRANSFORMS):
matrix = np.linalg.inv(six.get_method_self(inverse_map)._matrix)
matrix = np.linalg.inv(six.get_method_self(inverse_map).params)
if matrix is not None:
matrix = matrix.astype(np.double)
+24 -15
View File
@@ -56,19 +56,19 @@ def test_similarity_estimation():
# exact solution
tform = estimate_transform('similarity', SRC[:2, :], DST[:2, :])
assert_array_almost_equal(tform(SRC[:2, :]), DST[:2, :])
assert_equal(tform._matrix[0, 0], tform._matrix[1, 1])
assert_equal(tform._matrix[0, 1], - tform._matrix[1, 0])
assert_equal(tform.params[0, 0], tform.params[1, 1])
assert_equal(tform.params[0, 1], - tform.params[1, 0])
# over-determined
tform2 = estimate_transform('similarity', SRC, DST)
assert_array_almost_equal(tform2.inverse(tform2(SRC)), SRC)
assert_equal(tform2._matrix[0, 0], tform2._matrix[1, 1])
assert_equal(tform2._matrix[0, 1], - tform2._matrix[1, 0])
assert_equal(tform2.params[0, 0], tform2.params[1, 1])
assert_equal(tform2.params[0, 1], - tform2.params[1, 0])
# via estimate method
tform3 = SimilarityTransform()
tform3.estimate(SRC, DST)
assert_array_almost_equal(tform3._matrix, tform2._matrix)
assert_array_almost_equal(tform3.params, tform2.params)
def test_similarity_init():
@@ -83,7 +83,7 @@ def test_similarity_init():
assert_array_almost_equal(tform.translation, translation)
# init with transformation matrix
tform2 = SimilarityTransform(tform._matrix)
tform2 = SimilarityTransform(tform.params)
assert_array_almost_equal(tform2.scale, scale)
assert_array_almost_equal(tform2.rotation, rotation)
assert_array_almost_equal(tform2.translation, translation)
@@ -111,7 +111,7 @@ def test_affine_estimation():
# via estimate method
tform3 = AffineTransform()
tform3.estimate(SRC, DST)
assert_array_almost_equal(tform3._matrix, tform2._matrix)
assert_array_almost_equal(tform3.params, tform2.params)
def test_affine_init():
@@ -128,7 +128,7 @@ def test_affine_init():
assert_array_almost_equal(tform.translation, translation)
# init with transformation matrix
tform2 = AffineTransform(tform._matrix)
tform2 = AffineTransform(tform.params)
assert_array_almost_equal(tform2.scale, scale)
assert_array_almost_equal(tform2.rotation, rotation)
assert_array_almost_equal(tform2.shear, shear)
@@ -155,14 +155,14 @@ def test_projective_estimation():
# via estimate method
tform3 = ProjectiveTransform()
tform3.estimate(SRC, DST)
assert_array_almost_equal(tform3._matrix, tform2._matrix)
assert_array_almost_equal(tform3.params, tform2.params)
def test_projective_init():
tform = estimate_transform('projective', SRC, DST)
# init with transformation matrix
tform2 = ProjectiveTransform(tform._matrix)
assert_array_almost_equal(tform2._matrix, tform._matrix)
tform2 = ProjectiveTransform(tform.params)
assert_array_almost_equal(tform2.params, tform.params)
def test_polynomial_estimation():
@@ -173,20 +173,20 @@ def test_polynomial_estimation():
# via estimate method
tform2 = PolynomialTransform()
tform2.estimate(SRC, DST, order=10)
assert_array_almost_equal(tform2._params, tform._params)
assert_array_almost_equal(tform2.params, tform.params)
def test_polynomial_init():
tform = estimate_transform('polynomial', SRC, DST, order=10)
# init with transformation parameters
tform2 = PolynomialTransform(tform._params)
assert_array_almost_equal(tform2._params, tform._params)
tform2 = PolynomialTransform(tform.params)
assert_array_almost_equal(tform2.params, tform.params)
def test_polynomial_default_order():
tform = estimate_transform('polynomial', SRC, DST)
tform2 = estimate_transform('polynomial', SRC, DST, order=2)
assert_array_almost_equal(tform2._params, tform._params)
assert_array_almost_equal(tform2.params, tform.params)
def test_polynomial_inverse():
@@ -228,6 +228,15 @@ def test_invalid_input():
assert_raises(ValueError, PolynomialTransform, np.zeros((3, 3)))
def test_deprecated_params_attributes():
for t in ('projective', 'affine', 'similarity'):
tform = estimate_transform(t, SRC, DST)
assert_equal(tform._matrix, tform.params)
tform = estimate_transform('polynomial', SRC, DST, order=3)
assert_equal(tform._params, tform.params)
if __name__ == "__main__":
from numpy.testing import run_module_suite
run_module_suite()
+1 -1
View File
@@ -243,7 +243,7 @@ def test_invalid():
def test_inverse():
tform = SimilarityTransform(scale=0.5, rotation=0.1)
inverse_tform = SimilarityTransform(matrix=np.linalg.inv(tform._matrix))
inverse_tform = SimilarityTransform(matrix=np.linalg.inv(tform.params))
image = np.arange(10 * 10).reshape(10, 10).astype(np.double)
assert_array_equal(warp(image, inverse_tform), warp(image, tform.inverse))