Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nodes] HDR Fusion: Use the same bracket detection as in AliceVision #2154

Merged
merged 1 commit into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 56 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 math
import os
from collections import Counter

Expand Down Expand Up @@ -176,7 +177,7 @@
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

Check notice on line 180 in meshroom/nodes/aliceVision/LdrToHdrCalibration.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/nodes/aliceVision/LdrToHdrCalibration.py#L180

unresolved comment '# TODO: use Node version for this test' (C100)
if "userNbBrackets" not in node.getAttributes().keys():
# Old version of the node
return
Expand Down Expand Up @@ -205,9 +206,20 @@
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"], "")

# Find Fnumber
fnumber = findMetadata(d, ["FNumber"], "")
if fnumber == "":
aperture = findMetadata(d, ["Exif:ApertureValue", "ApertureValue", "Aperture"], "")
if aperture == "":
fnumber = -1.0
else:
fnumber = pow(2.0, aperture / 2.0)

# Get shutter speed and ISO
shutterSpeed = findMetadata(d, ["ExposureTime", "Exif:ShutterSpeedValue", "ShutterSpeedValue", "ShutterSpeed"], -1.0)
iso = findMetadata(d, ["Exif:PhotographicSensitivity", "PhotographicSensitivity", "Photographic Sensitivity", "ISO"], -1.0)

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.
Expand All @@ -222,6 +234,7 @@
prevShutterSpeed = 0.0
prevIso = 0.0
prevPath = None # Stores the dirname of the previous parsed image
prevExposure = None
newGroup = False # True if a new exposure group needs to be created (useful when there are several datasets)
for path, exp in inputs:
# If the dirname of the previous image and the dirname of the current image do not match, this means that the
Expand All @@ -231,20 +244,18 @@
if prevPath is not None and prevPath != os.path.dirname(path):
newGroup = True

# A new group is created if the current image's exposure level is larger than the previous image's, if there
# were any changes in the ISO or aperture value, or if a new dataset has been detected with the path.
# Since the input images are ordered, the shutter speed should always be decreasing, so a shutter speed larger
# than the previous one indicates the start of a new exposure group.
fnumber, shutterSpeed, iso = exp
if exposures:
prevFnumber, prevShutterSpeed, prevIso = exposures[-1]
if exposures and len(exposures) > 1 and (fnumber > prevFnumber or shutterSpeed > prevShutterSpeed or iso < prevIso) or newGroup:
currentExposure = LdrToHdrCalibration.getExposure(exp)

# Create a new group if the current image's exposure level is smaller than the previous image's, or
# if a new dataset has been detected (with a change in the path of the images).
if prevExposure and currentExposure < prevExposure or newGroup:
exposureGroups.append(exposures)
exposures = [exp]
else:
exposures.append(exp)

prevPath = os.path.dirname(path)
prevExposure = currentExposure
newGroup = False

exposureGroups.append(exposures)
Expand Down Expand Up @@ -274,3 +285,37 @@

bestBracketSize = bestTuple[0]
node.nbBrackets.value = bestBracketSize

@staticmethod
def getExposure(exp, refIso = 100.0, refFnumber = 1.0):
fnumber, shutterSpeed, iso = exp

validShutterSpeed = shutterSpeed > 0.0 and math.isfinite(shutterSpeed)
validFnumber = fnumber > 0.0 and math.isfinite(fnumber)

if not validShutterSpeed and not validFnumber:
return -1.0

validRefFnumber = refFnumber > 0.0 and math.isfinite(refFnumber)

if not validShutterSpeed:
shutterSpeed = 1.0 / 200.0

if not validFnumber:
if validRefFnumber:
fnumber = refFnumber
else:
fnumber = 2.0

lRefFnumber = refFnumber
if not validRefFnumber:
lRefFnumber = fnumber

isoToAperture = 1.0
if iso > 1e-6 and refIso > 1e-6:
isoToAperture = math.sqrt(iso / refIso)

newFnumber = fnumber * isoToAperture
expIncrease = (newFnumber / lRefFnumber) * (newFnumber / lRefFnumber)

return shutterSpeed * expIncrease
67 changes: 56 additions & 11 deletions meshroom/nodes/aliceVision/LdrToHdrMerge.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import json
import os
import math
from collections import Counter

from meshroom.core import desc
Expand Down Expand Up @@ -262,7 +263,7 @@
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

Check notice on line 266 in meshroom/nodes/aliceVision/LdrToHdrMerge.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/nodes/aliceVision/LdrToHdrMerge.py#L266

unresolved comment '# TODO: use Node version for this test' (C100)
if "userNbBrackets" not in node.getAttributes().keys():
# Old version of the node
return
Expand Down Expand Up @@ -291,9 +292,20 @@
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"], "")

# Find Fnumber
fnumber = findMetadata(d, ["FNumber"], "")
if fnumber == "":
aperture = findMetadata(d, ["Exif:ApertureValue", "ApertureValue", "Aperture"], "")
if aperture == "":
fnumber = -1.0
else:
fnumber = pow(2.0, aperture / 2.0)

# Get shutter speed and ISO
shutterSpeed = findMetadata(d, ["ExposureTime", "Exif:ShutterSpeedValue", "ShutterSpeedValue", "ShutterSpeed"], -1.0)
iso = findMetadata(d, ["Exif:PhotographicSensitivity", "PhotographicSensitivity", "Photographic Sensitivity", "ISO"], -1.0)

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.
Expand All @@ -308,6 +320,7 @@
prevShutterSpeed = 0.0
prevIso = 0.0
prevPath = None # Stores the dirname of the previous parsed image
prevExposure = None
newGroup = False # True if a new exposure group needs to be created (useful when there are several datasets)
for path, exp in inputs:
# If the dirname of the previous image and the dirname of the current image do not match, this means that the
Expand All @@ -317,20 +330,18 @@
if prevPath is not None and prevPath != os.path.dirname(path):
newGroup = True

# A new group is created if the current image's exposure level is larger than the previous image's, if there
# were any changes in the ISO or aperture value, or if a new dataset has been detected with the path.
# Since the input images are ordered, the shutter speed should always be decreasing, so a shutter speed larger
# than the previous one indicates the start of a new exposure group.
fnumber, shutterSpeed, iso = exp
if exposures:
prevFnumber, prevShutterSpeed, prevIso = exposures[-1]
if exposures and len(exposures) > 1 and (fnumber > prevFnumber or shutterSpeed > prevShutterSpeed or iso < prevIso) or newGroup:
currentExposure = LdrToHdrMerge.getExposure(exp)

# Create a new group if the current image's exposure level is smaller than the previous image's, or
# if a new dataset has been detected (with a change in the path of the images).
if prevExposure and currentExposure < prevExposure or newGroup:
exposureGroups.append(exposures)
exposures = [exp]
else:
exposures.append(exp)

prevPath = os.path.dirname(path)
prevExposure = currentExposure
newGroup = False

exposureGroups.append(exposures)
Expand Down Expand Up @@ -361,6 +372,40 @@
bestBracketSize = bestTuple[0]
node.nbBrackets.value = bestBracketSize

@staticmethod
def getExposure(exp, refIso = 100.0, refFnumber = 1.0):
fnumber, shutterSpeed, iso = exp

validShutterSpeed = shutterSpeed > 0.0 and math.isfinite(shutterSpeed)
validFnumber = fnumber > 0.0 and math.isfinite(fnumber)

if not validShutterSpeed and not validFnumber:
return -1.0

validRefFnumber = refFnumber > 0.0 and math.isfinite(refFnumber)

if not validShutterSpeed:
shutterSpeed = 1.0 / 200.0

if not validFnumber:
if validRefFnumber:
fnumber = refFnumber
else:
fnumber = 2.0

lRefFnumber = refFnumber
if not validRefFnumber:
lRefFnumber = fnumber

isoToAperture = 1.0
if iso > 1e-6 and refIso > 1e-6:
isoToAperture = math.sqrt(iso / refIso)

newFnumber = fnumber * isoToAperture
expIncrease = (newFnumber / lRefFnumber) * (newFnumber / lRefFnumber)

return shutterSpeed * expIncrease

def processChunk(self, chunk):
# Trick to avoid sending --nbBrackets to the command line when the bracket detection is automatic.
# Otherwise, the AliceVision executable has no way of determining whether the bracket detection was automatic
Expand Down
67 changes: 56 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 math
import os
from collections import Counter

Expand Down Expand Up @@ -201,7 +202,7 @@
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

Check notice on line 205 in meshroom/nodes/aliceVision/LdrToHdrSampling.py

View check run for this annotation

codefactor.io / CodeFactor

meshroom/nodes/aliceVision/LdrToHdrSampling.py#L205

unresolved comment '# TODO: use Node version for this test' (C100)
if "userNbBrackets" not in node.getAttributes().keys():
# Old version of the node
return
Expand Down Expand Up @@ -231,9 +232,20 @@
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"], "")

# Find Fnumber
fnumber = findMetadata(d, ["FNumber"], "")
if fnumber == "":
aperture = findMetadata(d, ["Exif:ApertureValue", "ApertureValue", "Aperture"], "")
if aperture == "":
fnumber = -1.0
else:
fnumber = pow(2.0, aperture / 2.0)

# Get shutter speed and ISO
shutterSpeed = findMetadata(d, ["ExposureTime", "Exif:ShutterSpeedValue", "ShutterSpeedValue", "ShutterSpeed"], -1.0)
iso = findMetadata(d, ["Exif:PhotographicSensitivity", "PhotographicSensitivity", "Photographic Sensitivity", "ISO"], -1.0)

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.
Expand All @@ -248,6 +260,7 @@
prevShutterSpeed = 0.0
prevIso = 0.0
prevPath = None # Stores the dirname of the previous parsed image
prevExposure = None
newGroup = False # True if a new exposure group needs to be created (useful when there are several datasets)
for path, exp in inputs:
# If the dirname of the previous image and the dirname of the current image do not match, this means that the
Expand All @@ -257,20 +270,18 @@
if prevPath is not None and prevPath != os.path.dirname(path):
newGroup = True

# A new group is created if the current image's exposure level is larger than the previous image's, if there
# were any changes in the ISO or aperture value, or if a new dataset has been detected with the path.
# Since the input images are ordered, the shutter speed should always be decreasing, so a shutter speed larger
# than the previous one indicates the start of a new exposure group.
fnumber, shutterSpeed, iso = exp
if exposures:
prevFnumber, prevShutterSpeed, prevIso = exposures[-1]
if exposures and len(exposures) > 1 and (fnumber > prevFnumber or shutterSpeed > prevShutterSpeed or iso < prevIso) or newGroup:
currentExposure = LdrToHdrSampling.getExposure(exp)

# Create a new group if the current image's exposure level is smaller than the previous image's, or
# if a new dataset has been detected (with a change in the path of the images).
if prevExposure and currentExposure < prevExposure or newGroup:
exposureGroups.append(exposures)
exposures = [exp]
else:
exposures.append(exp)

prevPath = os.path.dirname(path)
prevExposure = currentExposure
newGroup = False

exposureGroups.append(exposures)
Expand Down Expand Up @@ -302,3 +313,37 @@
bestCount = bestTuple[1]
node.outliersNb = len(inputs) - (bestBracketSize * bestCount) # Compute number of outliers
node.nbBrackets.value = bestBracketSize

@staticmethod
def getExposure(exp, refIso = 100.0, refFnumber = 1.0):
fnumber, shutterSpeed, iso = exp

validShutterSpeed = shutterSpeed > 0.0 and math.isfinite(shutterSpeed)
validFnumber = fnumber > 0.0 and math.isfinite(fnumber)

if not validShutterSpeed and not validFnumber:
return -1.0

validRefFnumber = refFnumber > 0.0 and math.isfinite(refFnumber)

if not validShutterSpeed:
shutterSpeed = 1.0 / 200.0

if not validFnumber:
if validRefFnumber:
fnumber = refFnumber
else:
fnumber = 2.0

lRefFnumber = refFnumber
if not validRefFnumber:
lRefFnumber = fnumber

isoToAperture = 1.0
if iso > 1e-6 and refIso > 1e-6:
isoToAperture = math.sqrt(iso / refIso)

newFnumber = fnumber * isoToAperture
expIncrease = (newFnumber / lRefFnumber) * (newFnumber / lRefFnumber)

return shutterSpeed * expIncrease