mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 06:33:19 +08:00
Fixed ellipse symmetry and added some tests.
This commit is contained in:
+27
-13
@@ -7,6 +7,15 @@ def _coords_inside_image(rr, cc, shape):
|
||||
return rr[mask], cc[mask]
|
||||
|
||||
|
||||
def _ellipse_in_shape(shape, center, radiuses):
|
||||
"""Generate coordinates of points within ellipse bounded by shape."""
|
||||
y, x = np.ogrid[0:shape[0], 0:shape[1]]
|
||||
cy, cx = center
|
||||
ry, rx = radiuses
|
||||
distances = ((y - cy) / ry) ** 2 + ((x - cx) / rx) ** 2
|
||||
return np.nonzero(distances < 1)
|
||||
|
||||
|
||||
def ellipse(cy, cx, yradius, xradius, shape=None):
|
||||
"""Generate coordinates of pixels within ellipse.
|
||||
|
||||
@@ -48,21 +57,26 @@ def ellipse(cy, cx, yradius, xradius, shape=None):
|
||||
|
||||
"""
|
||||
|
||||
dr = 1 / float(yradius)
|
||||
dc = 1 / float(xradius)
|
||||
|
||||
r, c = np.ogrid[-1:1:dr, -1:1:dc]
|
||||
rr, cc = np.nonzero(r ** 2 + c ** 2 < 1)
|
||||
|
||||
rr.flags.writeable = True
|
||||
cc.flags.writeable = True
|
||||
rr += cy - yradius
|
||||
cc += cx - xradius
|
||||
|
||||
center = np.array([cy, cx])
|
||||
radiuses = np.array([yradius, xradius])
|
||||
if shape is not None:
|
||||
return _coords_inside_image(rr, cc, shape)
|
||||
return _ellipse_in_shape(shape, center, radiuses)
|
||||
else:
|
||||
# rounding here is necessary to avoid rounding issues later
|
||||
upper_left = np.floor(center - radiuses)
|
||||
|
||||
return rr, cc
|
||||
shifted_center = center - upper_left
|
||||
|
||||
# Shifted center is in interval [radiuses, radiuses + 1], so
|
||||
# the ellipse must fit in [0, 2*radiuses + 1].
|
||||
bounding_shape = np.ceil(2 * radiuses + 1)
|
||||
|
||||
rr, cc = _ellipse_in_shape(bounding_shape, shifted_center, radiuses)
|
||||
rr.flags.writeable = True
|
||||
cc.flags.writeable = True
|
||||
rr += upper_left[0]
|
||||
cc += upper_left[1]
|
||||
return rr, cc
|
||||
|
||||
|
||||
def circle(cy, cx, radius, shape=None):
|
||||
|
||||
+139
-21
@@ -298,30 +298,134 @@ def test_circle_perimeter_aa():
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
|
||||
def test_ellipse():
|
||||
img = np.zeros((15, 15), 'uint8')
|
||||
def test_ellipse_trivial():
|
||||
img = np.zeros((2, 2), 'uint8')
|
||||
rr, cc = ellipse(0.5, 0.5, 0.5, 0.5)
|
||||
img[rr, cc] = 1
|
||||
img_correct = np.array([
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
])
|
||||
assert_array_equal(img, img_correct)
|
||||
|
||||
img = np.zeros((2, 2), 'uint8')
|
||||
rr, cc = ellipse(0.5, 0.5, 1.1, 1.1)
|
||||
img[rr, cc] = 1
|
||||
img_correct = np.array([
|
||||
[1, 1],
|
||||
[1, 1],
|
||||
])
|
||||
assert_array_equal(img, img_correct)
|
||||
|
||||
img = np.zeros((3, 3), 'uint8')
|
||||
rr, cc = ellipse(1, 1, 0.9, 0.9)
|
||||
img[rr, cc] = 1
|
||||
img_correct = np.array([
|
||||
[0, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 0],
|
||||
])
|
||||
assert_array_equal(img, img_correct)
|
||||
|
||||
img = np.zeros((3, 3), 'uint8')
|
||||
rr, cc = ellipse(1, 1, 1.1, 1.1)
|
||||
img[rr, cc] = 1
|
||||
img_correct = np.array([
|
||||
[0, 1, 0],
|
||||
[1, 1, 1],
|
||||
[0, 1, 0],
|
||||
])
|
||||
assert_array_equal(img, img_correct)
|
||||
|
||||
img = np.zeros((3, 3), 'uint8')
|
||||
rr, cc = ellipse(1, 1, 1.5, 1.5)
|
||||
img[rr, cc] = 1
|
||||
img_correct = np.array([
|
||||
[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
])
|
||||
assert_array_equal(img, img_correct)
|
||||
|
||||
|
||||
def test_ellipse_generic():
|
||||
img = np.zeros((4, 4), 'uint8')
|
||||
rr, cc = ellipse(1.5, 1.5, 1.1, 1.7)
|
||||
img[rr, cc] = 1
|
||||
img_ = np.array([
|
||||
[0, 0, 0, 0],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1],
|
||||
[0, 0, 0, 0],
|
||||
])
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
img = np.zeros((5, 5), 'uint8')
|
||||
rr, cc = ellipse(2, 2, 1.7, 1.7)
|
||||
img[rr, cc] = 1
|
||||
img_ = np.array([
|
||||
[0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0],
|
||||
])
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
img = np.zeros((10, 10), 'uint8')
|
||||
rr, cc = ellipse(5, 5, 3, 4)
|
||||
img[rr, cc] = 1
|
||||
img_ = np.array([
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
])
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
img = np.zeros((10, 10), 'uint8')
|
||||
rr, cc = ellipse(4.5, 5, 3.5, 4)
|
||||
img[rr, cc] = 1
|
||||
img_ = np.array([
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
])
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
img = np.zeros((15, 15), 'uint8')
|
||||
rr, cc = ellipse(7, 7, 3, 7)
|
||||
img[rr, cc] = 1
|
||||
|
||||
img_ = np.array(
|
||||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||
)
|
||||
|
||||
img_ = np.array([
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
])
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
|
||||
@@ -352,6 +456,20 @@ def test_ellipse_with_shape():
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
|
||||
def test_ellipse_negative():
|
||||
rr, cc = ellipse(-3, -3, 1.7, 1.7)
|
||||
rr_, cc_ = np.nonzero(np.array([
|
||||
[0, 0, 0, 0, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 1, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0],
|
||||
]))
|
||||
|
||||
assert_array_equal(rr, rr_ - 5)
|
||||
assert_array_equal(cc, cc_ - 5)
|
||||
|
||||
|
||||
def test_ellipse_perimeter_dot_zeroangle():
|
||||
# dot, angle == 0
|
||||
img = np.zeros((30, 15), 'uint8')
|
||||
|
||||
Reference in New Issue
Block a user