diff --git a/meshroom/nodes/aliceVision/LdrToHdrCalibration.py b/meshroom/nodes/aliceVision/LdrToHdrCalibration.py index 33503f72..feaa31f2 100644 --- a/meshroom/nodes/aliceVision/LdrToHdrCalibration.py +++ b/meshroom/nodes/aliceVision/LdrToHdrCalibration.py @@ -1,13 +1,32 @@ __version__ = "2.0" +import json +import os + from meshroom.core import desc +def findMetadata(d, keys, defaultValue): + v = None + for key in keys: + v = d.get(key, None) + k = key.lower() + if v != None: + return v + for dk, dv in d.iteritems(): + dkm = dk.lower().replace(" ", "") + if dkm == key.lower(): + return dv + dkm = dkm.split(":")[-1] + dkm = dkm.split("/")[-1] + if dkm == k: + return dv + return defaultValue + + class LdrToHdrCalibration(desc.CommandLineNode): commandLine = 'aliceVision_LdrToHdrCalibration {allParams}' size = desc.DynamicNodeSize('input') - #parallelization = desc.Parallelization(blockSize=40) - #commandLineRange = '--rangeStart {rangeStart} --rangeSize {rangeBlockSize}' documentation = ''' Calibrate LDR to HDR response curve from samples @@ -108,4 +127,68 @@ class LdrToHdrCalibration(desc.CommandLineNode): value=desc.Node.internalFolder + 'response.csv', uid=[], ) - ] \ No newline at end of file + ] + + @classmethod + def update(cls, node): + if not isinstance(node.nodeDesc, cls): + raise ValueError("Node {} is not an instance of type {}".format(node, cls)) + # TODO: use Node version for this test + if 'userNbBrackets' not in node.getAttributes().keys(): + # Old version of the node + return + if node.userNbBrackets.value != 0: + node.nbBrackets.value = node.userNbBrackets.value + return + # logging.info("[LDRToHDR] Update start: version:" + str(node.packageVersion)) + cameraInitOutput = node.input.getLinkParam(recursive=True) + if not cameraInitOutput: + node.nbBrackets.value = 0 + return + print("LdrToHdrCalib cameraInitOutput: " + str(cameraInitOutput)) + viewpoints = cameraInitOutput.node.viewpoints.value + print("LdrToHdrCalib viewpoints: " + str(viewpoints)) + + # logging.info("[LDRToHDR] Update start: nb viewpoints:" + str(len(viewpoints))) + inputs = [] + for viewpoint in viewpoints: + jsonMetadata = viewpoint.metadata.value + if not jsonMetadata: + # no metadata, we cannot found the number of brackets + node.nbBrackets.value = 0 + return + d = json.loads(jsonMetadata) + fnumber = findMetadata(d, ["FNumber", "Exif:ApertureValue", "ApertureValue", "Aperture"], "") + shutterSpeed = findMetadata(d, ["Exif:ShutterSpeedValue", "ShutterSpeedValue", "ShutterSpeed"], "") + iso = findMetadata(d, ["Exif:ISOSpeedRatings", "ISOSpeedRatings", "ISO"], "") + if not fnumber and not shutterSpeed: + # If one image without shutter or fnumber, we cannot found the number of brackets. + # We assume that there is no multi-bracketing, so nothing to do. + node.nbBrackets.value = 1 + return + inputs.append((viewpoint.path.value, (fnumber, shutterSpeed, iso))) + inputs.sort() + + exposureGroups = [] + exposures = [] + for path, exp in inputs: + if exposures and exp != exposures[-1] and exp == exposures[0]: + exposureGroups.append(exposures) + exposures = [exp] + else: + exposures.append(exp) + exposureGroups.append(exposures) + exposures = None + bracketSizes = set() + if len(exposureGroups) == 1: + node.nbBrackets.value = 1 + else: + for expGroup in exposureGroups: + bracketSizes.add(len(expGroup)) + if len(bracketSizes) == 1: + node.nbBrackets.value = bracketSizes.pop() + # logging.info("[LDRToHDR] nb bracket size:" + str(node.nbBrackets.value)) + else: + node.nbBrackets.value = 0 + # logging.info("[LDRToHDR] Update end") + diff --git a/meshroom/nodes/aliceVision/LdrToHdrMerge.py b/meshroom/nodes/aliceVision/LdrToHdrMerge.py index ba099b8f..f63606cd 100644 --- a/meshroom/nodes/aliceVision/LdrToHdrMerge.py +++ b/meshroom/nodes/aliceVision/LdrToHdrMerge.py @@ -1,11 +1,48 @@ __version__ = "2.0" +import json +import os + from meshroom.core import desc +def findMetadata(d, keys, defaultValue): + v = None + for key in keys: + v = d.get(key, None) + k = key.lower() + if v != None: + return v + for dk, dv in d.iteritems(): + dkm = dk.lower().replace(" ", "") + if dkm == key.lower(): + return dv + dkm = dkm.split(":")[-1] + dkm = dkm.split("/")[-1] + if dkm == k: + return dv + return defaultValue + + + +class DividedInputNodeSize(desc.DynamicNodeSize): + """ + The LDR2HDR will reduce the amount of views in the SfMData. + This class converts the number of LDR input views into the number of HDR output views. + """ + def __init__(self, param, divParam): + super(DividedInputNodeSize, self).__init__(param) + self._divParam = divParam + def computeSize(self, node): + s = super(DividedInputNodeSize, self).computeSize(node) + divParam = node.attribute(self._divParam) + if divParam.value == 0: + return s + return s / divParam.value + class LdrToHdrMerge(desc.CommandLineNode): commandLine = 'aliceVision_LdrToHdrMerge {allParams}' - size = desc.DynamicNodeSize('input') + size = DividedInputNodeSize('input', 'nbBrackets') #parallelization = desc.Parallelization(blockSize=40) #commandLineRange = '--rangeStart {rangeStart} --rangeSize {rangeBlockSize}' @@ -93,4 +130,66 @@ class LdrToHdrMerge(desc.CommandLineNode): value=desc.Node.internalFolder + 'sfmData.sfm', uid=[], ) - ] \ No newline at end of file + ] + + @classmethod + def update(cls, node): + if not isinstance(node.nodeDesc, cls): + raise ValueError("Node {} is not an instance of type {}".format(node, cls)) + # TODO: use Node version for this test + if 'userNbBrackets' not in node.getAttributes().keys(): + # Old version of the node + return + if node.userNbBrackets.value != 0: + node.nbBrackets.value = node.userNbBrackets.value + return + # logging.info("[LDRToHDR] Update start: version:" + str(node.packageVersion)) + cameraInitOutput = node.input.getLinkParam(recursive=True) + if not cameraInitOutput: + node.nbBrackets.value = 0 + return + viewpoints = cameraInitOutput.node.viewpoints.value + + # logging.info("[LDRToHDR] Update start: nb viewpoints:" + str(len(viewpoints))) + inputs = [] + for viewpoint in viewpoints: + jsonMetadata = viewpoint.metadata.value + if not jsonMetadata: + # no metadata, we cannot found the number of brackets + node.nbBrackets.value = 0 + return + d = json.loads(jsonMetadata) + fnumber = findMetadata(d, ["FNumber", "Exif:ApertureValue", "ApertureValue", "Aperture"], "") + shutterSpeed = findMetadata(d, ["Exif:ShutterSpeedValue", "ShutterSpeedValue", "ShutterSpeed"], "") + iso = findMetadata(d, ["Exif:ISOSpeedRatings", "ISOSpeedRatings", "ISO"], "") + if not fnumber and not shutterSpeed: + # If one image without shutter or fnumber, we cannot found the number of brackets. + # We assume that there is no multi-bracketing, so nothing to do. + node.nbBrackets.value = 1 + return + inputs.append((viewpoint.path.value, (fnumber, shutterSpeed, iso))) + inputs.sort() + + exposureGroups = [] + exposures = [] + for path, exp in inputs: + if exposures and exp != exposures[-1] and exp == exposures[0]: + exposureGroups.append(exposures) + exposures = [exp] + else: + exposures.append(exp) + exposureGroups.append(exposures) + exposures = None + bracketSizes = set() + if len(exposureGroups) == 1: + node.nbBrackets.value = 1 + else: + for expGroup in exposureGroups: + bracketSizes.add(len(expGroup)) + if len(bracketSizes) == 1: + node.nbBrackets.value = bracketSizes.pop() + # logging.info("[LDRToHDR] nb bracket size:" + str(node.nbBrackets.value)) + else: + node.nbBrackets.value = 0 + # logging.info("[LDRToHDR] Update end") + diff --git a/meshroom/nodes/aliceVision/LdrToHdrSampling.py b/meshroom/nodes/aliceVision/LdrToHdrSampling.py index 4547a9d1..ee481c79 100644 --- a/meshroom/nodes/aliceVision/LdrToHdrSampling.py +++ b/meshroom/nodes/aliceVision/LdrToHdrSampling.py @@ -1,7 +1,27 @@ __version__ = "2.0" +import json +import os + from meshroom.core import desc +def findMetadata(d, keys, defaultValue): + v = None + for key in keys: + v = d.get(key, None) + k = key.lower() + if v != None: + return v + for dk, dv in d.iteritems(): + dkm = dk.lower().replace(" ", "") + if dkm == key.lower(): + return dv + dkm = dkm.split(":")[-1] + dkm = dkm.split("/")[-1] + if dkm == k: + return dv + return defaultValue + class LdrToHdrSampling(desc.CommandLineNode): commandLine = 'aliceVision_LdrToHdrSampling {allParams}' @@ -74,4 +94,66 @@ class LdrToHdrSampling(desc.CommandLineNode): value=desc.Node.internalFolder, uid=[], ), - ] \ No newline at end of file + ] + + @classmethod + def update(cls, node): + if not isinstance(node.nodeDesc, cls): + raise ValueError("Node {} is not an instance of type {}".format(node, cls)) + # TODO: use Node version for this test + if 'userNbBrackets' not in node.getAttributes().keys(): + # Old version of the node + return + if node.userNbBrackets.value != 0: + node.nbBrackets.value = node.userNbBrackets.value + return + # logging.info("[LDRToHDR] Update start: version:" + str(node.packageVersion)) + cameraInitOutput = node.input.getLinkParam() + if not cameraInitOutput: + node.nbBrackets.value = 0 + return + viewpoints = cameraInitOutput.node.viewpoints.value + + # logging.info("[LDRToHDR] Update start: nb viewpoints:" + str(len(viewpoints))) + inputs = [] + for viewpoint in viewpoints: + jsonMetadata = viewpoint.metadata.value + if not jsonMetadata: + # no metadata, we cannot found the number of brackets + node.nbBrackets.value = 0 + return + d = json.loads(jsonMetadata) + fnumber = findMetadata(d, ["FNumber", "Exif:ApertureValue", "ApertureValue", "Aperture"], "") + shutterSpeed = findMetadata(d, ["Exif:ShutterSpeedValue", "ShutterSpeedValue", "ShutterSpeed"], "") + iso = findMetadata(d, ["Exif:ISOSpeedRatings", "ISOSpeedRatings", "ISO"], "") + if not fnumber and not shutterSpeed: + # If one image without shutter or fnumber, we cannot found the number of brackets. + # We assume that there is no multi-bracketing, so nothing to do. + node.nbBrackets.value = 1 + return + inputs.append((viewpoint.path.value, (fnumber, shutterSpeed, iso))) + inputs.sort() + + exposureGroups = [] + exposures = [] + for path, exp in inputs: + if exposures and exp != exposures[-1] and exp == exposures[0]: + exposureGroups.append(exposures) + exposures = [exp] + else: + exposures.append(exp) + exposureGroups.append(exposures) + exposures = None + bracketSizes = set() + if len(exposureGroups) == 1: + node.nbBrackets.value = 1 + else: + for expGroup in exposureGroups: + bracketSizes.add(len(expGroup)) + if len(bracketSizes) == 1: + node.nbBrackets.value = bracketSizes.pop() + # logging.info("[LDRToHDR] nb bracket size:" + str(node.nbBrackets.value)) + else: + node.nbBrackets.value = 0 + # logging.info("[LDRToHDR] Update end") +