Skip to content

Commit

Permalink
Merge pull request #1173 from alicevision/dev/largeWarping
Browse files Browse the repository at this point in the history
[panorama] PanoramaCompositing: new out-of-core algorithm
  • Loading branch information
fabiencastan authored Feb 12, 2021
2 parents aa8bbfd + 79e4a59 commit e82d0cd
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 53 deletions.
38 changes: 24 additions & 14 deletions meshroom/core/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class StatusData(BaseObject):
"""
dateTimeFormatting = '%Y-%m-%d %H:%M:%S.%f'

def __init__(self, nodeName='', nodeType='', packageName='', packageVersion=''):
def __init__(self, nodeName='', nodeType='', packageName='', packageVersion='', parent=None):
super(StatusData, self).__init__(parent)
self.status = Status.NONE
self.execMode = ExecMode.NONE
self.nodeName = nodeName
Expand Down Expand Up @@ -113,6 +114,7 @@ def elapsedTimeStr(self):

def toDict(self):
d = self.__dict__.copy()
d.pop('destroyed', None) # skip non data attributes from BaseObject
d["elapsedTimeStr"] = self.elapsedTimeStr
return d

Expand Down Expand Up @@ -161,7 +163,7 @@ def configureLogger(self):
def start(self, level):
# Clear log file
open(self.chunk.logFile, 'w').close()

self.configureLogger()
self.logger.setLevel(self.textToLevel(level))
self.progressBar = False
Expand All @@ -178,19 +180,19 @@ def makeProgressBar(self, end, message=''):
self.progressEnd = end
self.currentProgressTics = 0
self.progressBar = True

with open(self.chunk.logFile, 'a') as f:
if message:
f.write(message+'\n')
f.write('0% 10 20 30 40 50 60 70 80 90 100%\n')
f.write('|----|----|----|----|----|----|----|----|----|----|\n\n')

f.close()

with open(self.chunk.logFile, 'r') as f:
content = f.read()
self.progressBarPosition = content.rfind('\n')

f.close()

def updateProgressBar(self, value):
Expand Down Expand Up @@ -288,11 +290,16 @@ def updateStatusFromCache(self):
self.statusFileLastModTime = -1
self._status.reset()
else:
with open(statusFile, 'r') as jsonFile:
statusData = json.load(jsonFile)
self._status.fromDict(statusData)
self.statusFileLastModTime = os.path.getmtime(statusFile)
if oldStatus != self._status.status:
try:
with open(statusFile, 'r') as jsonFile:
statusData = json.load(jsonFile)
self.status.fromDict(statusData)
self.statusFileLastModTime = os.path.getmtime(statusFile)
except Exception as e:
self.statusFileLastModTime = -1
self.status.reset()

if oldStatus != self.status.status:
self.statusChanged.emit()

@property
Expand Down Expand Up @@ -323,8 +330,11 @@ def saveStatusFile(self):
data = self._status.toDict()
statusFilepath = self.statusFile
folder = os.path.dirname(statusFilepath)
if not os.path.exists(folder):
try:
os.makedirs(folder)
except Exception as e:
pass

statusFilepathWriting = getWritingFilepath(statusFilepath)
with open(statusFilepathWriting, 'w') as jsonFile:
json.dump(data, jsonFile, indent=4)
Expand Down Expand Up @@ -734,8 +744,8 @@ def clearSubmittedChunks(self):
This must be used with caution. This could lead to inconsistent node status
if the graph is still being computed.
"""
for chunk in self.alreadySubmittedChunks():
if not chunk.isExtern():
for chunk in self._chunks:
if chunk.isAlreadySubmitted():
chunk.upgradeStatusTo(Status.NONE, ExecMode.NONE)

def upgradeStatusTo(self, newStatus):
Expand Down
20 changes: 17 additions & 3 deletions meshroom/multiview.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,24 @@ def panoramaHdrPipeline(graph):
panoramaWarping = graph.addNewNode('PanoramaWarping',
input=panoramaOrientation.output)

panoramaSeams = graph.addNewNode('PanoramaSeams',
input=panoramaWarping.input,
warpingFolder=panoramaWarping.output
)

panoramaCompositing = graph.addNewNode('PanoramaCompositing',
input=panoramaWarping.input,
warpingFolder=panoramaWarping.output)
input=panoramaSeams.input,
warpingFolder=panoramaSeams.warpingFolder,
labels=panoramaSeams.output
)

panoramaMerging = graph.addNewNode('PanoramaMerging',
input=panoramaCompositing.input,
compositingFolder=panoramaCompositing.output
)

imageProcessing = graph.addNewNode('ImageProcessing',
input=panoramaCompositing.output,
input=panoramaMerging.outputPanorama,
fixNonFinite=True,
fillHoles=True,
extension='exr')
Expand All @@ -274,7 +286,9 @@ def panoramaHdrPipeline(graph):
panoramaEstimation,
panoramaOrientation,
panoramaWarping,
panoramaSeams,
panoramaCompositing,
panoramaMerging,
imageProcessing,
]

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/LdrToHdrMerge.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class LdrToHdrMerge(desc.CommandLineNode):
name='enableHighlight',
label='Enable Highlight',
description="Enable highlights correction.",
value=True,
value=False,
uid=[0],
group='user', # not used directly on the command line
enabled= lambda node: node.byPass.enabled and not node.byPass.value,
Expand Down
36 changes: 19 additions & 17 deletions meshroom/nodes/aliceVision/PanoramaCompositing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class PanoramaCompositing(desc.CommandLineNode):
commandLine = 'aliceVision_panoramaCompositing {allParams}'
size = desc.DynamicNodeSize('input')

parallelization = desc.Parallelization(blockSize=5)
commandLineRange = '--rangeIteration {rangeIteration} --rangeSize {rangeBlockSize}'

cpu = desc.Level.INTENSIVE
ram = desc.Level.INTENSIVE

Expand All @@ -35,15 +38,12 @@ class PanoramaCompositing(desc.CommandLineNode):
value='',
uid=[0],
),
desc.ChoiceParam(
name='outputFileType',
label='Output File Type',
description='Output file type for the undistorted images.',
value='exr',
values=['jpg', 'png', 'tif', 'exr'],
exclusive=True,
desc.File(
name='labels',
label='Labels image',
description="Panorama Seams results",
value='',
uid=[0],
group='', # not part of allParams, as this is not a parameter for the command line
),
desc.ChoiceParam(
name='compositerType',
Expand All @@ -57,12 +57,14 @@ class PanoramaCompositing(desc.CommandLineNode):
exclusive=True,
uid=[0]
),
desc.BoolParam(
name='useGraphCut',
label='Use Smart Seams',
description='Use a graphcut algorithm to optmize seams for better transitions between images.',
value=True,
uid=[0],
desc.IntParam(
name='maxThreads',
label='Max Nb Threads',
description='Specifies the maximum number of threads to run simultaneously.',
value=4,
range=(0, 48, 1),
uid=[],
advanced=True,
),
desc.ChoiceParam(
name='storageDataType',
Expand Down Expand Up @@ -105,9 +107,9 @@ class PanoramaCompositing(desc.CommandLineNode):
outputs = [
desc.File(
name='output',
label='Output Panorama',
label='Output Folder',
description='',
value=desc.Node.internalFolder + 'panorama.{outputFileTypeValue}',
value=desc.Node.internalFolder,
uid=[],
),
)
]
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/PanoramaInit.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class PanoramaInit(desc.CommandLineNode):
),
name='nbViewsPerLine',
label='Spherical: Nb Views Per Line',
description='Number of views per line in Spherical acquisition. Assumes angles from [-90°,+90°] for pitch and [-180°,+180°] for yaw. Use -1 to estimate the number of images automatically.',
description='Number of views per line in Spherical acquisition. Assumes angles from [-90,+90deg] for pitch and [-180,+180deg] for yaw. Use -1 to estimate the number of images automatically.',
joinChar=',',
enabled=lambda node: node.initializeCameras.value == 'Spherical',
),
Expand Down
78 changes: 78 additions & 0 deletions meshroom/nodes/aliceVision/PanoramaMerging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
__version__ = "1.0"

import json
import os

from meshroom.core import desc


class PanoramaMerging(desc.CommandLineNode):
commandLine = 'aliceVision_panoramaMerging {allParams}'
size = desc.DynamicNodeSize('input')

cpu = desc.Level.NORMAL
ram = desc.Level.INTENSIVE


documentation = '''
Merge all inputs coming from PanoramaComposiring
'''

inputs = [
desc.File(
name='input',
label='Input SfMData',
description="Input SfMData.",
value='',
uid=[0],
),
desc.File(
name='compositingFolder',
label='compositing Folder',
description="Panorama Compositing results",
value='',
uid=[0],
),
desc.ChoiceParam(
name='outputFileType',
label='Output File Type',
description='Output file type for the undistorted images.',
value='exr',
values=['jpg', 'png', 'tif', 'exr'],
exclusive=True,
uid=[0],
group='', # not part of allParams, as this is not a parameter for the command line
),
desc.ChoiceParam(
name='storageDataType',
label='Storage Data Type',
description='Storage image data type:\n'
' * float: Use full floating point (32 bits per channel)\n'
' * half: Use half float (16 bits per channel)\n'
' * halfFinite: Use half float, but clamp values to avoid non-finite values\n'
' * auto: Use half float if all values can fit, else use full float\n',
value='float',
values=['float', 'half', 'halfFinite', 'auto'],
exclusive=True,
uid=[0],
),
desc.ChoiceParam(
name='verboseLevel',
label='Verbose Level',
description='Verbosity level (fatal, error, warning, info, debug, trace).',
value='info',
values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
exclusive=True,
uid=[],
),
]

outputs = [
desc.File(
name='outputPanorama',
label='Output Folder',
description='',
value=desc.Node.internalFolder + 'panorama.{outputFileTypeValue}',
uid=[],
),
]
69 changes: 69 additions & 0 deletions meshroom/nodes/aliceVision/PanoramaSeams.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
__version__ = "1.0"

import json
import os

from meshroom.core import desc


class PanoramaSeams(desc.CommandLineNode):
commandLine = 'aliceVision_panoramaSeams {allParams}'
size = desc.DynamicNodeSize('input')

cpu = desc.Level.INTENSIVE
ram = desc.Level.INTENSIVE

documentation = '''
Estimate the seams lines between the inputs to provide an optimal compositing in a further node
'''

inputs = [
desc.File(
name='input',
label='Input SfMData',
description="Input SfMData.",
value='',
uid=[0],
),
desc.File(
name='warpingFolder',
label='Warping Folder',
description="Panorama Warping results",
value='',
uid=[0],
),
desc.IntParam(
name='maxWidth',
label='Max Resolution',
description='Maximal resolution for the panorama seams estimation.',
value=5000,
range=(0, 100000, 1),
uid=[0],
),
desc.BoolParam(
name='useGraphCut',
label='Use Smart Seams',
description='Use a graphcut algorithm to optmize seams for better transitions between images.',
value=True,
uid=[0],
),
desc.ChoiceParam(
name='verboseLevel',
label='Verbose Level',
description='Verbosity level (fatal, error, warning, info, debug, trace).',
value='info',
values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
exclusive=True,
uid=[],
)
]

outputs = [
desc.File(
name='output',
label='Output Labels',
description='',
value=desc.Node.internalFolder + 'labels.exr',
uid=[],
)
]
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/PanoramaWarping.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class PanoramaWarping(desc.CommandLineNode):
name='maxPanoramaWidth',
label='Max Panorama Width',
description='Choose the maximal output panorama width (in pixels). Zero means no limit.',
value=35000,
value=70000,
range=(0, 100000, 1000),
uid=[0],
enabled=lambda node: (node.estimateResolution.value),
Expand Down
Loading

0 comments on commit e82d0cd

Please sign in to comment.