mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-21 21:16:29 +02:00
[multiview] split pipeline creation into several functions
* add 'sfmPipeline', 'mvsPipeline' and 'photogrammetryPipeline' instantiating nodes in an existing graph * rename main function (creating a new Graph) 'photogrammetry' + create a Publish node if 'output' is specified
This commit is contained in:
parent
8ed0d0a7a2
commit
b596bdffca
4 changed files with 121 additions and 43 deletions
|
@ -43,7 +43,7 @@ if not args.input and not args.inputImages:
|
||||||
print('Nothing to compute. You need to set --input or --inputImages.')
|
print('Nothing to compute. You need to set --input or --inputImages.')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
graph = multiview.photogrammetryPipeline(output=args.output, inputFolder=args.input, inputImages=args.inputImages)
|
graph = multiview.photogrammetry(inputFolder=args.input, inputImages=args.inputImages, output=args.output)
|
||||||
graph.findNode('PrepareDenseScene').scale.value = args.scale
|
graph.findNode('PrepareDenseScene').scale.value = args.scale
|
||||||
|
|
||||||
if args.save:
|
if args.save:
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from .core.graph import Graph, GraphModification
|
from meshroom.core.graph import Graph, GraphModification
|
||||||
|
|
||||||
|
|
||||||
def findFiles(folder, patterns):
|
def findFiles(folder, patterns):
|
||||||
|
@ -17,11 +17,23 @@ def findFiles(folder, patterns):
|
||||||
return outFiles
|
return outFiles
|
||||||
|
|
||||||
|
|
||||||
def photogrammetryPipeline(output='', inputFolder='', inputImages=[], inputViewpoints=[]):
|
def photogrammetry(inputFolder='', inputImages=(), inputViewpoints=(), output=''):
|
||||||
# type: () -> Graph
|
"""
|
||||||
graph = Graph('pipeline')
|
Create a new Graph with a complete photogrammetry pipeline.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
inputFolder (str, optional): folder containing image files
|
||||||
|
inputImages (list of str, optional): list of image file paths
|
||||||
|
inputViewpoints (list of Viewpoint, optional): list of Viewpoints
|
||||||
|
output (str, optional): the path to export reconstructed model to
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Graph: the created graph
|
||||||
|
"""
|
||||||
|
graph = Graph('Photogrammetry')
|
||||||
with GraphModification(graph):
|
with GraphModification(graph):
|
||||||
cameraInit = graph.addNewNode('CameraInit')
|
sfmNodes, mvsNodes = photogrammetryPipeline(graph)
|
||||||
|
cameraInit = sfmNodes[0]
|
||||||
if inputFolder:
|
if inputFolder:
|
||||||
images = findFiles(inputFolder, ['*.jpg', '*.png'])
|
images = findFiles(inputFolder, ['*.jpg', '*.png'])
|
||||||
cameraInit.viewpoints.extend([{'path': image} for image in images])
|
cameraInit.viewpoints.extend([{'path': image} for image in images])
|
||||||
|
@ -29,35 +41,101 @@ def photogrammetryPipeline(output='', inputFolder='', inputImages=[], inputViewp
|
||||||
cameraInit.viewpoints.extend([{'path': image} for image in inputImages])
|
cameraInit.viewpoints.extend([{'path': image} for image in inputImages])
|
||||||
if inputViewpoints:
|
if inputViewpoints:
|
||||||
cameraInit.viewpoints.extend(inputViewpoints)
|
cameraInit.viewpoints.extend(inputViewpoints)
|
||||||
featureExtraction = graph.addNewNode('FeatureExtraction',
|
|
||||||
input=cameraInit.output)
|
if output:
|
||||||
imageMatching = graph.addNewNode('ImageMatching',
|
texturing = mvsNodes[-1]
|
||||||
input=featureExtraction.input,
|
graph.addNewNode('Publish', output=output, inputFiles=[texturing.outputMesh,
|
||||||
featuresFolder=featureExtraction.output,
|
texturing.outputMaterial,
|
||||||
)
|
texturing.outputTextures])
|
||||||
featureMatching = graph.addNewNode('FeatureMatching',
|
|
||||||
input=imageMatching.input,
|
|
||||||
featuresFolder=imageMatching.featuresFolder,
|
|
||||||
imagePairsList=imageMatching.output)
|
|
||||||
structureFromMotion = graph.addNewNode('StructureFromMotion',
|
|
||||||
input=featureMatching.input,
|
|
||||||
featuresFolder=featureMatching.featuresFolder,
|
|
||||||
matchesFolder=featureMatching.output)
|
|
||||||
prepareDenseScene = graph.addNewNode('PrepareDenseScene',
|
|
||||||
input=structureFromMotion.output)
|
|
||||||
cameraConnection = graph.addNewNode('CameraConnection',
|
|
||||||
ini=prepareDenseScene.ini)
|
|
||||||
depthMap = graph.addNewNode('DepthMap',
|
|
||||||
ini=cameraConnection.ini)
|
|
||||||
depthMapFilter = graph.addNewNode('DepthMapFilter',
|
|
||||||
depthMapFolder=depthMap.output,
|
|
||||||
ini=depthMap.ini)
|
|
||||||
meshing = graph.addNewNode('Meshing',
|
|
||||||
depthMapFolder=depthMapFilter.depthMapFolder,
|
|
||||||
depthMapFilterFolder=depthMapFilter.output,
|
|
||||||
ini=depthMapFilter.ini)
|
|
||||||
texturing = graph.addNewNode('Texturing',
|
|
||||||
ini=meshing.ini,
|
|
||||||
inputDenseReconstruction=meshing.outputDenseReconstruction)
|
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
|
|
||||||
|
def photogrammetryPipeline(graph):
|
||||||
|
"""
|
||||||
|
Instantiate a complete photogrammetry pipeline inside 'graph'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
graph (Graph/UIGraph): the graph in which nodes should be instantiated
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list of Node: the created nodes
|
||||||
|
"""
|
||||||
|
sfmNodes = sfmPipeline(graph)
|
||||||
|
mvsNodes = mvsPipeline(graph, sfmNodes[-1])
|
||||||
|
|
||||||
|
return sfmNodes, mvsNodes
|
||||||
|
|
||||||
|
|
||||||
|
def sfmPipeline(graph):
|
||||||
|
"""
|
||||||
|
Instantiate a SfM pipeline inside 'graph'.
|
||||||
|
Args:
|
||||||
|
graph (Graph/UIGraph): the graph in which nodes should be instantiated
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list of Node: the created nodes
|
||||||
|
"""
|
||||||
|
cameraInit = graph.addNewNode('CameraInit')
|
||||||
|
|
||||||
|
featureExtraction = graph.addNewNode('FeatureExtraction',
|
||||||
|
input=cameraInit.output)
|
||||||
|
imageMatching = graph.addNewNode('ImageMatching',
|
||||||
|
input=featureExtraction.input,
|
||||||
|
featuresFolder=featureExtraction.output,
|
||||||
|
)
|
||||||
|
featureMatching = graph.addNewNode('FeatureMatching',
|
||||||
|
input=imageMatching.input,
|
||||||
|
featuresFolder=imageMatching.featuresFolder,
|
||||||
|
imagePairsList=imageMatching.output)
|
||||||
|
structureFromMotion = graph.addNewNode('StructureFromMotion',
|
||||||
|
input=featureMatching.input,
|
||||||
|
featuresFolder=featureMatching.featuresFolder,
|
||||||
|
matchesFolder=featureMatching.output)
|
||||||
|
return [
|
||||||
|
cameraInit,
|
||||||
|
featureExtraction,
|
||||||
|
imageMatching,
|
||||||
|
featureMatching,
|
||||||
|
structureFromMotion
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def mvsPipeline(graph, sfm=None):
|
||||||
|
"""
|
||||||
|
Instantiate a MVS pipeline inside 'graph'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
graph (Graph/UIGraph): the graph in which nodes should be instantiated
|
||||||
|
sfm (Node, optional): if specified, connect the MVS pipeline to this StructureFromMotion node
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list of Node: the created nodes
|
||||||
|
"""
|
||||||
|
if sfm and not sfm.nodeType == "StructureFromMotion":
|
||||||
|
raise ValueError("Invalid node type. Expected StructureFromMotion, got {}.".format(sfm.nodeType))
|
||||||
|
|
||||||
|
prepareDenseScene = graph.addNewNode('PrepareDenseScene',
|
||||||
|
input=sfm.output if sfm else "")
|
||||||
|
cameraConnection = graph.addNewNode('CameraConnection',
|
||||||
|
ini=prepareDenseScene.ini)
|
||||||
|
depthMap = graph.addNewNode('DepthMap',
|
||||||
|
ini=cameraConnection.ini)
|
||||||
|
depthMapFilter = graph.addNewNode('DepthMapFilter',
|
||||||
|
depthMapFolder=depthMap.output,
|
||||||
|
ini=depthMap.ini)
|
||||||
|
meshing = graph.addNewNode('Meshing',
|
||||||
|
depthMapFolder=depthMapFilter.depthMapFolder,
|
||||||
|
depthMapFilterFolder=depthMapFilter.output,
|
||||||
|
ini=depthMapFilter.ini)
|
||||||
|
texturing = graph.addNewNode('Texturing',
|
||||||
|
ini=meshing.ini,
|
||||||
|
inputDenseReconstruction=meshing.outputDenseReconstruction)
|
||||||
|
|
||||||
|
return [
|
||||||
|
prepareDenseScene,
|
||||||
|
cameraConnection,
|
||||||
|
depthMap,
|
||||||
|
depthMapFilter,
|
||||||
|
meshing,
|
||||||
|
texturing
|
||||||
|
]
|
||||||
|
|
|
@ -170,7 +170,7 @@ class Reconstruction(UIGraph):
|
||||||
@Slot()
|
@Slot()
|
||||||
def new(self):
|
def new(self):
|
||||||
""" Create a new photogrammetry pipeline. """
|
""" Create a new photogrammetry pipeline. """
|
||||||
self.setGraph(multiview.photogrammetryPipeline())
|
self.setGraph(multiview.photogrammetry())
|
||||||
|
|
||||||
def onGraphChanged(self):
|
def onGraphChanged(self):
|
||||||
""" React to the change of the internal graph. """
|
""" React to the change of the internal graph. """
|
||||||
|
|
|
@ -4,15 +4,15 @@ import meshroom.multiview
|
||||||
|
|
||||||
|
|
||||||
def test_multiviewPipeline():
|
def test_multiviewPipeline():
|
||||||
graph1 = meshroom.multiview.photogrammetryPipeline(inputImages=['/non/existing/fileA'])
|
graph1 = meshroom.multiview.photogrammetry(inputImages=['/non/existing/fileA'])
|
||||||
graph2 = meshroom.multiview.photogrammetryPipeline(inputImages=[])
|
graph2 = meshroom.multiview.photogrammetry(inputImages=[])
|
||||||
graph2b = meshroom.multiview.photogrammetryPipeline(inputImages=[])
|
graph2b = meshroom.multiview.photogrammetry(inputImages=[])
|
||||||
graph3 = meshroom.multiview.photogrammetryPipeline(inputImages=['/non/existing/file1', '/non/existing/file2'])
|
graph3 = meshroom.multiview.photogrammetry(inputImages=['/non/existing/file1', '/non/existing/file2'])
|
||||||
graph4 = meshroom.multiview.photogrammetryPipeline(inputViewpoints=[
|
graph4 = meshroom.multiview.photogrammetry(inputViewpoints=[
|
||||||
{'path': '/non/existing/file1', 'intrinsicId': 50},
|
{'path': '/non/existing/file1', 'intrinsicId': 50},
|
||||||
{'path': '/non/existing/file2', 'intrinsicId': 55}
|
{'path': '/non/existing/file2', 'intrinsicId': 55}
|
||||||
])
|
])
|
||||||
graph4b = meshroom.multiview.photogrammetryPipeline(inputViewpoints=[
|
graph4b = meshroom.multiview.photogrammetry(inputViewpoints=[
|
||||||
{'path': '/non/existing/file1', 'intrinsicId': 50},
|
{'path': '/non/existing/file1', 'intrinsicId': 50},
|
||||||
{'path': '/non/existing/file2', 'intrinsicId': 55}
|
{'path': '/non/existing/file2', 'intrinsicId': 55}
|
||||||
])
|
])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue