Skip to content

Instantly share code, notes, and snippets.

@noio
Created March 6, 2015 19:59
Show Gist options
  • Save noio/61520ffaf56daf9fb272 to your computer and use it in GitHub Desktop.
Save noio/61520ffaf56daf9fb272 to your computer and use it in GitHub Desktop.
Cut Fragments from Sprite
#!/usr/bin/env python
import sys, os
import numpy as np
from matplotlib import cm
from scipy import ndimage, misc, spatial
OKGREEN = '\033[92m'
WARNING = '\033[93m'
ENDC = '\033[0m'
BOLD = '\033[1m'
filename = sys.argv[1]
fileroot = os.path.splitext(filename)[0]
image = misc.imread(filename)
if len(sys.argv) > 2:
hx = sys.argv[2]
channels = [hx[0:2], hx[2:4], hx[4:6], "FF"]
crack_color = [int(c, 16) for c in channels]
else:
crack_color = image[0,0]
print "Cracks with color: %s" % (crack_color)
cracks = np.all(image == crack_color, axis=-1)
transparent = image[:,:,3] == 0
regions = 1 - np.logical_or(cracks, transparent)
labels, num_labels = ndimage.label(regions)
# Structuring element that expands to bottom right
# when used for dilation
strel = np.array([[0,0,0],
[0,1,1],
[1,1,1]])
# We're going to assign all the cracks to the closest region
# in a way so that each crack pixel belongs to exactly one region
# Create a list of coordinates
positions = np.indices(labels.shape).transpose([1,2,0])
# Filter that list by the pixels that belong to a region
positions = positions[labels > 0]
# A KDTree is super overkill but it does save on some code here.
# Feed the KDTree the coordinates of all non-zero label positions
kdtree = spatial.KDTree(positions)
# Get positions of crack pixels
crack_positions = np.transpose(np.nonzero(cracks))
# Offset the cracks a tiny bit to bias the cracks to stick to
# the closest pixel on the top-left
crack_positions_offset = crack_positions.astype(float) + [[-0.1, -0.4]]
dists, idxs = kdtree.query(crack_positions_offset)
closest_region_position = positions[idxs]
closest_region_label = labels[closest_region_position[:,0], closest_region_position[:,1]]
# Assign the regions to the label matrix
labels[ crack_positions[:,0], crack_positions[:,1] ] = closest_region_label
# Save image that are transparent except for the region
for label in range(1,num_labels+1):
to_delete = (labels != label)
isolated = np.copy(image)
# Set all other pixels to transparent
isolated[to_delete] = [0,0,0,0]
# Compute a centroid
cy, cx = np.average(np.transpose(np.nonzero(labels == label)), axis=0).astype(int)
cy = round(cy / 4) * 4
cx = round(cx / 4) * 4
# Save the image using the centroid as name
# We do this so that the names of unaffected pieces
# stay the same if other pieces are merged or split
savepath = '%s_s%03d_%03d.png' % (fileroot, cx, cy)
if os.path.exists(savepath):
status = WARNING + BOLD + "Overwriting" + ENDC
else:
status = OKGREEN + "New" + ENDC
print "[%d/%d] %s %s" % (label, num_labels, status, os.path.basename(savepath))
misc.imsave(savepath, isolated)
# Save an image of the generated regions
colormap = cm.get_cmap("Set3")
colorlabels = colormap(labels / float(np.max(labels)))
colorlabels[:,:,-1] = image[:,:,-1] / 255.0
misc.imsave('%s_labels.png' % (fileroot), colorlabels)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment