mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-02 19:23:04 +08:00
Merge pull request #410 from sciunto/circle
Circle perimeter: add new method: Andres
This commit is contained in:
+44
-8
@@ -189,7 +189,7 @@ def circle(double cy, double cx, double radius, shape=None):
|
||||
return ellipse(cy, cx, radius, radius, shape)
|
||||
|
||||
|
||||
def circle_perimeter(int cy, int cx, int radius):
|
||||
def circle_perimeter(int cy, int cx, int radius, method='bresenham'):
|
||||
"""Generate circle perimeter coordinates.
|
||||
|
||||
Parameters
|
||||
@@ -198,6 +198,10 @@ def circle_perimeter(int cy, int cx, int radius):
|
||||
Centre coordinate of circle.
|
||||
radius: int
|
||||
Radius of circle.
|
||||
method : {'bresenham', 'andres'}, optional
|
||||
bresenham : Bresenham method
|
||||
andres : Andres method
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -206,6 +210,19 @@ def circle_perimeter(int cy, int cx, int radius):
|
||||
May be used to directly index into an array, e.g.
|
||||
``img[rr, cc] = 1``.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Andres method presents the advantage that concentric
|
||||
circles create a disc whereas Bresenham can make holes. There
|
||||
is also less distortions when Andres circles are rotated.
|
||||
Bresenham method is also known as midpoint circle algorithm.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] J.E. Bresenham, "Algorithm for computer control of a digital
|
||||
plotter", 4 (1965) 25-30.
|
||||
.. [2] E. Andres, "Discrete circles, rings and spheres", 18 (1994) 695-706.
|
||||
|
||||
"""
|
||||
|
||||
cdef list rr = list()
|
||||
@@ -213,17 +230,36 @@ def circle_perimeter(int cy, int cx, int radius):
|
||||
|
||||
cdef int x = 0
|
||||
cdef int y = radius
|
||||
cdef int d = 3 - 2 * radius
|
||||
cdef int d = 0
|
||||
if method == 'bresenham':
|
||||
d = 3 - 2 * radius
|
||||
elif method == 'andres':
|
||||
d = radius - 1
|
||||
else:
|
||||
raise ValueError('Wrong method')
|
||||
|
||||
while y >= x:
|
||||
rr.extend([y, -y, y, -y, x, -x, x, -x])
|
||||
cc.extend([x, x, -x, -x, y, y, -y, -y])
|
||||
if d < 0:
|
||||
d += 4 * x + 6
|
||||
else:
|
||||
d += 4 * (x - y) + 10
|
||||
y -= 1
|
||||
x += 1
|
||||
|
||||
if method == 'bresenham':
|
||||
if d < 0:
|
||||
d += 4 * x + 6
|
||||
else:
|
||||
d += 4 * (x - y) + 10
|
||||
y -= 1
|
||||
x += 1
|
||||
elif method == 'andres':
|
||||
if d >= 2 * (x - 1):
|
||||
d = d - 2 * x
|
||||
x = x + 1
|
||||
elif d <= 2 * (radius - y):
|
||||
d = d + 2 * y - 1
|
||||
y = y - 1
|
||||
else:
|
||||
d = d + 2 * (y - x - 1)
|
||||
y = y - 1
|
||||
x = x + 1
|
||||
|
||||
return np.array(rr) + cy, np.array(cc) + cx
|
||||
|
||||
|
||||
@@ -150,14 +150,14 @@ def test_circle():
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
|
||||
def test_circle_perimeter():
|
||||
def test_circle_perimeter_bresenham():
|
||||
img = np.zeros((15, 15), 'uint8')
|
||||
rr, cc = circle_perimeter(7, 7, 0)
|
||||
rr, cc = circle_perimeter(7, 7, 0, method='bresenham')
|
||||
img[rr, cc] = 1
|
||||
assert(np.sum(img) == 1)
|
||||
|
||||
img = np.zeros((17, 15), 'uint8')
|
||||
rr, cc = circle_perimeter(7, 7, 7)
|
||||
rr, cc = circle_perimeter(7, 7, 7, method='bresenham')
|
||||
img[rr, cc] = 1
|
||||
img_ = np.array(
|
||||
[[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
|
||||
@@ -180,6 +180,36 @@ def test_circle_perimeter():
|
||||
)
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
def test_circle_perimeter_andres():
|
||||
img = np.zeros((15, 15), 'uint8')
|
||||
rr, cc = circle_perimeter(7, 7, 0, method='andres')
|
||||
img[rr, cc] = 1
|
||||
assert(np.sum(img) == 1)
|
||||
|
||||
img = np.zeros((17, 15), 'uint8')
|
||||
rr, cc = circle_perimeter(7, 7, 7, method='andres')
|
||||
img[rr, cc] = 1
|
||||
img_ = np.array(
|
||||
[[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
||||
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
|
||||
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 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]]
|
||||
)
|
||||
assert_array_equal(img, img_)
|
||||
|
||||
|
||||
def test_ellipse():
|
||||
img = np.zeros((15, 15), 'uint8')
|
||||
|
||||
Reference in New Issue
Block a user