mirror of
https://codeberg.org/privacy1st/blur-exif-face-tags
synced 2024-12-23 01:16:04 +01:00
+ convert images in sub-directories
+ exiftool: if xmp sidecar exists, use it. Otherwise: use image file + skip already blurred images
This commit is contained in:
parent
b92a65c67f
commit
ce307c09d2
8
.idea/blur-exif-face-tags.iml
generated
Normal file
8
.idea/blur-exif-face-tags.iml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.9 (venv39-2)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@ -2,7 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/20210828_image-xml-metadata.iml" filepath="$PROJECT_DIR$/.idea/20210828_image-xml-metadata.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/blur-exif-face-tags.iml" filepath="$PROJECT_DIR$/.idea/blur-exif-face-tags.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -31,4 +31,4 @@ Many thanks to
|
||||
|
||||
* https://www.thregr.org/~wavexx/software/facedetect/#blurring-faces-within-an-image
|
||||
* "Make blur all around a rectangle in image with PIL", https://stackoverflow.com/q/56987112/6334421
|
||||
* Example image: https://unsplash.com/photos/1qfy-jDc_jo?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink
|
||||
* Example image: https://unsplash.com/photos/1qfy-jDc_jo?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink
|
||||
|
18
blur.py
18
blur.py
@ -12,7 +12,7 @@ import exif
|
||||
|
||||
class NormalizedRectangle:
|
||||
"""
|
||||
x, y, width and height are normalized: Their values are in the range [0, 1]
|
||||
x, y, width and height are normalized: Their values are in the range [0, 1].
|
||||
"""
|
||||
|
||||
x: float
|
||||
@ -82,5 +82,19 @@ def blur_rectangle2(image_src: Path, normalized_rectangles: List[NormalizedRecta
|
||||
|
||||
# Save image
|
||||
if image_dst is None:
|
||||
image_dst = image_src.parent.joinpath(f'{image_src.stem}_blurred{image_src.suffix}')
|
||||
image_dst = get_image_dst(image_src)
|
||||
im.save(image_dst)
|
||||
|
||||
|
||||
def get_image_dst(image: Path):
|
||||
return image.parent.joinpath(f'{image.stem}{stem_suffix()}{image.suffix}')
|
||||
|
||||
|
||||
def stem_suffix():
|
||||
"""
|
||||
Modified images will be saved with a different filename.
|
||||
This suffix will be added to their stem.
|
||||
"""
|
||||
|
||||
# return ' [blurred]'
|
||||
return '_blurred'
|
||||
|
32
exif.py
32
exif.py
@ -23,19 +23,12 @@ class Image:
|
||||
if len(self.files) == 0:
|
||||
raise Exception
|
||||
else:
|
||||
raise Exception
|
||||
raise Exception(f'{image_file}')
|
||||
|
||||
def get_image_file(self):
|
||||
return self.files[0]
|
||||
|
||||
def get_xmp_metadata(self) -> AnyStr:
|
||||
# TODO: Try to read xmp metadata from the image file itself, if there is no sidecar xmp file
|
||||
|
||||
xmp_sidecar = self.get_xmp_sidecar()
|
||||
with open(xmp_sidecar, "r") as f:
|
||||
return f.read()
|
||||
|
||||
def get_xmp_sidecar(self):
|
||||
def get_xmp_file(self):
|
||||
"""
|
||||
:return: The sidecar xmp file, if it exists. Otherwise None is returned.
|
||||
"""
|
||||
@ -46,6 +39,17 @@ class Image:
|
||||
return file
|
||||
return None
|
||||
|
||||
def get_metadata_file(self):
|
||||
"""
|
||||
If a sidecar xmp file exists, it is preferred over the image file itself.
|
||||
|
||||
:return: A file containing the image metadata.
|
||||
"""
|
||||
metadata = self.get_xmp_file()
|
||||
if metadata is None:
|
||||
metadata = self.get_image_file()
|
||||
return metadata
|
||||
|
||||
def __str__(self):
|
||||
return f'Image: {self.__dict__}'
|
||||
|
||||
@ -75,12 +79,12 @@ class ExifImageRegion:
|
||||
|
||||
|
||||
def get_exif_image_regions(image: Image) -> List[ExifImageRegion]:
|
||||
sidecar: Path = image.get_xmp_sidecar()
|
||||
img_metadata_file: Path = image.get_metadata_file()
|
||||
|
||||
names_str = exec.execute_save(['exiftool', '-RegionName', str(sidecar)])
|
||||
r_types_str = exec.execute_save(['exiftool', '-RegionType', str(sidecar)])
|
||||
area_units_str = exec.execute_save(['exiftool', '-RegionAreaUnit', str(sidecar)])
|
||||
rectangles_str = exec.execute_save(['exiftool', '-RegionRectangle', str(sidecar)])
|
||||
names_str = exec.execute_save(['exiftool', '-RegionName', str(img_metadata_file)])
|
||||
r_types_str = exec.execute_save(['exiftool', '-RegionType', str(img_metadata_file)])
|
||||
area_units_str = exec.execute_save(['exiftool', '-RegionAreaUnit', str(img_metadata_file)])
|
||||
rectangles_str = exec.execute_save(['exiftool', '-RegionRectangle', str(img_metadata_file)])
|
||||
|
||||
names = names_str.strip().split(':', 1)[1].strip().split(', ')
|
||||
r_types = r_types_str.strip().split(':', 1)[1].strip().split(', ')
|
||||
|
16
main.py
16
main.py
@ -1,3 +1,4 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@ -29,9 +30,18 @@ def blur_image(image: exif.Image):
|
||||
|
||||
|
||||
def main():
|
||||
for child in image_directory.iterdir():
|
||||
if child.suffix.lower() in image_extensions:
|
||||
blur_image(exif.Image(child))
|
||||
# Convert all images in the image_directory, including subdirectories.
|
||||
for _, _, files in os.walk(image_directory):
|
||||
for relative_file_str in files:
|
||||
file: Path = Path.joinpath(image_directory, relative_file_str)
|
||||
if file.suffix.lower() in image_extensions:
|
||||
|
||||
if file.stem.endswith(blur.stem_suffix()):
|
||||
print(f'Skipped the following image as it is already blurred:\n\t{file}')
|
||||
elif blur.get_image_dst(file).exists():
|
||||
print(f'Skipped the following image as it\'s blurred output does already exist:\n\t{file}')
|
||||
else:
|
||||
blur_image(exif.Image(file))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user