Last active
September 13, 2022 12:03
-
-
Save tdhooper/f9e24ded5eec5be8c2a953db9425db8e to your computer and use it in GitHub Desktop.
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 wand.image import Image, COMPOSITE_OPERATORS | |
from wand.drawing import Drawing | |
from wand.display import display | |
import sys | |
import os | |
import re | |
import glob | |
import pprint | |
start_frame = int(sys.argv[1]) | |
end_frame = int(sys.argv[2]) | |
overlap = int(sys.argv[3]) | |
keyframe_dirs_root = sys.argv[4] | |
frame_count = end_frame - start_frame | |
RE_NUMBER = r'(\d+)'; | |
''' | |
keyframes_and_frames = { | |
keyframe_index : { | |
frame_index : frame_path | |
} | |
} | |
''' | |
keyframes_and_frames = {} | |
for keyframe_dir in os.scandir(keyframe_dirs_root): | |
if not keyframe_dir.is_dir(): | |
continue | |
match = re.search(RE_NUMBER, keyframe_dir.name) | |
if not match: | |
continue | |
keyframe_index = int(match.group(0)) | |
keyframes_and_frames[keyframe_index] = {} | |
for image_path in glob.glob(os.path.join(keyframe_dir.path, "*.png")): | |
match = re.search(RE_NUMBER, os.path.basename(image_path)) | |
if not match: | |
continue | |
frame_index = int(match.group(0)) | |
keyframes_and_frames[keyframe_index][frame_index] = image_path | |
pp = pprint.PrettyPrinter(indent=4) | |
pp.pprint(keyframes_and_frames) | |
''' | |
example overlap of 3, start_frame of 3 end_frame of 8 | |
keyframe : frames | |
_ | |
3: 0 1 2 3 4 5 6 | |
_ | |
5: 2 3 4 5 6 7 8 | |
_ | |
7: 4 5 6 7 8 9 10 | |
''' | |
def unlerp(min, max, value): | |
return (value - min) / (max - min) | |
def smoothstep(edge0, edge1, x): | |
if x < edge0: | |
return 0 | |
if x >= edge1: | |
return 1 | |
x = (x - edge0) / (edge1 - edge0) | |
return x * x * (3 - 2 * x) | |
''' | |
frame_composition = [ | |
[ | |
(path, weight), | |
... | |
], | |
... | |
] | |
''' | |
frame_compositions = [] | |
for frame_index in range(start_frame, end_frame): | |
keyframes = sorted(keyframes_and_frames.keys()) | |
first_keyframe = next(i for i in reversed(keyframes) if i <= frame_index) | |
overlapping_keyframe_indicies = [ | |
i for i in range(first_keyframe, frame_index + overlap) | |
if i in keyframes | |
] | |
composition = [] | |
print(frame_index) | |
for keyframe in overlapping_keyframe_indicies: | |
if keyframe not in keyframes_and_frames: | |
continue | |
images = keyframes_and_frames[keyframe] | |
if frame_index not in images: | |
continue | |
#weight = smoothstep(keyframe - overlap, keyframe, frame_index) | |
weight = unlerp(keyframe - overlap, keyframe, frame_index) | |
weight = min(weight, 1.0) | |
composition.append((images[frame_index], weight)) | |
print(" - {} ({})".format(keyframe, weight)) | |
frame_compositions.append(composition) | |
#pp = pprint.PrettyPrinter(indent=4) | |
#pp.pprint(frame_compositions) | |
for i, composition in enumerate(frame_compositions): | |
with Image(filename=composition[0][0]) as base_img: | |
for (path, weight) in composition[1:]: | |
with Image(filename=path) as img: | |
base_img.composite(image=img, left=0, top=0, operator='blend', arguments='{}%'.format(weight*100)) | |
base_img.save(filename="output/out_{}.png".format(str(i).zfill(len(str(frame_count))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment