diff options
| author | Aaron LI <aaronly.me@outlook.com> | 2016-10-15 21:40:30 +0800 | 
|---|---|---|
| committer | Aaron LI <aaronly.me@outlook.com> | 2016-10-15 21:40:30 +0800 | 
| commit | 7b82cbb2e810593e2ae6cac5c12a4653609f8a40 (patch) | |
| tree | 4c77b0910ce68a69115cde3ebbb28b6876e840d7 /fg21sim/utils/draw.py | |
| parent | 514445d62661cb89a89999d23c76519e5f6a608c (diff) | |
| download | fg21sim-7b82cbb2e810593e2ae6cac5c12a4653609f8a40.tar.bz2 | |
Add utils/draw.py: draw circles and ellipses
These functions will be used to draw the image of a SNR or a radio halo.
These functions are copied from the `scikit-image` project.
Thanks!
scikit-image: http://scikit-image.org/docs/dev/api/skimage.draw.html
Diffstat (limited to 'fg21sim/utils/draw.py')
| -rw-r--r-- | fg21sim/utils/draw.py | 128 | 
1 files changed, 128 insertions, 0 deletions
| diff --git a/fg21sim/utils/draw.py b/fg21sim/utils/draw.py new file mode 100644 index 0000000..02f3903 --- /dev/null +++ b/fg21sim/utils/draw.py @@ -0,0 +1,128 @@ +# Copyright (c) 2016 Weitian LI <liweitianux@live.com> +# MIT license + +""" +Generic drawers (i.e., painters) that draw some commonly used shapes. + +Credits: +- scikit-image: draw +  http://scikit-image.org/docs/dev/api/skimage.draw.html +  https://github.com/scikit-image/scikit-image/blob/master/skimage/draw/draw.py +""" + + +import numpy as np + + +def _ellipse_in_shape(shape, center, radii): +    """Generate coordinates of points within the ellipse bounded by shape.""" +    r_lim, c_lim = np.ogrid[0:float(shape[0]), 0:float(shape[1])] +    r_o, c_o = center +    r_r, c_r = radii +    distances = ((r_lim - r_o) / r_r)**2 + ((c_lim - c_o) / c_r)**2 +    return np.nonzero(distances < 1.0) + + +def ellipse(r, c, r_radius, c_radius, shape=None): +    """Generate coordinates of pixels within the ellipse. + +    Parameters +    ---------- +    r, c : float +        Center coordinate of the ellipse. +    r_radius, c_radius : float +        Minor and major semi-axes. ``(r/r_radius)**2 + (c/c_radius)**2 = 1``. +    shape : tuple, optional +        Image shape which is used to determine the maximum extent of output +        pixel coordinates.  This is useful for ellipses that exceed the image +        size.  If None, the full extent of the ellipse is used. + +    Returns +    ------- +    rr, cc : integer `~numpy.ndarray` +        Pixel coordinates of the ellipse. +        May be used to directly index into an array, e.g. +        ``img[rr, cc] = 1``. + +    Examples +    -------- +    >>> from fg21sim.utils.draw import ellipse +    >>> img = np.zeros((10, 10), dtype=np.uint8) +    >>> rr, cc = ellipse(5, 5, 3, 4) +    >>> img[rr, cc] = 1 +    >>> img +    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]], dtype=uint8) +    """ +    center = np.array([r, c]) +    radii = np.array([r_radius, c_radius]) + +    # The upper_left and lower_right corners of the +    # smallest rectangle containing the ellipse. +    upper_left = np.ceil(center - radii).astype(int) +    lower_right = np.floor(center + radii).astype(int) + +    if shape is not None: +        # Constrain upper_left and lower_right by shape boundary. +        upper_left = np.maximum(upper_left, np.array([0, 0])) +        lower_right = np.minimum(lower_right, np.array(shape[:2]) - 1) + +    shifted_center = center - upper_left +    bounding_shape = lower_right - upper_left + 1 + +    rr, cc = _ellipse_in_shape(bounding_shape, shifted_center, radii) +    rr.flags.writeable = True +    cc.flags.writeable = True +    rr += upper_left[0] +    cc += upper_left[1] +    return rr, cc + + +def circle(r, c, radius, shape=None): +    """Generate coordinates of pixels within the circle. + +    Parameters +    ---------- +    r, c : float +        Center coordinate of the circle. +    radius : float +        Radius of the circle. +    shape : tuple, optional +        Image shape which is used to determine the maximum extent of output +        pixel coordinates.  This is useful for circles that exceed the image +        size.  If None, the full extent of the circle is used. + +    Returns +    ------- +    rr, cc : integer `~numpy.ndarray` +        Pixel coordinates of the circle. +        May be used to directly index into an array, e.g. +        ``img[rr, cc] = 1``. + +    Examples +    -------- +    >>> from fg21sim.utils.draw import circle +    >>> img = np.zeros((10, 10), dtype=np.uint8) +    >>> rr, cc = circle(4, 4, 5) +    >>> img[rr, cc] = 1 +    >>> img +    array([[0, 0, 1, 1, 1, 1, 1, 0, 0, 0], +           [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], +           [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], +           [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], +           [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], +           [1, 1, 1, 1, 1, 1, 1, 1, 1, 0], +           [1, 1, 1, 1, 1, 1, 1, 1, 1, 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]], dtype=uint8) +    """ +    return ellipse(r, c, radius, radius, shape) | 
