Meshroom/meshroom/nodes/aliceVision/ExtractMetadata.py
2025-01-30 17:18:58 +01:00

120 lines
4.2 KiB
Python

__version__ = "0.1"
from meshroom.core import desc
from meshroom.core.utils import VERBOSE_LEVEL
import distutils.dir_util as du
import shutil
import glob
import os
class ExtractMetadata(desc.Node):
size = desc.DynamicNodeSize("input")
category = 'Utils'
documentation = '''
Using exifTool, this node extracts metadata of all images referenced in a sfmData and store them in appropriate files.
'''
inputs = [
desc.File(
name="input",
label="Input",
description="SfMData file input.",
value="",
),
desc.BoolParam(
name="keepFilename",
label="Keep Filename",
description="Keep the filename of the inputs for the outputs.",
value=False,
),
desc.ChoiceParam(
name="extension",
label="Output File Extension",
description="Metadata file extension.",
value="txt",
values=["txt", "xml", "xmp"],
exclusive=True,
),
desc.StringParam(
name="arguments",
label="Arguments",
description="ExifTool command arguments",
value="",
),
desc.ChoiceParam(
name="verboseLevel",
label="Verbose Level",
description="Verbosity level (fatal, error, warning, info, debug, trace).",
values=VERBOSE_LEVEL,
value="info",
),
]
outputs = [
desc.File(
name="output",
label="Result Folder",
description="Output path for the resulting images.",
value=desc.Node.internalFolder,
),
]
def resolvedPaths(self, inputSfm, outDir, keepFilename, extension):
import pyalicevision as av
from pathlib import Path
paths = {}
dataAV = av.sfmData.SfMData()
if av.sfmDataIO.load(dataAV, inputSfm, av.sfmDataIO.ALL) and os.path.isdir(outDir):
views = dataAV.getViews()
for id, v in views.items():
inputFile = v.getImage().getImagePath()
if keepFilename:
outputMetadata = os.path.join(outDir, Path(inputFile).stem + "." + extension)
else:
outputMetadata = os.path.join(outDir, str(id) + "." + extension)
paths[inputFile] = outputMetadata
return paths
def processChunk(self, chunk):
try:
chunk.logManager.start(chunk.node.verboseLevel.value)
if not chunk.node.input:
chunk.logger.warning('No image file to process')
return
outFiles = self.resolvedPaths(chunk.node.input.value, chunk.node.output.value, chunk.node.keepFilename.value, chunk.node.extension.value)
if not outFiles:
error = 'ExtractMetadata: No input files! Check that a sfmData is connected as input.'
chunk.logger.error(error)
raise RuntimeError(error)
if not os.path.exists(chunk.node.output.value):
os.mkdir(chunk.node.output.value)
for iFile, oFile in outFiles.items():
if chunk.node.extension.value == 'txt':
cmd = 'exiftool ' + chunk.node.arguments.value.strip() + ' ' + iFile + ' > ' + oFile
elif chunk.node.extension.value == 'xml':
cmd = 'exiftool -X ' + chunk.node.arguments.value.strip() + ' ' + iFile + ' > ' + oFile
else: #xmp
cmd = 'exiftool -tagsfromfile ' + iFile + ' ' + chunk.node.arguments.value.strip() + ' ' + oFile
chunk.logger.debug(cmd)
try:
os.system(cmd)
except:
chunk.logger.error("exifTool command failed ! Check that exifTool can be accessed on your system.")
raise RuntimeError(error)
if not os.path.exists(oFile):
info = 'No metadata extracted for file ' + iFile
chunk.logger.info(info)
chunk.logger.info('Metadata extraction end')
finally:
chunk.logManager.end()