Skip to content

Commit

Permalink
[nodes] HDR Fusion: Correctly detect number of brackets
Browse files Browse the repository at this point in the history
The detection of the number of brackets used to only work in a case where
there was a single dataset / a single camera intrinsics. If two datasets
with the same number of brackets were provided, the detection was failing
because we expected the exposure levels to be uniform across all the
images.

If more than one dataset is provided, there is no guarantee that the
exposure groups will be identical although the number of brackets is the
same.

Since the path of each image whose exposure is evaluated is available, this
commit uses it to determine whether the evaluated dataset is still the
same. While it is, the bracket detection is performed as usual: a new
exposure group is created whenever the exposure level of an image
corresponds to the first exposure level of an already existing group.

As soon as it is not, a new group is immediately created, and the rest
of the evaluation can resume.

Using the paths to determine whether the dataset has changed is chosen
over assuming that the exposure levels within a same group should always
increase or decrease, as there is no explicit guarantee that this order
will always be respected across the provided datasets.
  • Loading branch information
cbentejac committed Jul 7, 2023
1 parent 96ae35b commit 60f694b
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 33 deletions.
36 changes: 25 additions & 11 deletions meshroom/nodes/aliceVision/LdrToHdrCalibration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
__version__ = "3.0"

import json
import os

from meshroom.core import desc

Expand Down Expand Up @@ -168,33 +169,31 @@ 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():
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
if not cameraInitOutput.node.hasAttribute('viewpoints'):
if cameraInitOutput.node.hasAttribute('input'):
if not cameraInitOutput.node.hasAttribute("viewpoints"):
if cameraInitOutput.node.hasAttribute("input"):
cameraInitOutput = cameraInitOutput.node.input.getLinkParam(recursive=True)
if cameraInitOutput and cameraInitOutput.node and cameraInitOutput.node.hasAttribute('viewpoints'):
if cameraInitOutput and cameraInitOutput.node and cameraInitOutput.node.hasAttribute("viewpoints"):
viewpoints = cameraInitOutput.node.viewpoints.value
else:
# No connected CameraInit
node.nbBrackets.value = 0
return

# 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
# no metadata, we cannot find the number of brackets
node.nbBrackets.value = 0
return
d = json.loads(jsonMetadata)
Expand All @@ -211,13 +210,30 @@ def update(cls, node):

exposureGroups = []
exposures = []
prevPath = None # Stores the dirname of the previous parsed image
newGroup = False # True if a new exposure group needs to be created (useful when there are several datasets)
for path, exp in inputs:
if exposures and exp != exposures[-1] and exp == exposures[0]:
# If the dirname of the previous image and the dirname of the current image do not match, this means that the
# dataset that is being parsed has changed. A new group needs to be created but will fail to be detected in the
# next "if" statement if the new dataset's exposure levels are different. Setting "newGroup" to True prevents this
# from happening.
if prevPath is not None and prevPath != os.path.dirname(path):
newGroup = True

# A new group is created if one of these is true:
# - a change of dataset has been detected ("newGroup" has been flagged)
# - the exposure level of the current image is different from the previous image's,
# but corresponds to the first exposure level of the group
if exposures and (exp != exposures[-1] and exp == exposures[0]) or newGroup:
exposureGroups.append(exposures)
exposures = [exp]
else:
exposures.append(exp)

prevPath = os.path.dirname(path)
newGroup = False
exposureGroups.append(exposures)

exposures = None
bracketSizes = set()
if len(exposureGroups) == 1:
Expand All @@ -230,10 +246,8 @@ def update(cls, node):
else:
for expGroup in exposureGroups:
bracketSizes.add(len(expGroup))
print(bracketSizes)
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")

35 changes: 24 additions & 11 deletions meshroom/nodes/aliceVision/LdrToHdrMerge.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
__version__ = "4.1"

import json
import os

from meshroom.core import desc

Expand Down Expand Up @@ -260,33 +261,31 @@ 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():
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
if not cameraInitOutput.node.hasAttribute('viewpoints'):
if cameraInitOutput.node.hasAttribute('input'):
if not cameraInitOutput.node.hasAttribute("viewpoints"):
if cameraInitOutput.node.hasAttribute("input"):
cameraInitOutput = cameraInitOutput.node.input.getLinkParam(recursive=True)
if cameraInitOutput and cameraInitOutput.node and cameraInitOutput.node.hasAttribute('viewpoints'):
if cameraInitOutput and cameraInitOutput.node and cameraInitOutput.node.hasAttribute("viewpoints"):
viewpoints = cameraInitOutput.node.viewpoints.value
else:
# No connected CameraInit
node.nbBrackets.value = 0
return

# 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
# no metadata, we cannot find the number of brackets
node.nbBrackets.value = 0
return
d = json.loads(jsonMetadata)
Expand All @@ -303,13 +302,30 @@ def update(cls, node):

exposureGroups = []
exposures = []
prevPath = None # Stores the dirname of the previous parsed image
newGroup = False # True if a new exposure group needs to be created (useful when there are several datasets)
for path, exp in inputs:
if exposures and exp != exposures[-1] and exp == exposures[0]:
# If the dirname of the previous image and the dirname of the current image do not match, this means that the
# dataset that is being parsed has changed. A new group needs to be created but will fail to be detected in the
# next "if" statement if the new dataset's exposure levels are different. Setting "newGroup" to True prevents this
# from happening.
if prevPath is not None and prevPath != os.path.dirname(path):
newGroup = True

# A new group is created if one of these is true:
# - a change of dataset has been detected ("newGroup" has been flagged)
# - the exposure level of the current image is different from the previous image's,
# but corresponds to the first exposure level of the group
if exposures and (exp != exposures[-1] and exp == exposures[0]) or newGroup:
exposureGroups.append(exposures)
exposures = [exp]
else:
exposures.append(exp)

prevPath = os.path.dirname(path)
newGroup = False
exposureGroups.append(exposures)

exposures = None
bracketSizes = set()
if len(exposureGroups) == 1:
Expand All @@ -324,8 +340,5 @@ def update(cls, node):
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")

35 changes: 24 additions & 11 deletions meshroom/nodes/aliceVision/LdrToHdrSampling.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
__version__ = "4.0"

import json
import os

from meshroom.core import desc

Expand Down Expand Up @@ -189,33 +190,31 @@ 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():
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
if not cameraInitOutput.node.hasAttribute('viewpoints'):
if cameraInitOutput.node.hasAttribute('input'):
if not cameraInitOutput.node.hasAttribute("viewpoints"):
if cameraInitOutput.node.hasAttribute("input"):
cameraInitOutput = cameraInitOutput.node.input.getLinkParam(recursive=True)
if cameraInitOutput and cameraInitOutput.node and cameraInitOutput.node.hasAttribute('viewpoints'):
if cameraInitOutput and cameraInitOutput.node and cameraInitOutput.node.hasAttribute("viewpoints"):
viewpoints = cameraInitOutput.node.viewpoints.value
else:
# No connected CameraInit
node.nbBrackets.value = 0
return

# 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
# no metadata, we cannot find the number of brackets
node.nbBrackets.value = 0
return
d = json.loads(jsonMetadata)
Expand All @@ -232,13 +231,30 @@ def update(cls, node):

exposureGroups = []
exposures = []
prevPath = None # Stores the dirname of the previous parsed image
newGroup = False # True if a new exposure group needs to be created (useful when there are several datasets)
for path, exp in inputs:
if exposures and exp != exposures[-1] and exp == exposures[0]:
# If the dirname of the previous image and the dirname of the current image do not match, this means that the
# dataset that is being parsed has changed. A new group needs to be created but will fail to be detected in the
# next "if" statement if the new dataset's exposure levels are different. Setting "newGroup" to True prevents this
# from happening.
if prevPath is not None and prevPath != os.path.dirname(path):
newGroup = True

# A new group is created if one of these is true:
# - a change of dataset has been detected ("newGroup" has been flagged)
# - the exposure level of the current image is different from the previous image's,
# but corresponds to the first exposure level of the group
if exposures and (exp != exposures[-1] and exp == exposures[0]) or newGroup:
exposureGroups.append(exposures)
exposures = [exp]
else:
exposures.append(exp)

prevPath = os.path.dirname(path)
newGroup = False
exposureGroups.append(exposures)

exposures = None
bracketSizes = set()
if len(exposureGroups) == 1:
Expand All @@ -253,8 +269,5 @@ def update(cls, node):
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")

0 comments on commit 60f694b

Please sign in to comment.