updated README

This commit is contained in:
WALTERS
2019-08-19 07:30:00 -05:00
parent d32dd0c47d
commit 66a344d35a
6 changed files with 164 additions and 19 deletions

128
.gitignore vendored
View File

@@ -1,6 +1,132 @@
# Custom .gitignore stuff
package/key/
*.jpg
*.png
*.jpeg
*.nef
*.xmp
*.xmp
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/

9
README.md Normal file
View File

@@ -0,0 +1,9 @@
# photo-tagging
## What is this repository?
This repository is for a interesting project involving Google's Vision API and support for automatic photo tagging, with support for Adobe's XMP metadata and other file property based metadata.
## How does it work?
This application is built in Python and utilizes the `google-cloud` python module. Install using `pip install google-cloud`. A key should be provided by google in a `.json` file, insert this at `./package/key/photo_tagging_service.json`.

10
main.py
View File

@@ -3,5 +3,11 @@ from package import app
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]=os.path.join(sys.path[0], 'package', 'key', 'photo_tagging_service.json')
if __name__ == "__main__":
sys.exit(app.run())
# if __name__ == "__main__":
# sys.exit(app.run())
import exif
path = 'E:\\Photography\\Colorado 2019\\DSC_7960.jpg'
image = exif.Image(open(path, 'rb'))
print(image.artist)
print(dir(image))

View File

Binary file not shown.

View File

@@ -1,8 +1,8 @@
import io, sys, os, time, rawpy, imageio, progressbar
from google.cloud import vision
import io, sys, os, time, rawpy, imageio, progressbar, shutil, iptcinfo3
from google.cloud.vision import types
from google.cloud import vision
from package import xmp
from PIL import Image
from package.xmp import writeTags
# The name of the image file to annotate
input_path = os.path.join(sys.path[0], 'package', 'processing', 'input')
@@ -36,7 +36,7 @@ def process_file(file_name, xmp):
image.thumbnail(size, resample=Image.ANTIALIAS)
image.save(file_path, format='jpeg', optimize=True, quality=quality)
base = os.path.splitext(file_name)[0]
base, ext = os.path.splitext(file_name)
temp_file_path = os.path.join(temp_path, base + '.jpeg')
try:
@@ -64,11 +64,20 @@ def process_file(file_name, xmp):
response = client.label_detection(image=image)
labels = [label.description for label in response.label_annotations]
print('\tLabels: {}'.format(', '.join(labels)))
print('\tWriting {} tags to output folder...')
writeTags(os.path.join(input_path, xmp), os.path.join(output_path, xmp), labels)
print('\tMoving associated original image file...')
os.rename(os.path.join(input_path, file_name), os.path.join(output_path, file_name))
if ext == '.NEF':
print('\tWriting {} tags to output XMP...'.format(len(labels)))
xmp.writeXMP(os.path.join(input_path, xmp), os.path.join(output_path, xmp), labels)
else:
print('\tWriting {} tags to output {}'.format(len(labels), ext[1:].upper()))
info = iptcinfo3.IPTCInfo(os.path.join(input_path, xmp))
info['keywords'].extend(labels)
info.save()
# Remove the strange ghost file
os.remove(os.path.join(input_path, xmp) + '~')
print('\tMoving associated original image file...')
# Copy dry-run
shutil.copy2(os.path.join(input_path, file_name), os.path.join(output_path, file_name))
# os.rename(os.path.join(input_path, file_name), os.path.join(output_path, file_name))
except:
_cleanup()

View File

@@ -1,14 +1,13 @@
# from libxmp import file_to_dict
import os, sys, re
ext_filter = lambda file : file.endswith('.NEF')
mainPattern = r'<dc:subject>\n\s+<rdf:Bag>\n(?: <rdf:li>.+<\/rdf:li>\n)*\s+<\/rdf:Bag>\n\s+<\/dc:subject>\n'
subPattern = r'<rdf:li>(.*)</rdf:li>\n'
subFormatPattern = ' <rdf:li>{}</rdf:li>\n'
def writeTags(inputPath, outputPath, tags):
# Write tags to an XMP file, using regex patterns
def writeXMP(inputPath, outputPath, tags):
data = open(inputPath, 'r').read()
# Detect and find the <dc:Subject: part
match = re.search(mainPattern, data)
# If it's not found, we just add the tags area right below the creator tag
@@ -17,17 +16,13 @@ def writeTags(inputPath, outputPath, tags):
look = data.find('</dc:creator>') + 13
data = data[:look] + addition + data[look:]
match = re.search(mainPattern, data)
# Get last matching tag
submatch = None
for submatch in re.finditer(subPattern, match.group(0)):
pass
# Calculate very end
spanend = match.span()[0] + (submatch.span()[1] if submatch else 0)
# add tags to end
data = data[:spanend] + ''.join(subFormatPattern.format(tag) for tag in tags) + data[spanend:]
# Write file to disk
open(outputPath, 'w+').write( data)