So I discovered another odd quirk that I actually think might be quite easy to address. It seems that your software has a bit of an issue when the face is super closeup but this can be easily fixed using something like PIL to pad the image borders with black pixels, run the swap and then remove the black pixels afterwards. This is what I was thinking. I was going to run some tests after work today and I will report back what I find.
Here is how I implement it in my version of your facedancer function. You need to import PIL and define the variable padding to your liking. I am going to experiment with what the optimal setting for this padding and check to make sure there aren't any negative side effects.
def pad_in():
target_files = os.listdir(temp_one)
for target_filename in target_files:
img_path = os.path.join(temp_one, target_filename)
img_output = os.path.join(temp_two, os.path.basename(img_path))
image = Image.open(img_path)
width, height = image.size
new_width = width + (2 * padding)
new_height = height + (2 * padding)
new_image = Image.new("RGB", (new_width, new_height), (0, 0, 0))
x = padding + (new_width - width) // 2
y = padding + (new_height - height) // 2
new_image.paste(image, (x, y))
new_image.save(img_output)
shuffle_up()
def pad_out():
target_files = os.listdir(temp_one)
for target_filename in target_files:
img_path = os.path.join(temp_one, target_filename)
img_output = os.path.join(temp_two, os.path.basename(img_path))
image = Image.open(img_path)
padded_width, padded_height = image.size
original_width = padded_width - (2 * padding)
original_height = padded_height - (2 * padding)
left = padding
top = padding
right = padded_width - padding
bottom = padded_height - padding
cropped_image = image.crop((left, top, right, bottom))
cropped_image.save(img_output)
def face_dancer():
global count_step, check_pause
if count_step == 3:
if input('Next Step: Swapping faces with FaceDancer...Continue (y/n): ') == 'y':
RetinaFace = load_model(opt.retina_path, compile=False,
custom_objects={'FPN': FPN,
'SSH': SSH,
'BboxHead': BboxHead,
'LandmarkHead': LandmarkHead,
'ClassHead': ClassHead})
ArcFace = load_model(opt.arcface_path, compile=False)
G = load_model(opt.facedancer_path, compile=False,
custom_objects={'AdaIN': AdaIN,
'AdaptiveAttention': AdaptiveAttention,
'InstanceNormalization': InstanceNormalization})
target_files = os.listdir(temp_one)
pad_in()
for target_filename in target_files:
img_path = os.path.join(temp_one, target_filename)
img_output = os.path.join(temp_two, os.path.basename(img_path))
run_inference(opt, swap_source, img_path,
RetinaFace, ArcFace, G, img_output)
pad_out()
if check_pause == 'true':
pause()
shuffle_up()
So I discovered another odd quirk that I actually think might be quite easy to address. It seems that your software has a bit of an issue when the face is super closeup but this can be easily fixed using something like PIL to pad the image borders with black pixels, run the swap and then remove the black pixels afterwards. This is what I was thinking. I was going to run some tests after work today and I will report back what I find.
Here is how I implement it in my version of your facedancer function. You need to import PIL and define the variable padding to your liking. I am going to experiment with what the optimal setting for this padding and check to make sure there aren't any negative side effects.