Last active
March 29, 2017 19:20
-
-
Save Adjective-Object/8764ff1fc2839de0bd286d20ab89cb8a to your computer and use it in GitHub Desktop.
insert transparent images into other images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import Image, ImageCms | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import pylab | |
from scipy import signal, ndimage | |
import scipy | |
import os | |
import random | |
############## | |
# transforms # | |
############## | |
srgb_profile = ImageCms.createProfile("sRGB") | |
lab_profile = ImageCms.createProfile("LAB") | |
rgb2lab_transform = ImageCms.buildTransformFromOpenProfiles( | |
srgb_profile, lab_profile, "RGB", "LAB") | |
############## | |
# transforms # | |
############## | |
def center_spectrum(im): | |
h, w = im.shape[0], im.shape[1] | |
q1 = im[h/2:, :w/2] | |
q2 = im[h/2:, w/2:] | |
q3 = im[:h/2, :w/2] | |
q4 = im[:h/2, w/2:] | |
upper_half = pylab.hstack((q2, q1)) | |
lower_half = pylab.hstack((q4, q3)) | |
im = pylab.vstack((upper_half, lower_half)) | |
return im | |
def scale(arr, factor): | |
return scipy.misc.imresize( | |
arr, | |
(int(arr.shape[0] / factor), int(arr.shape[1]/ factor)), | |
interp="bilinear") / 255.0 | |
scale_factor = 8 | |
pad=4 | |
def overlay_image_coords(target, overlay): | |
target_arr = np.average(np.array(target), axis=2) / 255.0 | |
overlay_arr = np.array(overlay)[:,:,3] / 255.0 | |
print "edge detection" | |
blur_arr = ndimage.filters.gaussian_filter(target_arr, 2) | |
edges = blur_arr - target_arr | |
edges = - edges | |
edges -= edges.min() | |
edges = edges / edges.max() | |
print edges.max(), edges.min(), "<<" | |
# plt.imshow(edges) | |
# plt.show() | |
print "convolving edges with gaussian to provide border" | |
edges = edges - np.average(edges) | |
edges_gauss = ndimage.filters.gaussian_filter(edges, 20) | |
edges = np.maximum(edges, edges_gauss) | |
# plt.imshow(edges) | |
# plt.show() | |
print "convolving with overlay.." | |
edges = scale(edges, scale_factor) | |
overlay_arr = scale(overlay_arr, scale_factor) | |
unpadded_shape = overlay_arr.shape | |
overlay_arr = np.pad(overlay_arr, [[pad, pad], [pad, pad]], 'constant', constant_values=0) | |
print "lowres edges:", edges.shape | |
print "lowres overlay:", overlay_arr.shape | |
# plt.imshow(edges) | |
# plt.show() | |
print "convolving overlay with gaussian to provide border" | |
overlay_gauss = ndimage.filters.gaussian_filter(overlay_arr, 5) | |
overlay_arr = np.maximum(overlay_arr, overlay_gauss) | |
# plt.imshow(overlay_arr) | |
# plt.show() | |
print "convolving overlay with edge image" | |
overlaps = signal.convolve2d(edges, overlay_arr, boundary="fill", fillvalue=np.min(edges)) | |
print "edges:", edges.shape | |
print "overlay:", overlay_arr.shape | |
print "image:", target.size | |
print "overlaps:", overlaps.shape | |
print "overlaps:", overlaps.shape[0] * scale_factor, overlaps.shape[1] * scale_factor | |
# plt.imshow(overlaps) | |
# plt.show() | |
print "cropping" | |
# prevent anime grills from being placed out of image | |
overlaps = overlaps[ | |
int(overlay_arr.shape[0] * 1) : int(-overlay_arr.shape[0] * 1), | |
int(overlay_arr.shape[1] * 1) : int(-overlay_arr.shape[1] * 1), | |
] | |
print "overlaps:", overlaps.shape | |
print "overlaps:", overlaps.shape[0] * scale_factor, overlaps.shape[1] * scale_factor | |
# plt.imshow(overlaps) | |
# plt.show() | |
flat_index = np.argmin(overlaps) | |
coords = np.unravel_index(flat_index, overlaps.shape) | |
cx = int(float(coords[1] + overlay_arr.shape[1]/2 + pad) / edges.shape[1] * target.size[0]) | |
cy = int(float(coords[0] + overlay_arr.shape[0]/2 + pad) / edges.shape[0] * target.size[1]) | |
overlay_arr = scale(overlay_arr, 1.0/scale_factor) | |
overlay_arr = np.repeat( | |
np.reshape(overlay_arr, (overlay_arr.shape[0], overlay_arr.shape[1], 1)), | |
3, | |
axis=2) | |
x = (overlay_arr * 255).astype(np.uint8) | |
print x.shape, x.dtype | |
img = Image.fromarray(x) | |
return (cx, cy), img | |
assetpath = os.path.join( | |
os.getcwd(), | |
"smug" | |
) | |
imgs = [ | |
os.path.join(assetpath, p) | |
for p in os.listdir(assetpath) | |
] | |
def maybe_resize(screenshot, smug): | |
ratio = max( | |
(smug.size[0] + pad * scale_factor * 2.0) / screenshot.size[0], | |
(smug.size[1] + pad * scale_factor * 2.0) / screenshot.size[1], | |
) | |
if (ratio > 0.5): | |
print "downscaling smugness to fit on page", screenshot.size | |
newsize = ( | |
0.5 / ratio *smug.size[0], | |
0.5 / ratio *smug.size[1] | |
) | |
smug.thumbnail(newsize, Image.ANTIALIAS) | |
print "resulting smugness is ", smug.size | |
return smug | |
def main(): | |
screenshot = Image.open("screenshot.png") | |
smugpath = random.choice(imgs) | |
print smugpath | |
smug = Image.open(smugpath) | |
# ensure overlay smaller than image | |
smug = maybe_resize(screenshot, smug) | |
coords, img = overlay_image_coords(screenshot, smug) | |
print "found coords", coords | |
# screenshot.paste(img, (coords[0] - pad * scale_factor, coords[1] - pad * scale_factor)) | |
coords = ( | |
coords[0] - img.size[0] / 2, | |
coords[1] - img.size[1] / 2 | |
) | |
screenshot.paste(smug, coords, smug) | |
print "writing out.png" | |
screenshot.save("out.png") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment