8 Commits
0.1 ... 0.2

Author SHA1 Message Date
04fad8d5b8 Added changelog for v0.2 2020-03-05 16:37:07 +01:00
5404ae6437 Finalized v0.2
Added copy function to be able to place files to outdir before modification.
Added verbose output about what it going to happen.
Added table header for output.
Removed obsolete "Processing..." message, as it was never visible.
2020-03-05 16:34:35 +01:00
0ad627fb0b Added examples with sample output to Readme.md 2020-03-05 16:31:04 +01:00
f46c8682ec Working output mechanism, honors users outdir choice.
If outdir is set, srcfile will be copied to outdir first and modified there.
2020-03-05 15:19:29 +01:00
ef6080d64c Restructured parts of the tool in preparation for new image output mechanism. 2020-03-05 13:36:01 +01:00
249acb6d85 Added changelog 2020-03-05 13:35:11 +01:00
b4c6448645 Directly create datetime object from tag.value, instead of ASCII export and datetime import. 2020-03-04 15:44:18 +01:00
6e8aaf3338 Started, to re-write using pyexiv2.
Can already read DateTimeOriginal :-)
2020-03-04 15:17:56 +01:00
3 changed files with 100 additions and 27 deletions

32
CHANGELOG.md Normal file
View File

@@ -0,0 +1,32 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.2] - 2020-02-05
### Added
- uses pyexiv2 instead of piexif which is also able to tag various camera raw formats, e. g. CR2
- added copy function to be able to place files to outdir before modification
- added verbose output about what it going to happen
- added table header for output
### Changed
- removed unnecessary datetime object creation as pyexiv2 can output datetime objects itself
- removed obsolete "Processing..." message, as it was never visible.
## [0.1] - 2020-02-02
First prototype using piexif
### Added
- argument parsing enabled
- parametrized factor to calculate Sieverts
- parametrized output dir
- usage of os.path to be os-aware
- output in a tablish manner
### Changed
- exchanged selfmade CSV parser by python's core CSV library

View File

@@ -11,7 +11,9 @@ It then creates a `UserComment` Exif tag with the actual measured radiation at t
## Dependencies
Right now it depends on the following non-core Python 3 libraries:
* [piexif](https://pypi.org/project/pyexif/): Python module for working with EXIF image data.
* [py3exiv2](https://pypi.org/project/py3exiv2/) A Python 3 binding to the library exiv2.
* [boost.python3](http://www.boost.org/libs/python/doc/index.html) Welcome to Boost.Python, a C++ library which enables seamless interoperability between C++ and the Python programming language.
* [exiv2](http://www.exiv2.org/) Exiv2 is a Cross-platform C++ library and a command line utility to manage image metadata.
## Requirements
* GeigerCounter log file in csv format as it is being exported by the software GeigerLog.
@@ -47,6 +49,29 @@ optional arguments:
Directory to output processed photos (default: .)
```
### Examples
Use test.hisdb.his from current working dir and modify (overwrite) all .CR2 files in place.
```
./exif_rad.py test.hisdb.his *.CR2
Modifying photos in place (overwrite)
filename date / time Exif UserComment
DSC_0196.JPG 2020-03-03 18:33:33 NOT FOUND!
DSC_0197.JPG 2020-03-03 20:14:18 Radiation ☢ 0.15 µS/h
DSC_0198.JPG 2020-03-03 22:18:13 Radiation ☢ 0.07 µS/h
```
Use test.hisdb.his in folder 'testdata', read all .JPG files from 'testsource' and write them to 'testdest'.
```
./exif_rad.py testdata/test.hisdb.his -o testdest/ testsource/*.JPG
Modifying photos in testdest/ (copy)
filename date / time Exif UserComment
DSC_0196.JPG 2020-03-03 18:33:33 NOT FOUND!
DSC_0197.JPG 2020-03-03 20:14:18 Radiation ☢ 0.15 µS/h
DSC_0198.JPG 2020-03-03 22:18:13 Radiation ☢ 0.07 µS/h
```
## GeigerLog setup
The Software is Open-Source and can be downloaded from [Sourceforge](https://sourceforge.net/projects/Geigerlog/).

View File

@@ -3,15 +3,15 @@
"""Iterates over a bunch of .jpg or .cr2 files and matches
DateTimeOriginal from Exif tag to DateTime in a csv log
of a GeigerMuellerCounter."""
of a GeigerMuellerCounter and writes its value to the UserComment
Exif tag in µS/h"""
from datetime import datetime
import os
import shutil
import csv
import argparse
from PIL import Image
import piexif
import piexif.helper
import pyexiv2
# SIFACTOR for GQ Geiger counters
@@ -38,42 +38,58 @@ parser.add_argument('-o', '--outdir', type=str, default='.',
args = parser.parse_args()
for photo in args.photos:
# Load Image and EXIF data
im = Image.open(photo)
exif_dict = piexif.load(im.info['exif'])
# Inform the user about what is going to happen
if args.outdir == ".":
print('Modifying photos in place (overwrite)')
else:
print('Modifying photos in', str(args.outdir), '(copy)')
# Print table header
print('{:<15} {:<20} {:<22}'.format('filename', 'date / time', 'Exif UserComment'))
for srcphoto in args.photos:
# Get image file name out of path
photo_basename = os.path.basename(photo)
photo_basename = os.path.basename(srcphoto)
# Decide whether to modify photo in place or to copy it to outdir first
# Then set the destination file as 'photo' to work on
if args.outdir == ".":
photo = srcphoto
else:
# be os aware and use the correct directory delimiter for destfile
dstphoto = os.path.join(args.outdir, photo_basename)
shutil.copy(srcphoto, dstphoto)
photo = dstphoto
# Load Exif data from image
metadata = pyexiv2.ImageMetadata(photo)
metadata.read()
tag = metadata['Exif.Photo.DateTimeOriginal']
# tag.value creates datetime object in pictime
pictime = tag.value
# Import GeigerCounter log
with open(args.csv, "r") as f:
csvreader = csv.reader(filter(lambda row: row[0] != '#', f),
delimiter=',', skipinitialspace=True)
picrawtime = exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal].decode('ASCII')
picisotime = datetime.strptime(picrawtime, "%Y:%m:%d %H:%M:%S")
print('Processing file:', photo_basename, end='\r')
for _, csvrawtime, csvrawcpm, _ in csvreader:
csvisotime = datetime.fromisoformat(csvrawtime)
# Process image if its timestamp is found in CSV log
if csvisotime == picisotime:
csvtime = datetime.fromisoformat(csvrawtime)
# Process image if its timestamp is found in CSV log (compares 2 datetime objects)
if csvtime == pictime:
rad = round(float(csvrawcpm) * args.sifactor, 2)
# convert str to exif compatible string
# Set key, value for new UserComment
key = 'Exif.Photo.UserComment'
new_comment = 'Radiation ☢ ' + str(rad) + ' µS/h'
user_comment = piexif.helper.UserComment.dump(new_comment, encoding="unicode")
exif_dict["Exif"][piexif.ExifIFD.UserComment] = user_comment
metadata[key] = pyexiv2.ExifTag(key, new_comment)
# compile and write tags
exif_bytes = piexif.dump(exif_dict)
# be os aware and use the correct directory delimiter
outfile = os.path.join(args.outdir, photo_basename)
im.save(outfile, exif=exif_bytes)
# print output
print('{:<30} {:<20} {:<22}'.format(photo_basename, str(picisotime), new_comment))
# print found radiation levels
print('{:<15} {:<20} {:<22}'.format(photo_basename, str(pictime), new_comment))
# Write Exif tags to file
metadata.write()
break
else:
print('{:<30} {:<20} {:<22}'.format(photo_basename, str(picisotime), 'NOT FOUND!'))
print('{:<15} {:<20} {:<22}'.format(photo_basename, str(pictime), 'NOT FOUND!'))
# close CSV file
f.close()