Merge pull request #264 from alicevision/dev_keyframeAndRig

New camera rig workflow
This commit is contained in:
Fabien Castan 2018-12-10 15:25:07 +01:00 committed by GitHub
commit 3f4a5b203f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 144 additions and 52 deletions

View file

@ -24,6 +24,16 @@ class ConvertSfMFormat(desc.CommandLineNode):
uid=[0], uid=[0],
group='', # exclude from command line group='', # exclude from command line
), ),
desc.ChoiceParam(
name='describerTypes',
label='Describer Types',
description='Describer types to keep.',
value=['sift'],
values=['sift', 'sift_float', 'sift_upright', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv'],
exclusive=False,
uid=[0],
joinChar=',',
),
desc.BoolParam( desc.BoolParam(
name='views', name='views',
label='Views', label='Views',

View file

@ -1,4 +1,4 @@
__version__ = "1.0" __version__ = "2.0"
import os import os
from meshroom.core import desc from meshroom.core import desc
@ -8,74 +8,126 @@ class KeyframeSelection(desc.CommandLineNode):
commandLine = 'aliceVision_utils_keyframeSelection {allParams}' commandLine = 'aliceVision_utils_keyframeSelection {allParams}'
inputs = [ inputs = [
desc.File( desc.ListAttribute(
elementDesc=desc.File(
name="mediaPath",
label="Media Path",
description="Media path.",
value="",
uid=[0],
),
name='mediaPaths', name='mediaPaths',
label='Media Paths', label='Media Paths',
description='''Input video files or image sequence directories.''', description='Input video files or image sequence directories.',
value='', ),
uid=[0], desc.ListAttribute(
elementDesc=desc.File(
name="brand",
label="Brand",
description="Camera brand.",
value="",
uid=[0],
), ),
desc.IntParam( name="brands",
name='maxNbOutFrame', label="Brands",
label='Max Nb Out Frame', description="Camera brands."
description='''maximum number of output frames (0 = no limit)''', ),
value=1000, desc.ListAttribute(
range=(0, 10000, 1), elementDesc=desc.File(
uid=[], name="model",
label="Model",
description="Camera model.",
value="",
uid=[0],
), ),
name="models",
label="Models",
description="Camera models."
),
desc.ListAttribute(
elementDesc=desc.FloatParam(
name="mmFocal",
label="mmFocal",
description="Focal in mm (will be use if not 0).",
value=0.0,
range=(0.0, 500.0, 1.0),
uid=[0],
),
name="mmFocals",
label="mmFocals",
description="Focals in mm (will be use if not 0)."
),
desc.ListAttribute(
elementDesc=desc.FloatParam(
name="pxFocal",
label="pxFocal",
description="Focal in px (will be use and convert in mm if not 0).",
value=0.0,
range=(0.0, 500.0, 1.0),
uid=[0],
),
name="pxFocals",
label="pxFocals",
description="Focals in px (will be use and convert in mm if not 0)."
),
desc.ListAttribute(
elementDesc=desc.IntParam(
name="frameOffset",
label="Frame Offset",
description="Frame offset.",
value=0,
range=(0, 100.0, 1.0),
uid=[0],
),
name="frameOffsets",
label="Frame Offsets",
description="Frame offsets."
),
desc.File( desc.File(
name='sensorDbPath', name='sensorDbPath',
label='Sensor Db Path', label='Sensor Db Path',
description='''Camera sensor width database path.''', description='''Camera sensor width database path.''',
value=os.environ.get('ALICEVISION_SENSOR_DB', ''), value=os.environ.get('ALICEVISION_SENSOR_DB', ''),
uid=[0], uid=[0],
), ),
desc.File( desc.File(
name='voctreePath', name='voctreePath',
label='Voctree Path', label='Voctree Path',
description='''Vocabulary tree path.''', description='''Vocabulary tree path.''',
value=os.environ.get('ALICEVISION_VOCTREE', ''), value=os.environ.get('ALICEVISION_VOCTREE', ''),
uid=[0], uid=[0],
), ),
desc.StringParam( desc.BoolParam(
name='brands', name='useSparseDistanceSelection',
label='Brands', label='Use Sparse Distance Selection',
description='''Camera brands.''', description='Use sparseDistance selection in order to avoid similar keyframes.',
value='', value=True,
uid=[0], uid=[0],
), ),
desc.StringParam( desc.BoolParam(
name='models', name='useSharpnessSelection',
label='Models', label='Use Sharpness Selection',
description='''Camera models.''', description='Use frame sharpness score for keyframe selection.',
value='', value=True,
uid=[0], uid=[0],
), ),
desc.FloatParam( desc.FloatParam(
name='mmFocals', name='sparseDistMaxScore',
label='Mm Focals', label='Sparse Distance Max Score',
description='''Focals in mm (will be use if not 0).''', description='Maximum number of strong common points between two keyframes.',
value=0.0, value=100.0,
range=(0.0, 500.0, 1.0), range=(1.0, 200.0, 1.0),
uid=[0], uid=[0],
), ),
desc.FloatParam(
name='pxFocals',
label='Px Focals',
description='''Focals in px (will be use and convert in mm if not 0).''',
value=0.0,
range=(0.0, 500.0, 1.0),
uid=[0],
),
desc.ChoiceParam( desc.ChoiceParam(
name='sharpnessPreset', name='sharpnessPreset',
label='Sharpness Preset', label='Sharpness Preset',
description='''Preset for sharpnessSelection : {ultra, high, normal, low, very_low, none}''', description='Preset for sharpnessSelection : {ultra, high, normal, low, very_low, none}',
value='normal', value='normal',
values=['ultra', 'high', 'normal', 'low', 'very_low', 'none'], values=['ultra', 'high', 'normal', 'low', 'very_low', 'none'],
exclusive=True, exclusive=True,
uid=[0], uid=[0],
), ),
desc.IntParam( desc.IntParam(
name='sharpSubset', name='sharpSubset',
label='Sharp Subset', label='Sharp Subset',
@ -83,7 +135,7 @@ class KeyframeSelection(desc.CommandLineNode):
value=4, value=4,
range=(1, 100, 1), range=(1, 100, 1),
uid=[0], uid=[0],
), ),
desc.IntParam( desc.IntParam(
name='minFrameStep', name='minFrameStep',
label='Min Frame Step', label='Min Frame Step',
@ -91,7 +143,7 @@ class KeyframeSelection(desc.CommandLineNode):
value=12, value=12,
range=(1, 100, 1), range=(1, 100, 1),
uid=[0], uid=[0],
), ),
desc.IntParam( desc.IntParam(
name='maxFrameStep', name='maxFrameStep',
label='Max Frame Step', label='Max Frame Step',
@ -99,7 +151,24 @@ class KeyframeSelection(desc.CommandLineNode):
value=36, value=36,
range=(2, 1000, 1), range=(2, 1000, 1),
uid=[0], uid=[0],
), ),
desc.IntParam(
name='maxNbOutFrame',
label='Max Nb Out Frame',
description='''maximum number of output frames (0 = no limit)''',
value=0,
range=(0, 10000, 1),
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 = [ outputs = [
@ -109,6 +178,6 @@ class KeyframeSelection(desc.CommandLineNode):
description='''Output keyframes folder for extracted frames.''', description='''Output keyframes folder for extracted frames.''',
value=desc.Node.internalFolder, value=desc.Node.internalFolder,
uid=[], uid=[],
), ),
] ]

View file

@ -1,4 +1,4 @@
__version__ = "1.0" __version__ = "2.0"
import json import json
import os import os
@ -161,6 +161,13 @@ class StructureFromMotion(desc.CommandLineNode):
value=False, value=False,
uid=[], uid=[],
), ),
desc.BoolParam(
name='useRigsCalibration',
label='Use Rigs Calibration',
description='Enable/Disable rigs calibration.',
value=True,
uid=[0],
),
desc.File( desc.File(
name='initialPairA', name='initialPairA',
label='Initial Pair A', label='Initial Pair A',

View file

@ -444,8 +444,8 @@ class Reconstruction(UIGraph):
Update internal views and poses based on the current SfM node. Update internal views and poses based on the current SfM node.
""" """
if not self._sfm: if not self._sfm:
self._views = [] self._views = dict()
self._poses = [] self._poses = dict()
else: else:
self._views, self._poses = self._sfm.nodeDesc.getViewsAndPoses(self._sfm) self._views, self._poses = self._sfm.nodeDesc.getViewsAndPoses(self._sfm)
self.sfmReportChanged.emit() self.sfmReportChanged.emit()
@ -492,8 +492,9 @@ class Reconstruction(UIGraph):
@Slot(QObject, result=bool) @Slot(QObject, result=bool)
def isReconstructed(self, viewpoint): def isReconstructed(self, viewpoint):
# keys are strings (faster lookup) # fetch up-to-date poseId from sfm result (in case of rigs, poseId might have changed)
return str(viewpoint.poseId.value) in self._poses view = self._views.get(str(viewpoint.poseId.value), None) # keys are strings (faster lookup)
return view.get('poseId', -1) in self._poses if view else False
@Slot(QObject, result=bool) @Slot(QObject, result=bool)
def hasValidIntrinsic(self, viewpoint): def hasValidIntrinsic(self, viewpoint):
@ -512,6 +513,11 @@ class Reconstruction(UIGraph):
self._selectedViewId = viewId self._selectedViewId = viewId
self.selectedViewIdChanged.emit() self.selectedViewIdChanged.emit()
def reconstructedCamerasCount(self):
""" Get the number of reconstructed cameras in the current context. """
return len([v for v in self.getViewpoints() if self.isReconstructed(v)])
selectedViewIdChanged = Signal() selectedViewIdChanged = Signal()
selectedViewId = Property(str, lambda self: self._selectedViewId, setSelectedViewId, notify=selectedViewIdChanged) selectedViewId = Property(str, lambda self: self._selectedViewId, setSelectedViewId, notify=selectedViewIdChanged)
@ -522,7 +528,7 @@ class Reconstruction(UIGraph):
sfmReport = Property(bool, lambda self: len(self._poses) > 0, notify=sfmReportChanged) sfmReport = Property(bool, lambda self: len(self._poses) > 0, notify=sfmReportChanged)
sfmAugmented = Signal(Node, Node) sfmAugmented = Signal(Node, Node)
nbCameras = Property(int, lambda self: len(self._poses), notify=sfmReportChanged) nbCameras = Property(int, reconstructedCamerasCount, notify=sfmReportChanged)
# Signals to propagate high-level messages # Signals to propagate high-level messages
error = Signal(Message) error = Signal(Message)