-- Adam Hughes
-- 2/27/14
-- The George Washington University
Our task is to generate some test data for SEM images that can be used to test segmentation algorithm performance.
Configure notebook style (see NBCONFIG.ipynb), add imports and paths. The %run magic used below requires IPython 2.0 or higher.
%run NBCONFIG.ipynb
from pyparty import Grid
from pyparty.utils import any2rgb
Populating the interactive namespace from numpy and matplotlib
First, let's define several parameters to facilitate easy reuse:
RESOLUTION = (1024, 1024) #Image resolution
DIAM_SINGLE = 30 #Particle Diameter in Pixels
BGGRAY = 128 #Light gray background
PCOLOR = 255 #White particles
NOISE_DENSITY = 0.15 #Percent noise
c = Canvas(rez=RESOLUTION, background=BGGRAY)
c.grid.xdiv = c.grid.ydiv=25
for (cx, cy) in c.gpairs('centers'):
c.add('circle', radius=DIAM_SINGLE/2, center=(cx,cy), color=PCOLOR)
c.show(annotate=True);
Note: We use any2rgb() to RGB-convert the background so that plotting doesn't try to normalize the colors.
def warped(xx, yy, power=1.0):
""" 2d function to generate uneven contrasts """
return abs(np.cos(xx**power) + np.sin(yy**power))
g1 = Grid(style='h', rez=RESOLUTION)
gradientbg = g1.blend_bg(c.image, weight=0.35)
gradientbg = any2rgb(gradientbg)
g2 = Grid(rez=RESOLUTION)
g2.set_zfcn(warped)
warpedbg = g2.blend_bg(c.image, weight=0.25)
warpedbg = any2rgb(warpedbg)
axes = splot(1,3, figsize=(9,6))
IMAGES = [c.image, gradientbg, warpedbg]
for (idx, img) in enumerate(IMAGES):
showim(img, 'gray', axes[idx]);
WARNING:pyparty.tools.grids:3-channel image convert to 8-bit uint WARNING:pyparty.utils: color has been converted (1-channel to 3-channel RGB) WARNING:pyparty.tools.grids:3-channel image convert to 8-bit uint WARNING:pyparty.utils: color has been converted (1-channel to 3-channel RGB)
from pyparty.noise import salt, pepper, saltpepper, color, multicolor
axes = splot(1,3, figsize=(9,6))
for idx, img in enumerate(IMAGES):
noisyimg = salt(img, coverage=NOISE_DENSITY)
showim(noisyimg, 'gray', axes[idx])
Valid pyparty noise types are:
Where one color takes valid pyparty color (eg 'red', #0000FF, 230, (.5, .5, .5) ). Noise is always randomly distributed across the image. Multicolor noise is random 3-channel (r,g,b), where each channel is randomly chosen on 0-1 interval.
# Function that adds no noise: for plot 1
def nonoise(img, coverage): return img
noisefcns = (nonoise, salt, pepper, saltpepper, color, multicolor)
axes = splot(2,3, figsize=(9,6))
for idx, noisefcn in enumerate(noisefcns):
ax, title = axes[idx], noisefcn.__name__
showim(noisefcn(warpedbg, NOISE_DENSITY), ax, title=title);
Some of the code below is a bit messy, but basically it's a lot of hoopla to randomly sample particles of normally-distributed diameters, at random orientation and ranging from singles, dimers, trimers and clusters.
STD_DEV = 3 # pixels
PCOLOR = 200 #Single color
import random
from random import choice
COUNT = len(c.gpairs('centers'))
RAND_DIAM = np.random.normal(loc=DIAM_SINGLE,
scale=STD_DEV, size=2000)
def rint(x):
return int(round(x, 0))
def rran(samples=1):
""" Pick a random radius from distribution. """
out = [rint(choice(RAND_DIAM)/2.0) for i in range(samples)]
if len(out) == 1:
out = out[0]
return out
def rphi():
return rint(random.random() * 360.0)
def roverlap():
return 0 + (random.random() * .2 )
def populate_canvas(c):
for (cx, cy) in c.gpairs('centers'):
idx, pcolor = choice([(1, PCOLOR), (2, PCOLOR+15), (3, PCOLOR+35),(4, PCOLOR+55)])
shared = {'color':pcolor, 'center':(cx,cy),
'phi':rphi(), 'overlap':roverlap()}
if idx == 1:
c.add('circle', radius=rran(), **shared)
elif idx == 2:
c.add('dimer', *rran(2), **shared)
elif idx == 3:
c.add('trimer', *rran(3),**shared)
elif idx == 4:
c.add('tetramer', *rran(4), **shared)
c.clear_particles()
c.grid.xdiv = c.grid.ydiv = 20
populate_canvas(c)
c.show();
from pyparty import MultiCanvas
mc = MultiCanvas.from_canvas(c)
mc.set_names('singles', 'dimers', 'trimers', 'tetramers')
mc.set_colors('r', 'g', 'y', 'magenta')
mc
MultiCanvas (0x4da8050) 380: singles - Canvas (0x1cd60890) : 1024 X 1024 : 94 particles dimers - Canvas (0x9b25530) : 1024 X 1024 : 91 particles trimers - Canvas (0x12533ef0) : 1024 X 1024 : 80 particles tetramers - Canvas (0x12a90a10) : 1024 X 1024 : 115 particles
ax1, ax2 = splot(1,2)
mc.pie(ax1, autopct='both')
mc.hist(ax2, xlim='auto', bins=20);
clabeled = mc.to_canvas(mapcolors=True)
clabeled.background = 'black'
clabeled.show();