Skip to content

Instantly share code, notes, and snippets.

@msgtn
Created July 17, 2023 02:36
Show Gist options
  • Save msgtn/bb9f1f2d206345335cf083706f84f79c to your computer and use it in GitHub Desktop.
Save msgtn/bb9f1f2d206345335cf083706f84f79c to your computer and use it in GitHub Desktop.
Raw code for generating 'I am me' matted image montage
#%%
# import cv
from PIL import Image, ImageOps, ImageChops, ImageDraw, ImageFont
import glob
import numpy as np
import moviepy
from moviepy import *
from moviepy.editor import *
import cv2 as cv
import random
# from moviepy import concatenate_videoclips
#%%
cascPath = "haarcascade_frontalface_default.xml"
# Create the haar cascade
faceCascade = cv.CascadeClassifier(cascPath)
#%%
base_fn = 'FXV10688.JPG'
base = Image.open('red_bg.JPG')
base_black = Image.open('red_black.jpg')
base_shape = base.size
base_size = np.array(base_shape)
base_shape = np.array([base_shape[1]*4//5,base_shape[1]])
base_crop = list((base_size-base_shape)//2) + list((base_size+base_shape)//2)
base = base.crop(base_crop)
base_black = base_black.crop(base_crop)
frames = glob.glob('../bwbd2/*')
frames = frames[:len(frames)//2]
random.shuffle(frames)
# %%
inv_base = ImageOps.grayscale(ImageOps.invert(base))
bw_base = Image.fromarray(np.array(inv_base)<=5)
bw_base = np.array(bw_base.convert('RGB'))[:,:,::-1].copy()
bw_base = cv.GaussianBlur(bw_base,tuple([9]*2),0)
bw_base = ImageOps.grayscale(Image.fromarray(bw_base))
inv_base = Image.fromarray(np.array(inv_base)>5)
inv_np = np.array(inv_base.convert('RGB'))[:,:,::-1].copy()
inv_base = cv.GaussianBlur(inv_np,tuple([9]*2),0)
inv_base = ImageOps.grayscale(Image.fromarray(inv_base))
#%%
cmp_base = []
canny_base = cv.imread(base_fn)
canny_base = canny_base[base_crop[1]:base_crop[3],base_crop[0]:base_crop[2]]
canny_base = cv.GaussianBlur(canny_base,tuple([9]*2),0)
# canny_base = cv.GaussianBlur(canny_base,(3,3),0)
# canny_base = cv.Sobel(canny_base, ddepth=cv.CV_8U, dx=1, dy=1, ksize=5)
canny_base = cv.Canny(canny_base,50,70) # not bad
canny_base = cv.GaussianBlur(canny_base,tuple([7]*2),0)
canny_base = ImageOps.invert(Image.fromarray(canny_base))
canny_base = np.array(canny_base)
canny_base = -(np.expand_dims(canny_base,axis=-1).repeat(3,axis=-1)-255)
canny_base = Image.fromarray(canny_base)
# canny_base.show()
font_size = 0.07
img_size = base.size
img_font = ImageFont.truetype('Roboto-Regular.ttf', int(img_size[1]*font_size),)
img_text = "I am me."
text_size = img_font.getsize(img_text)
frames.insert(0,frames.pop(frames.index('../bwbd2/FXF12079.jpg')))
# frames.append(frames.pop(frames.index('../bwbd2/FXV11138.jpg')))
for f,frame in enumerate(frames):
if f%5!=0:continue
# for f,frame in enumerate(frames[:30]):
if f%50==0: print(f)
f_img = Image.open(frame)
f_shape = f_img.size
f_img = f_img.resize([base.size[0]]*2)
f_img = ImageOps.expand(f_img,border=(base.size[1]-base.size[0]))
f_shape = f_img.size
f_crop_x = [(f_shape[0]-base.size[0])//2, (f_shape[0]+base.size[0])//2]
f_img = f_img.crop([f_crop_x[0], 0, f_crop_x[1], base.size[1]])
if f>0:
f_img = ImageOps.grayscale(f_img)
f_img = np.expand_dims(np.array(f_img),axis=-1).repeat(3,axis=-1)
f_img = Image.fromarray(f_img)
f_base = Image.composite(base_black,f_img,inv_base)
f_base = ImageChops.subtract(f_base,canny_base)
f_text = ImageDraw.Draw(f_base)
sub_loc = img_size*np.array([.5,.85])
cmp_base.append(f_base)
from moviepy.video import VideoClip
fps = np.ceil(len(frames)/60)
# fps = 12
fps = 16
img_clips = [ImageClip(np.array(c),duration=1./fps) for c in cmp_base]
# %%
from moviepy.editor import concatenate_videoclips
mov = concatenate_videoclips(img_clips)
mov.write_videofile('./230425_boku_bw.mp4',fps=fps)
#
'''
ffmpeg -i 230425_boku_bw.mp4 \
-vf "scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
-loop 0 boku.gif
'''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment