Skip to content

Commit 59948b2

Browse files
committed
[bin] batch: better flexibility to set InitNodes from command line
Allow to set the input on all InitNodes. Allow to set the input to specific init nodes. Note: Use "=" and "," instead of ":" and ";".
1 parent 772ed15 commit 59948b2

File tree

1 file changed

+47
-56
lines changed

1 file changed

+47
-56
lines changed

bin/meshroom_batch

Lines changed: 47 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,27 @@ import sys
1010
import meshroom.core.graph
1111
from meshroom import setupEnvironment, logStringToPython
1212

13+
def parseInitInputs(inputs: list[str]) -> dict[str, str]:
14+
"""Utility method for parsing the input and inputRecursive arguments.
15+
Args:
16+
inputs: Command line values in format 'nodeName=value' or just 'value' to set it on all init nodes
17+
18+
Returns:
19+
Dict mapping node names (or empty string if it applies to all) to their input values
20+
21+
Raises:
22+
ValueError: If input format is invalid
23+
"""
24+
mapInputs = {}
25+
for inp in inputs:
26+
# Stop after the first occurrence
27+
inputGroup = inp.split('=', 1)
28+
nodeName = inputGroup[0] if len(inputGroup) == 2 else ""
29+
nodeInputs = inputGroup[-1].split(',')
30+
mapInputs[nodeName] = [os.path.abspath(path) for path in nodeInputs]
31+
return mapInputs
32+
33+
1334
setupEnvironment()
1435

1536
meshroom.core.initPipelines()
@@ -40,13 +61,13 @@ Additional Resources:
4061

4162
general_group = parser.add_argument_group('General Options')
4263
general_group.add_argument(
43-
'-i', '--input', metavar='NODEINSTANCE:"SFM/FOLDERS/IMAGES;..."', type=str, nargs='*',
64+
'-i', '--input', metavar='NODEINSTANCE="SFM/FOLDERS/IMAGES,..."', type=str, nargs='*',
4465
default=[],
4566
help='Input folder containing images or folders of images or file (.sfm or .json) '
4667
'with images paths and optionally predefined camera intrinsics.')
4768

4869
general_group.add_argument(
49-
'-I', '--inputRecursive', metavar='NODEINSTANCE:"FOLDERS/IMAGES;..."', type=str, nargs='*',
70+
'-I', '--inputRecursive', metavar='NODEINSTANCE="FOLDERS/IMAGES,..."', type=str, nargs='*',
5071
default=[],
5172
help='Input folders containing all images recursively.')
5273

@@ -156,60 +177,30 @@ with meshroom.core.graph.GraphModification(graph):
156177
# custom pipeline
157178
graph.initFromTemplate(args.pipeline, copyOutputs=True if args.output else False)
158179

159-
def parseInputs(inputs, uniqueInitNode):
160-
"""Utility method for parsing the input and inputRecursive arguments."""
161-
mapInputs = {}
162-
for inp in inputs:
163-
# Stop after the first occurrence to handle multiple input paths on Windows platforms
164-
inputGroup = inp.split(':', 1)
165-
nodeName = None
166-
if len(inputGroup) == 1 and uniqueInitNode:
167-
nodeName = uniqueInitNode.getName()
168-
elif len(inputGroup) == 2:
169-
# If inputGroup[0] is a valid node name, use it as such.
170-
if (inputGroup[0] in graph.toDict().keys()):
171-
nodeName = inputGroup[0]
172-
# Otherwise, the platform might be Windows and inputGroup[0] is part of the input path:
173-
# in that case, we should behave as if len(inputGroup) == 1, use the uniqueInitNode's name
174-
# and re-join the path together.
175-
elif uniqueInitNode:
176-
nodeName = uniqueInitNode.getName()
177-
inputGroup = [":".join(inputGroup)]
178-
else:
179-
print('Syntax error in input argument')
180-
# If a node name has been provided and the platform is Windows, the length of inputGroup might be
181-
# 3: first the node name, then the first path of the input path, then the rest of the input path.
182-
# The input path should also be re-joined here.
183-
elif len(inputGroup) == 3:
184-
nodeName = inputGroup[0]
185-
inputGroup[1] = ":".join(inputGroup[1:])
186-
inputGroup.pop(-1)
187-
else:
188-
print('Syntax error in input argument')
189-
sys.exit(1)
190-
nodeInputs = inputGroup[-1].split(';')
191-
mapInputs[nodeName] = [os.path.abspath(path) for path in nodeInputs]
192-
return mapInputs
193-
194-
# get init nodes
195-
initNodes = graph.findInitNodes()
196-
uniqueInitNode = initNodes[0] if (len(initNodes) == 1) else None
197-
198-
# parse inputs for each init node
199-
mapInput = parseInputs(args.input, uniqueInitNode)
200-
201-
# parse recursive inputs for each init node
202-
mapInputRecursive = parseInputs(args.inputRecursive, uniqueInitNode)
203-
204-
# feed inputs and recursive inputs to init nodes
205-
for initNode in initNodes:
206-
nodeName = initNode.getName()
207-
inp = mapInput.get(nodeName)
208-
inpRec = mapInputRecursive.get(nodeName)
209-
if not inp and not inpRec:
210-
print(f'Nothing to compute for node {nodeName}.')
211-
sys.exit(1)
212-
initNode.nodeDesc.initialize(initNode, inp, inpRec)
180+
if args.input:
181+
# get init nodes
182+
initNodes = graph.findInitNodes()
183+
initNodesNames = [n.getName() for n in initNodes]
184+
185+
# parse inputs for each init node
186+
mapInput = parseInitInputs(args.input)
187+
188+
# parse recursive inputs for each init node
189+
mapInputRecursive = parseInitInputs(args.inputRecursive)
190+
191+
# check that input nodes exist in the pipeline template
192+
for nodeName in mapInput.keys() | mapInputRecursive.keys():
193+
if nodeName and nodeName not in initNodesNames:
194+
raise RuntimeError(f"Failed to find the Init Node '{nodeName}' in your pipeline.\nAvailable Init Nodes: {initNodesNames}")
195+
196+
# feed inputs (recursive and non-recursive paths) to corresponding init nodes
197+
for initNode in initNodes:
198+
nodeName = initNode.getName()
199+
# Retrieve input per node and inputs for all init node types
200+
input = mapInput.get(nodeName, []) + mapInput.get("", [])
201+
# Retrieve recursive inputs
202+
inputRec = mapInputRecursive.get(nodeName, []) + mapInputRecursive.get("", [])
203+
initNode.nodeDesc.initialize(initNode, input, inputRec)
213204

214205
if not graph.canComputeLeaves:
215206
raise RuntimeError("Graph cannot be computed. Check for compatibility issues.")

0 commit comments

Comments
 (0)