mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-13 17:45:20 +08:00
Fix and clean up anti-aliased line drawing (closes #1563)
This commit is contained in:
+39
-30
@@ -37,14 +37,14 @@ def _coords_inside_image(rr, cc, shape, val=None):
|
||||
return rr[mask], cc[mask]
|
||||
|
||||
|
||||
def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2):
|
||||
def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y1, Py_ssize_t x1):
|
||||
"""Generate line pixel coordinates.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
y, x : int
|
||||
Starting position (row, column).
|
||||
y2, x2 : int
|
||||
y1, x1 : int
|
||||
End position (row, column).
|
||||
|
||||
Returns
|
||||
@@ -79,16 +79,16 @@ def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2):
|
||||
"""
|
||||
|
||||
cdef char steep = 0
|
||||
cdef Py_ssize_t dx = abs(x2 - x)
|
||||
cdef Py_ssize_t dy = abs(y2 - y)
|
||||
cdef Py_ssize_t dx = abs(x1 - x)
|
||||
cdef Py_ssize_t dy = abs(y1 - y)
|
||||
cdef Py_ssize_t sx, sy, d, i
|
||||
|
||||
with nogil:
|
||||
if (x2 - x) > 0:
|
||||
if (x1 - x) > 0:
|
||||
sx = 1
|
||||
else:
|
||||
sx = -1
|
||||
if (y2 - y) > 0:
|
||||
if (y1 - y) > 0:
|
||||
sy = 1
|
||||
else:
|
||||
sy = -1
|
||||
@@ -116,20 +116,20 @@ def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2):
|
||||
x = x + sx
|
||||
d = d + (2 * dy)
|
||||
|
||||
rr[dx] = y2
|
||||
cc[dx] = x2
|
||||
rr[dx] = y1
|
||||
cc[dx] = x1
|
||||
|
||||
return np.asarray(rr), np.asarray(cc)
|
||||
|
||||
|
||||
def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2):
|
||||
def line_aa(Py_ssize_t y0, Py_ssize_t x0, Py_ssize_t y1, Py_ssize_t x1):
|
||||
"""Generate anti-aliased line pixel coordinates.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
y1, x1 : int
|
||||
y0, x0 : int
|
||||
Starting position (row, column).
|
||||
y2, x2 : int
|
||||
y1, x1 : int
|
||||
End position (row, column).
|
||||
|
||||
Returns
|
||||
@@ -165,17 +165,22 @@ def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2):
|
||||
cdef list cc = list()
|
||||
cdef list val = list()
|
||||
|
||||
cdef int dx = abs(x1 - x2)
|
||||
cdef int dy = abs(y1 - y2)
|
||||
cdef int err = dx - dy
|
||||
cdef int x, y, e, ed, sign_x, sign_y
|
||||
cdef int dx = abs(x0 - x1)
|
||||
cdef int dx_prime
|
||||
|
||||
if x1 < x2:
|
||||
cdef int dy = abs(y0 - y1)
|
||||
cdef float err = dx - dy
|
||||
cdef float err_prime
|
||||
|
||||
cdef int x, y, sign_x, sign_y
|
||||
cdef float ed
|
||||
|
||||
if x0 < x1:
|
||||
sign_x = 1
|
||||
else:
|
||||
sign_x = -1
|
||||
|
||||
if y1 < y2:
|
||||
if y0 < y1:
|
||||
sign_y = 1
|
||||
else:
|
||||
sign_y = -1
|
||||
@@ -183,30 +188,34 @@ def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2):
|
||||
if dx + dy == 0:
|
||||
ed = 1
|
||||
else:
|
||||
ed = <int>(sqrt(dx*dx + dy*dy))
|
||||
ed = sqrt(dx*dx + dy*dy)
|
||||
|
||||
x, y = x1, y1
|
||||
x, y = x0, y0
|
||||
while True:
|
||||
cc.append(x)
|
||||
rr.append(y)
|
||||
val.append(1. * fabs(err - dx + dy) / <float>(ed))
|
||||
e = err
|
||||
if 2 * e >= -dx:
|
||||
if x == x2:
|
||||
val.append(fabs(err - dx + dy) / ed)
|
||||
|
||||
err_prime = err
|
||||
x_prime = x
|
||||
|
||||
if (2 * err_prime) >= -dx:
|
||||
if x == x1:
|
||||
break
|
||||
if e + dy < ed:
|
||||
if (err_prime + dy) < ed:
|
||||
cc.append(x)
|
||||
rr.append(y + sign_y)
|
||||
val.append(1. * fabs(e + dy) / <float>(ed))
|
||||
val.append(fabs(err_prime + dy) / ed)
|
||||
err -= dy
|
||||
x += sign_x
|
||||
if 2 * e <= dy:
|
||||
if y == y2:
|
||||
|
||||
if 2 * err_prime <= dy:
|
||||
if y == y1:
|
||||
break
|
||||
if dx - e < ed:
|
||||
cc.append(x)
|
||||
if (dx - err_prime) < ed:
|
||||
cc.append(x_prime + sign_x)
|
||||
rr.append(y)
|
||||
val.append(fabs(dx - e) / <float>(ed))
|
||||
val.append(fabs(dx - err_prime) / ed)
|
||||
err += dx
|
||||
y += sign_y
|
||||
|
||||
|
||||
@@ -104,6 +104,21 @@ def test_line_aa_diagonal():
|
||||
for x, y in zip(r, c):
|
||||
assert_equal(img[r, c], 1)
|
||||
|
||||
def test_line_equal_aliasing_horizontally_vertically():
|
||||
img0 = np.zeros((25, 25))
|
||||
img1 = np.zeros((25, 25))
|
||||
|
||||
# Near-horizontal line
|
||||
rr, cc, val = line_aa(10, 2, 12, 20)
|
||||
img0[rr, cc] = val
|
||||
|
||||
# Near-vertical (transpose of prior)
|
||||
rr, cc, val = line_aa(2, 10, 20, 12)
|
||||
img1[rr, cc] = val
|
||||
|
||||
# Difference - should be zero
|
||||
assert_array_equal(img0, img1.T)
|
||||
|
||||
|
||||
def test_polygon_rectangle():
|
||||
img = np.zeros((10, 10), 'uint8')
|
||||
|
||||
Reference in New Issue
Block a user