mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-02 00:46:26 +08:00
Merge pull request #1156 from alexeyum/ellipse-symmetry
Ellipse symmetry
This commit is contained in:
+4
-1
@@ -187,4 +187,7 @@
|
||||
PIL Image import and export improvements
|
||||
|
||||
- Geoffrey French
|
||||
skimage.filters.rank.windowed_histogram and plot_windowed_histogram example.
|
||||
skimage.filters.rank.windowed_histogram and plot_windowed_histogram example.
|
||||
|
||||
- Alexey Umnov
|
||||
skimage.draw.ellipse bug fix and tests.
|
||||
|
||||
+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:float(shape[0]), 0:float(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