Merge pull request #329 from alicevision/devSfmIntrinsicsInput

[CLI] Add possibility to run pipeline from a .sfm file
This commit is contained in:
Yann Lanthony 2019-01-28 10:54:37 +01:00 committed by GitHub
commit 0c9c2b2424
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 26 deletions

View file

@ -5,6 +5,7 @@ import meshroom
meshroom.setupEnvironment() meshroom.setupEnvironment()
import meshroom.core.graph import meshroom.core.graph
from meshroom.nodes.aliceVision.CameraInit import readSfMData
from meshroom import multiview from meshroom import multiview
parser = argparse.ArgumentParser(description='Launch the full photogrammetry pipeline.') parser = argparse.ArgumentParser(description='Launch the full photogrammetry pipeline.')
@ -43,7 +44,15 @@ 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.photogrammetry(inputFolder=args.input, inputImages=args.inputImages, output=args.output) if args.input and os.path.isfile(args.input):
views, intrinsics = readSfMData(args.input)
# print(views)
# print(intrinsics)
graph = multiview.photogrammetry(inputViewpoints=views, inputIntrinsics=intrinsics, inputImages=args.inputImages, output=args.output)
else:
graph = multiview.photogrammetry(inputFolder=args.input, inputImages=args.inputImages, output=args.output)
graph.findNode('DepthMap_1').downscale.value = args.scale graph.findNode('DepthMap_1').downscale.value = args.scale
if args.save: if args.save:
@ -62,4 +71,3 @@ if args.toNode:
toNodes = graph.findNodes(args.toNode) toNodes = graph.findNodes(args.toNode)
meshroom.core.graph.executeGraph(graph, toNodes=toNodes, forceCompute=args.forceCompute, forceStatus=args.forceStatus) meshroom.core.graph.executeGraph(graph, toNodes=toNodes, forceCompute=args.forceCompute, forceStatus=args.forceStatus)

View file

@ -20,7 +20,7 @@ def findFiles(folder, patterns):
return outFiles return outFiles
def photogrammetry(inputFolder='', inputImages=(), inputViewpoints=(), output=''): def photogrammetry(inputFolder='', inputImages=(), inputViewpoints=(), inputIntrinsics=(), output=''):
""" """
Create a new Graph with a complete photogrammetry pipeline. Create a new Graph with a complete photogrammetry pipeline.
@ -44,6 +44,8 @@ def photogrammetry(inputFolder='', inputImages=(), inputViewpoints=(), output=''
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)
if inputIntrinsics:
cameraInit.intrinsics.extend(inputIntrinsics)
if output: if output:
texturing = mvsNodes[-1] texturing = mvsNodes[-1]

View file

@ -45,6 +45,38 @@ Intrinsic = [
value=False, uid=[0]), value=False, uid=[0]),
] ]
def readSfMData(sfmFile):
""" Read views and intrinsics from a .sfm file
Args:
sfmFile: the .sfm file containing views and intrinsics
Returns:
The views and intrinsics of the .sfm as two separate lists
"""
import io # use io.open for Python2/3 compatibility (allow to specify encoding + errors handling)
# skip decoding errors to avoid potential exceptions due to non utf-8 characters in images metadata
with io.open(sfmFile, 'r', encoding='utf-8', errors='ignore') as f:
data = json.load(f)
intrinsicsKeys = [i.name for i in Intrinsic]
intrinsics = [{k: v for k, v in item.items() if k in intrinsicsKeys} for item in data.get("intrinsics", [])]
for intrinsic in intrinsics:
pp = intrinsic['principalPoint']
intrinsic['principalPoint'] = {}
intrinsic['principalPoint']['x'] = pp[0]
intrinsic['principalPoint']['y'] = pp[1]
# convert empty string distortionParams (i.e: Pinhole model) to empty list
if intrinsic['distortionParams'] == '':
intrinsic['distortionParams'] = list()
viewsKeys = [v.name for v in Viewpoint]
views = [{k: v for k, v in item.items() if k in viewsKeys} for item in data.get("views", [])]
for view in views:
view['metadata'] = json.dumps(view['metadata']) # convert metadata to string
return views, intrinsics
class CameraInit(desc.CommandLineNode): class CameraInit(desc.CommandLineNode):
commandLine = 'aliceVision_cameraInit {allParams} --allowSingleView 1' # don't throw an error if there is only one image commandLine = 'aliceVision_cameraInit {allParams} --allowSingleView 1' # don't throw an error if there is only one image
@ -134,28 +166,7 @@ class CameraInit(desc.CommandLineNode):
# Reload result of aliceVision_cameraInit # Reload result of aliceVision_cameraInit
cameraInitSfM = node.output.value cameraInitSfM = node.output.value
import io # use io.open for Python2/3 compatibility (allow to specify encoding + errors handling) return readSfMData(cameraInitSfM)
# skip decoding errors to avoid potential exceptions due to non utf-8 characters in images metadata
with io.open(cameraInitSfM, 'r', encoding='utf-8', errors='ignore') as f:
data = json.load(f)
intrinsicsKeys = [i.name for i in Intrinsic]
intrinsics = [{k: v for k, v in item.items() if k in intrinsicsKeys} for item in data.get("intrinsics", [])]
for intrinsic in intrinsics:
pp = intrinsic['principalPoint']
intrinsic['principalPoint'] = {}
intrinsic['principalPoint']['x'] = pp[0]
intrinsic['principalPoint']['y'] = pp[1]
# convert empty string distortionParams (i.e: Pinhole model) to empty list
if intrinsic['distortionParams'] == '':
intrinsic['distortionParams'] = list()
# print('intrinsics:', intrinsics)
viewsKeys = [v.name for v in Viewpoint]
views = [{k: v for k, v in item.items() if k in viewsKeys} for item in data.get("views", [])]
for view in views:
view['metadata'] = json.dumps(view['metadata']) # convert metadata to string
# print('views:', views)
return views, intrinsics
except Exception: except Exception:
raise raise
@ -198,4 +209,3 @@ class CameraInit(desc.CommandLineNode):
def processChunk(self, chunk): def processChunk(self, chunk):
self.createViewpointsFile(chunk.node) self.createViewpointsFile(chunk.node)
desc.CommandLineNode.processChunk(self, chunk) desc.CommandLineNode.processChunk(self, chunk)

View file

@ -178,6 +178,15 @@ class StructureFromMotion(desc.CommandLineNode):
uid=[0], uid=[0],
advanced=True, advanced=True,
), ),
desc.BoolParam(
name='lockAllIntrinsics',
label='Force Lock of All Intrinsic Camera Parameters.',
description='Force to keep constant all the intrinsics parameters of the cameras (focal length, \n'
'principal point, distortion if any) during the reconstruction.\n'
'This may be helpful if the input cameras are already fully calibrated.',
value=False,
uid=[0],
),
desc.File( desc.File(
name='initialPairA', name='initialPairA',
label='Initial Pair A', label='Initial Pair A',