OpenDroneMap-ODM/opendm/exiftool.py

94 wiersze
3.0 KiB
Python

import json
import os
import tempfile
import base64
from rasterio.io import MemoryFile
from opendm.system import run
from opendm import log
from opendm.utils import double_quote
def extract_raw_thermal_image_data(image_path):
try:
f, tmp_file_path = tempfile.mkstemp(suffix='.json')
os.close(f)
try:
output = run("exiftool -b -x ThumbnailImage -x PreviewImage -j \"%s\" > \"%s\"" % (image_path, tmp_file_path), quiet=True)
with open(tmp_file_path) as f:
j = json.loads(f.read())
if isinstance(j, list):
j = j[0] # single file
if "RawThermalImage" in j:
imageBytes = base64.b64decode(j["RawThermalImage"][len("base64:"):])
with MemoryFile(imageBytes) as memfile:
with memfile.open() as dataset:
img = dataset.read()
bands, h, w = img.shape
if bands != 1:
raise Exception("Raw thermal image has more than one band? This is not supported")
# (1, 512, 640) --> (512, 640, 1)
img = img[0][:,:,None]
del j["RawThermalImage"]
return extract_temperature_params_from(j), img
else:
raise Exception("Invalid JSON (not a list)")
except Exception as e:
log.ODM_WARNING("Cannot extract tags using exiftool: %s" % str(e))
return {}, None
finally:
if os.path.isfile(tmp_file_path):
os.remove(tmp_file_path)
except Exception as e:
log.ODM_WARNING("Cannot create temporary file: %s" % str(e))
return {}, None
def unit(unit):
def _convert(v):
if isinstance(v, float):
return v
elif isinstance(v, str):
if not v[-1].isnumeric():
if v[-1].upper() != unit.upper():
log.ODM_WARNING("Assuming %s is in %s" % (v, unit))
return float(v[:-1])
else:
return float(v)
else:
return float(v)
return _convert
def extract_temperature_params_from(tags):
# Defaults
meta = {
"Emissivity": float,
"ObjectDistance": unit("m"),
"AtmosphericTemperature": unit("C"),
"ReflectedApparentTemperature": unit("C"),
"IRWindowTemperature": unit("C"),
"IRWindowTransmission": float,
"RelativeHumidity": unit("%"),
"PlanckR1": float,
"PlanckB": float,
"PlanckF": float,
"PlanckO": float,
"PlanckR2": float,
}
params = {}
for m in meta:
if m not in tags:
# All or nothing
raise Exception("Cannot find %s in tags" % m)
params[m] = (meta[m])(tags[m])
return params