Skip to content

Instantly share code, notes, and snippets.

@twidi
Created September 14, 2016 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save twidi/b4c6c83d5a12f29c2cf23a4704eab116 to your computer and use it in GitHub Desktop.
Save twidi/b4c6c83d5a12f29c2cf23a4704eab116 to your computer and use it in GitHub Desktop.
Timelapse preparation: remove the birds and planes from the sky
# 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