Merge pull request #457 from tonysyu/logo_refactor

RF: Refactor code that generates scikit-image logo.
This commit is contained in:
Stefan van der Walt
2013-03-07 10:02:08 -08:00
2 changed files with 81 additions and 145 deletions
+75 -135
View File
@@ -1,17 +1,26 @@
"""
Script to draw skimage logo using Scipy logo as stencil. The easiest
starting point is the `plot_colorized_logo`; the "if-main" demonstrates its use.
starting point is the `plot_colorized_logo`.
Original snake image from pixabay [1]_
.. [1] http://pixabay.com/en/snake-green-toxic-close-yellow-3237/
"""
import numpy as np
import sys
if len(sys.argv) != 2 or sys.argv[1] != '--no-plot':
print "Run with '--no-plot' flag to generate logo silently."
else:
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
import scipy.misc
import numpy as np
import skimage.io as sio
import skimage.filter as imfilt
from skimage import img_as_float
from skimage.color import gray2rgb, rgb2gray
from skimage.exposure import rescale_intensity
from skimage.filter import sobel
import scipy_logo
@@ -19,42 +28,21 @@ import scipy_logo
# Utility functions
# =================
def get_edges(img):
edge = np.empty(img.shape)
if len(img.shape) == 3:
for i in range(3):
edge[:, :, i] = imfilt.sobel(img[:, :, i])
else:
edge = imfilt.sobel(img)
edge = rescale_intensity(edge)
return edge
def colorize(image, color, whiten=False):
"""Return colorized image from gray scale image.
def rescale_intensity(img):
i_range = float(img.max() - img.min())
img = (img - img.min()) / i_range * 255
return np.uint8(img)
def colorize(img, color, whiten=False):
"""Return colorized image from gray scale image
Parameters
----------
img : N x M array
grayscale image
color : length-3 sequence of floats
RGB color spec. Float values should be between 0 and 1.
whiten : bool
If True, a color value less than 1 increases the image intensity.
The colorized image has values from ranging between black at the lowest
intensity to `color` at the highest. If `whiten=True`, then the color
ranges from `color` to white.
"""
color = np.asarray(color)[np.newaxis, np.newaxis, :]
img = img[:, :, np.newaxis]
image = image[:, :, np.newaxis]
if whiten:
# truncate and stretch intensity range to enhance contrast
img = np.clip(img, 80, 255)
img = rescale_intensity(img)
return np.uint8(color * (255 - img) + img)
image = rescale_intensity(image, in_range=(0.3, 1))
return color * (1 - image) + image
else:
return np.uint8(img * color)
return image * color
def prepare_axes(ax):
@@ -65,16 +53,6 @@ def prepare_axes(ax):
spine.set_visible(False)
_rgb_stack = np.ones((1, 1, 3), dtype=bool)
def gray2rgb(arr):
"""Return RGB image from a grayscale image.
Expand h x w image to h x w x 3 image where color channels are simply copies
of the grayscale image.
"""
return arr[:, :, np.newaxis] * _rgb_stack
# Logo generating classes
# =======================
@@ -82,21 +60,17 @@ class LogoBase(object):
def __init__(self):
self.logo = scipy_logo.ScipyLogo(radius=self.radius)
self.mask_1 = self.logo.get_mask(self.img.shape, 'upper left')
self.mask_2 = self.logo.get_mask(self.img.shape, 'lower right')
self.edges = get_edges(self.img)
self.mask_1 = self.logo.get_mask(self.image.shape, 'upper left')
self.mask_2 = self.logo.get_mask(self.image.shape, 'lower right')
edges = np.array([sobel(img) for img in self.image.T]).T
# truncate and stretch intensity range to enhance contrast
self.edges = np.clip(self.edges, 0, 100)
self.edges = rescale_intensity(self.edges)
self.edges = rescale_intensity(edges, in_range=(0, 0.4))
def _crop_image(self, img):
def _crop_image(self, image):
w = 2 * self.radius
x, y = self.origin
return img[y:y+w, x:x+w]
def get_canvas(self):
return 255 * np.ones(self.img.shape, dtype=np.uint8)
return image[y:y + w, x:x + w]
def plot_curve(self, **kwargs):
self.logo.plot_snake_curve(**kwargs)
@@ -104,15 +78,13 @@ class LogoBase(object):
class SnakeLogo(LogoBase):
def __init__(self):
self.radius = 250
self.origin = (420, 0)
img = sio.imread('data/snake_pixabay.jpg')
img = self._crop_image(img)
radius = 250
origin = (420, 0)
img = img.astype(float) * 1.1
img[img > 255] = 255
self.img = img.astype(np.uint8)
def __init__(self):
image = sio.imread('data/snake_pixabay.jpg')
image = self._crop_image(image)
self.image = img_as_float(image)
LogoBase.__init__(self)
@@ -120,107 +92,75 @@ class SnakeLogo(LogoBase):
snake_color = SnakeLogo()
snake = SnakeLogo()
# turn RGB image into gray image
snake.img = np.mean(snake.img, axis=2)
snake.edges = np.mean(snake.edges, axis=2)
snake.image = rgb2gray(snake.image)
snake.edges = rgb2gray(snake.edges)
# Demo plotting functions
# =======================
def plot_colorized_logo(logo, color, edges='light', switch=False, whiten=False):
"""Convenience function to plot artificially colored logo.
def plot_colorized_logo(logo, color, edges='light', whiten=False):
"""Convenience function to plot artificially-colored logo.
The upper-left half of the logo is an edge filtered image, while the
lower-right half is unfiltered.
Parameters
----------
logo : subclass of LogoBase
color : length-3 sequence of floats
logo : LogoBase instance
color : length-3 sequence of floats or 2 length-3 sequences
RGB color spec. Float values should be between 0 and 1.
edges : {'light'|'dark'}
Specifies whether Sobel edges are drawn light or dark
switch : bool
If False, the image is drawn on the southeast half of the Scipy curve
and the edge image is drawn on northwest half.
whiten : bool
whiten : bool or 2 bools
If True, a color value less than 1 increases the image intensity.
"""
if not hasattr(color[0], '__iter__'):
color = [color] * 2
color = [color] * 2 # use same color for upper-left & lower-right
if not hasattr(whiten, '__iter__'):
whiten = [whiten] * 2
img = gray2rgb(logo.get_canvas())
whiten = [whiten] * 2 # use same setting for upper-left & lower-right
image = gray2rgb(np.ones_like(logo.image))
mask_img = gray2rgb(logo.mask_2)
mask_edge = gray2rgb(logo.mask_1)
if switch:
mask_img, mask_edge = mask_edge, mask_img
# Compose image with colorized image and edge-image.
if edges == 'dark':
lg_edge = colorize(255 - logo.edges, color[0], whiten=whiten[0])
logo_edge = colorize(1 - logo.edges, color[0], whiten=whiten[0])
else:
lg_edge = colorize(logo.edges, color[0], whiten=whiten[0])
lg_img = colorize(logo.img, color[1], whiten=whiten[1])
img[mask_img] = lg_img[mask_img]
img[mask_edge] = lg_edge[mask_edge]
logo.plot_curve(lw=5, color='w')
plt.imshow(img)
logo_edge = colorize(logo.edges, color[0], whiten=whiten[0])
logo_img = colorize(logo.image, color[1], whiten=whiten[1])
image[mask_img] = logo_img[mask_img]
image[mask_edge] = logo_edge[mask_edge]
def red_light_edges(logo, **kwargs):
plot_colorized_logo(logo, (1, 0, 0), edges='light', **kwargs)
def red_dark_edges(logo, **kwargs):
plot_colorized_logo(logo, (1, 0, 0), edges='dark', **kwargs)
def blue_light_edges(logo, **kwargs):
plot_colorized_logo(logo, (0.35, 0.55, 0.85), edges='light', **kwargs)
def blue_dark_edges(logo, **kwargs):
plot_colorized_logo(logo, (0.35, 0.55, 0.85), edges='dark', **kwargs)
def green_orange_light_edges(logo, **kwargs):
colors = ((0.6, 0.8, 0.3), (1, 0.5, 0.1))
plot_colorized_logo(logo, colors, edges='light', **kwargs)
def green_orange_dark_edges(logo, **kwargs):
colors = ((0.6, 0.8, 0.3), (1, 0.5, 0.1))
plot_colorized_logo(logo, colors, edges='dark', **kwargs)
logo.plot_curve(lw=5, color='w') # plot snake curve on current axes
plt.imshow(image)
if __name__ == '__main__':
import sys
plot = False
if len(sys.argv) < 2 or sys.argv[1] != '--no-plot':
plot = True
print "Run with '--no-plot' flag to generate logo silently."
# Colors to use for the logo:
red = (1, 0, 0)
blue = (0.35, 0.55, 0.85)
green_orange = ((0.6, 0.8, 0.3), (1, 0.5, 0.1))
def plot_all():
plotters = (red_light_edges, red_dark_edges,
blue_light_edges, blue_dark_edges,
green_orange_light_edges, green_orange_dark_edges)
f, axes_array = plt.subplots(nrows=2, ncols=len(plotters))
for plot, ax_col in zip(plotters, axes_array.T):
prepare_axes(ax_col[0])
plot(snake)
prepare_axes(ax_col[1])
plot(snake, whiten=True)
color_list = [red, blue, green_orange]
edge_list = ['light', 'dark']
f, axes = plt.subplots(nrows=len(edge_list), ncols=len(color_list))
for axes_row, edges in zip(axes, edge_list):
for ax, color in zip(axes_row, color_list):
prepare_axes(ax)
plot_colorized_logo(snake, color, edges=edges)
plt.tight_layout()
def plot_snake():
def plot_official_logo():
f, ax = plt.subplots()
prepare_axes(ax)
green_orange_dark_edges(snake, whiten=(False, True))
plot_colorized_logo(snake, green_orange, edges='dark',
whiten=(False, True))
plt.savefig('green_orange_snake.png', bbox_inches='tight')
if plot:
plot_all()
plot_snake()
if plot:
plt.show()
plot_all()
plot_official_logo()
plt.show()
+6 -10
View File
@@ -3,10 +3,11 @@ Code used to trace Scipy logo.
"""
import numpy as np
import matplotlib.pyplot as plt
import skimage.io as imgio
from scipy.misc import lena
import matplotlib.nxutils as nx
from skimage import io
from skimage import data
class SymmetricAnchorPoint(object):
"""Anchor point in a parametric curve with symmetric handles
@@ -185,7 +186,7 @@ class ScipyLogo(object):
def plot_image(self, **kwargs):
ax = kwargs.pop('ax', plt.gca())
img = imgio.imread('data/scipy.png')
img = io.imread('data/scipy.png')
ax.imshow(img, **kwargs)
def get_mask(self, shape, region):
@@ -236,9 +237,7 @@ def plot_snake_overlay():
logo = ScipyLogo((670, 250), 250)
logo.plot_snake_curve()
logo.plot_circle()
img = imgio.imread('data/snake_pixabay.jpg')
#mask = logo.get_mask(img.shape, 'upper left')
#img[mask] = 255
img = io.imread('data/snake_pixabay.jpg')
plt.imshow(img)
@@ -247,9 +246,7 @@ def plot_lena_overlay():
logo = ScipyLogo((300, 300), 180)
logo.plot_snake_curve()
logo.plot_circle()
img = lena()
#mask = logo.get_mask(img.shape, 'upper left')
#img[mask] = 255
img = data.lena()
plt.imshow(img)
@@ -259,4 +256,3 @@ if __name__ == '__main__':
plot_lena_overlay()
plt.show()