Created
September 14, 2016 21:44
-
-
Save twidi/b4c6c83d5a12f29c2cf23a4704eab116 to your computer and use it in GitHub Desktop.
Timelapse preparation: remove the birds and planes from the sky
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
# Clean the sky: remove birds, planes... only work if each images are "close", and there is no cloud moving fast | |
# by @twidi | |
import glob, os, shutil, sys | |
from gimpfu import * | |
def run(source_dir='.', extension='JPG', threshold=30, mask=None, dest_dir=None): | |
""" | |
This script will try to remove objects from photos that are not present on the previous one | |
Parameters | |
---------- | |
source_dir: str | |
The directory where to load images from. Default to '.' | |
extension: str | |
The extension of image files to load. Default to 'JPG' | |
threshold: int | |
The value to use for the "back threshold". Default to 30 | |
mask: str | |
The full path of the mask to apply (the part of the image where we want to ignore the | |
differences). If falsy, no mask will be applied. Default to ``None``. | |
dest_dir: str | |
The directory where to save images, updated or not. If falsy, the images in | |
``source_dir`` will be replaced. Default to ``None``. | |
""" | |
if dest_dir: | |
if not os.path.exists(dest_dir): | |
os.makedirs(dest_dir) | |
else: | |
dest_dir = source_dir | |
mask_image = pdb.gimp_file_load(mask, mask) if mask else None | |
work_image = None | |
all_files = sorted(glob.iglob(os.path.join(source_dir, '*' + extension))) | |
for file_path in all_files: | |
sys.stdout.flush() | |
file_name = os.path.basename(file_path) | |
dest_path = os.path.normpath(os.path.join(dest_dir, file_name)) if dest_dir != source_dir else file_path | |
# we open the image | |
file_image = pdb.gimp_file_load(file_path, file_name) | |
if not work_image: | |
# first image in the dir: we simply keep it to be the reference image to start with | |
work_image = file_image | |
# and we copy it in the dest dir if different from source dir | |
if dest_dir != source_dir: | |
shutil.copy2(file_path, dest_path) | |
print('%s is first image, copied' % file_name) | |
else: | |
print('%s is first image' % file_name) | |
continue | |
# create a new layer from the new loaded image and get the difference | |
second_layer = pdb.gimp_layer_new_from_drawable(file_image.layers[0], work_image) | |
second_layer.mode = DIFFERENCE_MODE | |
work_image.add_layer(second_layer, 0) | |
# add the mask as a new layer | |
if mask_image: | |
third_layer = pdb.gimp_layer_new_from_drawable(mask_image.layers[0], work_image) | |
work_image.add_layer(third_layer, 0) | |
# combine all layers | |
work_image.flatten() | |
first_layer = work_image.layers[0] | |
# apply a threshold to display only real big differences | |
pdb.gimp_threshold(first_layer, threshold, 255) | |
# select all black | |
pdb.gimp_image_select_color(work_image, CHANNEL_OP_REPLACE, first_layer, (0, 0, 0, 0)) | |
# invert to get the non-black (gray and white) | |
pdb.gimp_selection_invert(work_image) | |
something_selected = not pdb.gimp_selection_is_empty(work_image) | |
if something_selected: | |
# we grow the selection a little | |
pdb.gimp_selection_grow(work_image, 5) | |
# we set back the image as main layer (to remove the content of the selection if any | |
# and as base image for the next image to be treated) | |
second_layer = pdb.gimp_layer_new_from_drawable(file_image.layers[0], work_image) | |
work_image.add_layer(second_layer, 0) | |
work_image.flatten() | |
# we delete it in gimp, we don't need it any more | |
pdb.gimp_image_delete(file_image) | |
if something_selected: | |
# magically remove the content of the selection (thanks resynthetize) | |
pdb.python_fu_heal_selection(work_image, work_image.active_layer, 50, 0, 0) # from all around, fill random | |
# and save it | |
pdb.gimp_file_save(work_image, work_image.active_layer, dest_path, file_name) | |
print('%s updated' % file_name) | |
# cancel all selection for the next image to be treated | |
pdb.gimp_selection_none(work_image) | |
else: | |
# don't need to update the image, we just copy it if different dest_dir | |
if dest_dir != source_dir: | |
shutil.copy2(file_path, dest_path) | |
print('%s not updated, copied' % file_name) | |
else: | |
print('%s not updated' % file_name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment