Add option to configure folder
This commit is contained in:
parent
d9fd9255cc
commit
1c8c6a7991
2 changed files with 18 additions and 13 deletions
|
@ -4,4 +4,5 @@ Classifies images by their EXIF date (e.g. /path/YYYY.MM.DD/image.jpg).
|
||||||
|
|
||||||
= Install
|
= Install
|
||||||
|
|
||||||
|
apt install exiv2 cmake libexiv2-dev libboost-python-dev
|
||||||
python3 setup.py install
|
python3 setup.py install
|
||||||
|
|
|
@ -17,6 +17,7 @@ from logging.handlers import SysLogHandler
|
||||||
import face_recognition
|
import face_recognition
|
||||||
import pyexiv2
|
import pyexiv2
|
||||||
import PIL
|
import PIL
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class CustomFormatter(logging.Formatter):
|
class CustomFormatter(logging.Formatter):
|
||||||
|
@ -49,7 +50,7 @@ class CustomFormatter(logging.Formatter):
|
||||||
class image_classifier:
|
class image_classifier:
|
||||||
|
|
||||||
def __init__(self, debug_level, log_file, faces_directory, directory, no_move,
|
def __init__(self, debug_level, log_file, faces_directory, directory, no_move,
|
||||||
people_folder, recursive):
|
people_folder, recursive, folder_date_format):
|
||||||
''' Initial function called when object is created '''
|
''' Initial function called when object is created '''
|
||||||
self.debug_level = debug_level
|
self.debug_level = debug_level
|
||||||
if log_file is None:
|
if log_file is None:
|
||||||
|
@ -66,6 +67,7 @@ class image_classifier:
|
||||||
self.no_move = no_move
|
self.no_move = no_move
|
||||||
self.people_folder = people_folder
|
self.people_folder = people_folder
|
||||||
self.recursive = recursive
|
self.recursive = recursive
|
||||||
|
self.folder_date_format = folder_date_format
|
||||||
|
|
||||||
if self.recursive:
|
if self.recursive:
|
||||||
entries = self.recursive_scandir(directory)
|
entries = self.recursive_scandir(directory)
|
||||||
|
@ -122,32 +124,32 @@ class image_classifier:
|
||||||
if not os.access(file, os.R_OK):
|
if not os.access(file, os.R_OK):
|
||||||
self._log.error(f"The file '{file}' is not readable.")
|
self._log.error(f"The file '{file}' is not readable.")
|
||||||
else:
|
else:
|
||||||
file_date = "unknown-time"
|
|
||||||
if self.is_image(file):
|
if self.is_image(file):
|
||||||
if 'Exif.Photo.DateTimeOriginal' in self.metadata.exif_keys:
|
if 'Exif.Photo.DateTimeOriginal' in self.metadata.exif_keys:
|
||||||
original_date = self.metadata['Exif.Photo.DateTimeOriginal'].value
|
original_date = self.metadata['Exif.Photo.DateTimeOriginal'].value
|
||||||
self._log.debug(f"File creation time: {original_date} \
|
self._log.debug(f"File creation time in EXIF: {original_date} \
|
||||||
(type: {type(original_date)})")
|
(type: {type(original_date)})")
|
||||||
try:
|
try:
|
||||||
file_date = original_date.strftime('%Y.%m.%d')
|
#file_date = original_date.strftime('%Y/%Y.%m.%d')
|
||||||
|
file_date = original_date
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self._log.error(f"Failed to convert EXIF information about date '{original_date}'.")
|
self._log.error(f"Failed to convert EXIF information about date '{original_date}'.")
|
||||||
file_date = 'unknown-time'
|
file_date = None
|
||||||
if file_date == 'unknown-time':
|
if file_date is None:
|
||||||
self._log.debug('Date not stored in EXIF metadata')
|
self._log.debug('Date not stored in EXIF metadata')
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r'(?P<year>20[0-9]{2})[\-/\._]?(?P<month>[0-1]?[0-9])[\-/\._]?(?P<day>[0-3]?[0-9])',
|
r'(?P<year>20[0-9]{2})[\-/\._]?(?P<month>[0-1]?[0-9])[\-/\._]?(?P<day>[0-3]?[0-9])',
|
||||||
filename
|
filename
|
||||||
)
|
)
|
||||||
if match:
|
if match:
|
||||||
file_date = f"{match.group('year')}.{match.group('month')}.\
|
file_date = datetime.strptime(f"{match.group('year')}.{match.group('month')}.\
|
||||||
{match.group('day')}"
|
{match.group('day')}", '%Y.%m.%d')
|
||||||
else:
|
else:
|
||||||
match = re.search(r'(?P<day>[0-3]?[0-9])[\-/\._]?\
|
match = re.search(r'(?P<day>[0-3]?[0-9])[\-/\._]?\
|
||||||
(?P<month>[0-1]?[0-9])[\-/\._]?(?P<year>20[0-9]{2})', filename)
|
(?P<month>[0-1]?[0-9])[\-/\._]?(?P<year>20[0-9]{2})', filename)
|
||||||
if match:
|
if match:
|
||||||
file_date = f"{match.group('year')}.{match.group('month')}.\
|
file_date = datetime.strptime(f"{match.group('year')}.{match.group('month')}.\
|
||||||
{match.group('day')}"
|
{match.group('day')}", '%Y.%m.%d')
|
||||||
else:
|
else:
|
||||||
self._log.warning(f"Date not found in file's name '{filename}'.")
|
self._log.warning(f"Date not found in file's name '{filename}'.")
|
||||||
else:
|
else:
|
||||||
|
@ -166,7 +168,8 @@ class image_classifier:
|
||||||
people = list()
|
people = list()
|
||||||
if self.is_image(file):
|
if self.is_image(file):
|
||||||
self.process_metadata(file)
|
self.process_metadata(file)
|
||||||
folder_date = self.get_file_date(file)
|
folder_date_time = self.get_file_date(file)
|
||||||
|
folder_date = folder_date_time.strftime(self.folder_date_format)
|
||||||
if folder_date:
|
if folder_date:
|
||||||
if self.is_image(file):
|
if self.is_image(file):
|
||||||
people = self.find_faces(file)
|
people = self.find_faces(file)
|
||||||
|
@ -340,11 +343,12 @@ identify people. Filename would be used as the name for the person. Just one per
|
||||||
pictures to each person's folder. Be sure to have deduplication in the filesystem to avoid using \
|
pictures to each person's folder. Be sure to have deduplication in the filesystem to avoid using \
|
||||||
too much storage.")
|
too much storage.")
|
||||||
@click.option('--recursive', '-r', is_flag=True, help='Recursively search for files in the provided --directory')
|
@click.option('--recursive', '-r', is_flag=True, help='Recursively search for files in the provided --directory')
|
||||||
|
@click.option('--folder-date-format', '-F', default='%Y/%Y.%m.%d', help='Format for the folder with the file date according to https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior')
|
||||||
@click_config_file.configuration_option()
|
@click_config_file.configuration_option()
|
||||||
def __main__(debug_level, log_file, faces_directory, directory, no_move,
|
def __main__(debug_level, log_file, faces_directory, directory, no_move,
|
||||||
people_folder, recursive):
|
people_folder, recursive, folder_date_format):
|
||||||
return image_classifier(debug_level, log_file, faces_directory, directory, no_move,
|
return image_classifier(debug_level, log_file, faces_directory, directory, no_move,
|
||||||
people_folder, recursive)
|
people_folder, recursive, folder_date_format)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue