[reconstruction] retrieve and expose solved intrinsics

* [nodes] SfM: make more generic method to get SfM results and return solved intrinsics in addition to views and poses
* [reconstruction] store and expose solved intrinsics by viewpoints
This commit is contained in:
Yann Lanthony 2019-09-10 18:23:35 +02:00
parent bf912cd353
commit c7a55e56b7
No known key found for this signature in database
GPG key ID: 519FAE6DF7A70642
2 changed files with 27 additions and 11 deletions

View file

@ -267,19 +267,20 @@ class StructureFromMotion(desc.CommandLineNode):
] ]
@staticmethod @staticmethod
def getViewsAndPoses(node): def getResults(node):
""" """
Parse SfM result and return views and poses as two dict with viewId and poseId as keys. Parse SfM result and return views, poses and intrinsics as three dicts with viewId, poseId and intrinsicId as keys.
""" """
reportFile = node.outputViewsAndPoses.value reportFile = node.outputViewsAndPoses.value
if not os.path.exists(reportFile): if not os.path.exists(reportFile):
return {}, {} return {}, {}, {}
with open(reportFile) as jsonFile: with open(reportFile) as jsonFile:
report = json.load(jsonFile) report = json.load(jsonFile)
views = dict() views = dict()
poses = dict() poses = dict()
intrinsics = dict()
for view in report['views']: for view in report['views']:
views[view['viewId']] = view views[view['viewId']] = view
@ -287,4 +288,7 @@ class StructureFromMotion(desc.CommandLineNode):
for pose in report['poses']: for pose in report['poses']:
poses[pose['poseId']] = pose['pose'] poses[pose['poseId']] = pose['pose']
return views, poses for intrinsic in report['intrinsics']:
intrinsics[intrinsic['intrinsicId']] = intrinsic
return views, poses, intrinsics

View file

@ -178,6 +178,7 @@ class Reconstruction(UIGraph):
self._sfm = None self._sfm = None
self._views = None self._views = None
self._poses = None self._poses = None
self._solvedIntrinsics = None
self._selectedViewId = None self._selectedViewId = None
self._liveSfmManager = LiveSfmManager(self) self._liveSfmManager = LiveSfmManager(self)
@ -465,15 +466,16 @@ class Reconstruction(UIGraph):
buildingIntrinsics = Property(bool, lambda self: self._buildingIntrinsics, notify=buildingIntrinsicsChanged) buildingIntrinsics = Property(bool, lambda self: self._buildingIntrinsics, notify=buildingIntrinsicsChanged)
liveSfmManager = Property(QObject, lambda self: self._liveSfmManager, constant=True) liveSfmManager = Property(QObject, lambda self: self._liveSfmManager, constant=True)
def updateViewsAndPoses(self): def updateSfMResults(self):
""" """
Update internal views and poses based on the current SfM node. Update internal views, poses and solved intrinsics based on the current SfM node.
""" """
if not self._sfm: if not self._sfm:
self._views = dict() self._views = dict()
self._poses = dict() self._poses = dict()
self._solvedIntrinsics = dict()
else: else:
self._views, self._poses = self._sfm.nodeDesc.getViewsAndPoses(self._sfm) self._views, self._poses, self._solvedIntrinsics = self._sfm.nodeDesc.getResults(self._sfm)
self.sfmReportChanged.emit() self.sfmReportChanged.emit()
def getSfm(self): def getSfm(self):
@ -490,15 +492,15 @@ class Reconstruction(UIGraph):
See Also: setSfm See Also: setSfm
""" """
self._sfm = node self._sfm = node
# Update views and poses and do so each time # Update sfm results and do so each time
# the status of the SfM node's only chunk changes # the status of the SfM node's only chunk changes
self.updateViewsAndPoses() self.updateSfMResults()
if self._sfm: if self._sfm:
# when destroyed, directly use '_setSfm' to bypass # when destroyed, directly use '_setSfm' to bypass
# disconnection step in 'setSfm' (at this point, 'self._sfm' underlying object # disconnection step in 'setSfm' (at this point, 'self._sfm' underlying object
# has been destroyed and can't be evaluated anymore) # has been destroyed and can't be evaluated anymore)
self._sfm.destroyed.connect(self._unsetSfm) self._sfm.destroyed.connect(self._unsetSfm)
self._sfm.chunks[0].statusChanged.connect(self.updateViewsAndPoses) self._sfm.chunks[0].statusChanged.connect(self.updateSfMResults)
self.sfmChanged.emit() self.sfmChanged.emit()
def setSfm(self, node): def setSfm(self, node):
@ -507,7 +509,7 @@ class Reconstruction(UIGraph):
""" """
# disconnect from previous SfM node if any # disconnect from previous SfM node if any
if self._sfm: if self._sfm:
self._sfm.chunks[0].statusChanged.disconnect(self.updateViewsAndPoses) self._sfm.chunks[0].statusChanged.disconnect(self.updateSfMResults)
self._sfm.destroyed.disconnect(self._unsetSfm) self._sfm.destroyed.disconnect(self._unsetSfm)
self._setSfm(node) self._setSfm(node)
@ -564,6 +566,16 @@ class Reconstruction(UIGraph):
""" Get the number of reconstructed cameras in the current context. """ """ Get the number of reconstructed cameras in the current context. """
return len([v for v in self.getViewpoints() if self.isReconstructed(v)]) return len([v for v in self.getViewpoints() if self.isReconstructed(v)])
@Slot(QObject, result="QVariant")
def getSolvedIntrinsics(self, viewpoint):
""" Return viewpoint's solved intrinsics if it has been reconstructed, None otherwise.
Args:
viewpoint: the viewpoint object to instrinsics for.
"""
if not viewpoint:
return None
return self._solvedIntrinsics.get(str(viewpoint.intrinsicId.value), None)
selectedViewIdChanged = Signal() selectedViewIdChanged = Signal()
selectedViewId = Property(str, lambda self: self._selectedViewId, setSelectedViewId, notify=selectedViewIdChanged) selectedViewId = Property(str, lambda self: self._selectedViewId, setSelectedViewId, notify=selectedViewIdChanged)