mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-21 21:16:29 +02:00
[ui] ImageGallery: allow to visualize the list of HDR images created by LDRToHDR
Conflicts: meshroom/ui/reconstruction.py
This commit is contained in:
parent
85dd992927
commit
19d2f90554
5 changed files with 85 additions and 12 deletions
|
@ -606,6 +606,10 @@ class BaseNode(BaseObject):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@Slot(result=bool)
|
||||||
|
def isComputed(self):
|
||||||
|
return self.hasStatus(Status.SUCCESS)
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def clearData(self):
|
def clearData(self):
|
||||||
""" Delete this Node internal folder.
|
""" Delete this Node internal folder.
|
||||||
|
|
|
@ -160,6 +160,9 @@ class CameraInit(desc.CommandLineNode):
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def readSfMData(self, sfmFile):
|
||||||
|
return readSfMData(sfmFile)
|
||||||
|
|
||||||
def buildIntrinsics(self, node, additionalViews=()):
|
def buildIntrinsics(self, node, additionalViews=()):
|
||||||
""" Build intrinsics from node current views and optional additional views
|
""" Build intrinsics from node current views and optional additional views
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,13 @@ Panel {
|
||||||
|
|
||||||
property variant cameraInits
|
property variant cameraInits
|
||||||
property variant cameraInit
|
property variant cameraInit
|
||||||
|
property variant hdrCameraInit
|
||||||
readonly property alias currentItem: grid.currentItem
|
readonly property alias currentItem: grid.currentItem
|
||||||
readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : ""
|
readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : ""
|
||||||
readonly property var currentItemMetadata: grid.currentItem ? grid.currentItem.metadata : undefined
|
readonly property var currentItemMetadata: grid.currentItem ? grid.currentItem.metadata : undefined
|
||||||
property int defaultCellSize: 160
|
property int defaultCellSize: 160
|
||||||
property int currentIndex: 0
|
property int currentIndex: 0
|
||||||
property bool readOnly: false
|
property bool readOnly: false
|
||||||
readonly property variant viewpoints: cameraInit.attribute('viewpoints').value
|
|
||||||
|
|
||||||
signal removeImageRequest(var attribute)
|
signal removeImageRequest(var attribute)
|
||||||
signal filesDropped(var drop, var augmentSfm)
|
signal filesDropped(var drop, var augmentSfm)
|
||||||
|
@ -30,6 +30,17 @@ Panel {
|
||||||
title: "Images"
|
title: "Images"
|
||||||
implicitWidth: (root.defaultCellSize + 2) * 2
|
implicitWidth: (root.defaultCellSize + 2) * 2
|
||||||
|
|
||||||
|
function changeCurrentIndex(newIndex) {
|
||||||
|
_reconstruction.cameraInitIndex = newIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: m
|
||||||
|
property variant currentCameraInit: displayHDR.checked ? _reconstruction.hdrCameraInit : root.cameraInit
|
||||||
|
property variant viewpoints: currentCameraInit ? currentCameraInit.attribute('viewpoints').value : undefined
|
||||||
|
property bool readOnly: root.readOnly || displayHDR.checked
|
||||||
|
}
|
||||||
|
|
||||||
headerBar: RowLayout {
|
headerBar: RowLayout {
|
||||||
MaterialToolButton {
|
MaterialToolButton {
|
||||||
text: MaterialIcons.more_vert
|
text: MaterialIcons.more_vert
|
||||||
|
@ -99,7 +110,7 @@ Panel {
|
||||||
|
|
||||||
model: SortFilterDelegateModel {
|
model: SortFilterDelegateModel {
|
||||||
id: sortedModel
|
id: sortedModel
|
||||||
model: _reconstruction.viewpoints
|
model: m.viewpoints
|
||||||
sortRole: "path"
|
sortRole: "path"
|
||||||
// TODO: provide filtering on reconstruction status
|
// TODO: provide filtering on reconstruction status
|
||||||
// filterRole: _reconstruction.sfmReport ? "reconstructed" : ""
|
// filterRole: _reconstruction.sfmReport ? "reconstructed" : ""
|
||||||
|
@ -123,7 +134,7 @@ Panel {
|
||||||
viewpoint: object.value
|
viewpoint: object.value
|
||||||
width: grid.cellWidth
|
width: grid.cellWidth
|
||||||
height: grid.cellHeight
|
height: grid.cellHeight
|
||||||
readOnly: root.readOnly
|
readOnly: m.readOnly
|
||||||
displayViewId: displayViewIdsAction.checked
|
displayViewId: displayViewIdsAction.checked
|
||||||
|
|
||||||
isCurrentItem: GridView.isCurrentItem
|
isCurrentItem: GridView.isCurrentItem
|
||||||
|
@ -202,9 +213,9 @@ Panel {
|
||||||
{
|
{
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
if(event.key == Qt.Key_Right)
|
if(event.key == Qt.Key_Right)
|
||||||
root.currentIndex = Math.min(root.cameraInits.count - 1, root.currentIndex + 1)
|
root.changeCurrentIndex(Math.min(root.cameraInits.count - 1, root.currentIndex + 1))
|
||||||
else if(event.key == Qt.Key_Left)
|
else if(event.key == Qt.Key_Left)
|
||||||
root.currentIndex = Math.max(0, root.currentIndex - 1)
|
root.changeCurrentIndex(Math.max(0, root.currentIndex - 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +238,7 @@ Panel {
|
||||||
DropArea {
|
DropArea {
|
||||||
id: dropArea
|
id: dropArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: !root.readOnly
|
enabled: !m.readOnly
|
||||||
keys: ["text/uri-list"]
|
keys: ["text/uri-list"]
|
||||||
// TODO: onEntered: call specific method to filter files based on extension
|
// TODO: onEntered: call specific method to filter files based on extension
|
||||||
onDropped: {
|
onDropped: {
|
||||||
|
@ -274,7 +285,7 @@ Panel {
|
||||||
text: "Augment Reconstruction"
|
text: "Augment Reconstruction"
|
||||||
font.bold: true
|
font.bold: true
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
visible: viewpoints.count > 0
|
visible: m.viewpoints ? m.viewpoints.count > 0 : false
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: parent.hovered ? palette.highlight : palette.window
|
color: parent.hovered ? palette.highlight : palette.window
|
||||||
opacity: 0.8
|
opacity: 0.8
|
||||||
|
@ -299,14 +310,13 @@ Panel {
|
||||||
enabled: nodesCB.currentIndex > 0
|
enabled: nodesCB.currentIndex > 0
|
||||||
onClicked: nodesCB.decrementCurrentIndex()
|
onClicked: nodesCB.decrementCurrentIndex()
|
||||||
}
|
}
|
||||||
Label { text: "Group " }
|
Label { id: groupLabel; text: "Group " }
|
||||||
ComboBox {
|
ComboBox {
|
||||||
id: nodesCB
|
id: nodesCB
|
||||||
model: root.cameraInits.count
|
model: root.cameraInits.count
|
||||||
implicitWidth: 40
|
implicitWidth: 40
|
||||||
currentIndex: root.currentIndex
|
currentIndex: root.currentIndex
|
||||||
onActivated: root.currentIndex = currentIndex
|
onActivated: root.changeCurrentIndex(currentIndex)
|
||||||
|
|
||||||
}
|
}
|
||||||
Label { text: "/ " + (root.cameraInits.count - 1) }
|
Label { text: "/ " + (root.cameraInits.count - 1) }
|
||||||
ToolButton {
|
ToolButton {
|
||||||
|
@ -337,6 +347,26 @@ Panel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaterialToolButton {
|
||||||
|
id: displayHDR
|
||||||
|
font.pointSize: 20
|
||||||
|
padding: 0
|
||||||
|
anchors.margins: 0
|
||||||
|
implicitHeight: 14
|
||||||
|
ToolTip.text: "Visualize HDR images"
|
||||||
|
text: MaterialIcons.hdr_on
|
||||||
|
visible: _reconstruction.ldr2hdr
|
||||||
|
enabled: visible && _reconstruction.ldr2hdr.isComputed()
|
||||||
|
onEnabledChanged: {
|
||||||
|
// Reset the toggle to avoid getting stuck
|
||||||
|
// with the HDR node checked but disabled.
|
||||||
|
checked = false;
|
||||||
|
}
|
||||||
|
checkable: true
|
||||||
|
checked: false
|
||||||
|
onClicked: { _reconstruction.setupLDRToHDRCameraInit(); }
|
||||||
|
}
|
||||||
|
|
||||||
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
||||||
|
|
||||||
// Thumbnail size icon and slider
|
// Thumbnail size icon and slider
|
||||||
|
|
|
@ -64,9 +64,9 @@ Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
readOnly: root.readOnly
|
readOnly: root.readOnly
|
||||||
cameraInits: root.cameraInits
|
cameraInits: root.cameraInits
|
||||||
cameraInit: _reconstruction.cameraInit
|
cameraInit: reconstruction.cameraInit
|
||||||
|
hdrCameraInit: reconstruction.hdrCameraInit
|
||||||
currentIndex: reconstruction.cameraInitIndex
|
currentIndex: reconstruction.cameraInitIndex
|
||||||
onCurrentIndexChanged: reconstruction.cameraInitIndex = currentIndex
|
|
||||||
onRemoveImageRequest: reconstruction.removeAttribute(attribute)
|
onRemoveImageRequest: reconstruction.removeAttribute(attribute)
|
||||||
onFilesDropped: reconstruction.handleFilesDrop(drop, augmentSfm ? null : cameraInit)
|
onFilesDropped: reconstruction.handleFilesDrop(drop, augmentSfm ? null : cameraInit)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ from threading import Thread
|
||||||
from PySide2.QtCore import QObject, Slot, Property, Signal, QUrl, QSizeF
|
from PySide2.QtCore import QObject, Slot, Property, Signal, QUrl, QSizeF
|
||||||
from PySide2.QtGui import QMatrix4x4, QMatrix3x3, QQuaternion, QVector3D, QVector2D
|
from PySide2.QtGui import QMatrix4x4, QMatrix3x3, QQuaternion, QVector3D, QVector2D
|
||||||
|
|
||||||
|
import meshroom.core
|
||||||
from meshroom import multiview
|
from meshroom import multiview
|
||||||
from meshroom.common.qt import QObjectListModel
|
from meshroom.common.qt import QObjectListModel
|
||||||
from meshroom.core import Version
|
from meshroom.core import Version
|
||||||
|
@ -369,6 +370,8 @@ class Reconstruction(UIGraph):
|
||||||
self._buildingIntrinsics = False
|
self._buildingIntrinsics = False
|
||||||
self.intrinsicsBuilt.connect(self.onIntrinsicsAvailable)
|
self.intrinsicsBuilt.connect(self.onIntrinsicsAvailable)
|
||||||
|
|
||||||
|
self._hdrCameraInit = None
|
||||||
|
|
||||||
self.importImagesFailed.connect(self.onImportImagesFailed)
|
self.importImagesFailed.connect(self.onImportImagesFailed)
|
||||||
|
|
||||||
# - Feature Extraction
|
# - Feature Extraction
|
||||||
|
@ -394,6 +397,10 @@ class Reconstruction(UIGraph):
|
||||||
# - Texturing
|
# - Texturing
|
||||||
self._texturing = None
|
self._texturing = None
|
||||||
|
|
||||||
|
# - LDR2HDR
|
||||||
|
self._ldr2hdr = None
|
||||||
|
self.cameraInitChanged.connect(self.updateLdr2hdrNode)
|
||||||
|
|
||||||
# react to internal graph changes to update those variables
|
# react to internal graph changes to update those variables
|
||||||
self.graphChanged.connect(self.onGraphChanged)
|
self.graphChanged.connect(self.onGraphChanged)
|
||||||
|
|
||||||
|
@ -449,6 +456,8 @@ class Reconstruction(UIGraph):
|
||||||
self.prepareDenseScene = None
|
self.prepareDenseScene = None
|
||||||
self.depthMap = None
|
self.depthMap = None
|
||||||
self.texturing = None
|
self.texturing = None
|
||||||
|
self.ldr2hdr = None
|
||||||
|
self.hdrCameraInit = None
|
||||||
self.updateCameraInits()
|
self.updateCameraInits()
|
||||||
if not self._graph:
|
if not self._graph:
|
||||||
return
|
return
|
||||||
|
@ -478,6 +487,10 @@ class Reconstruction(UIGraph):
|
||||||
|
|
||||||
def getCameraInitIndex(self):
|
def getCameraInitIndex(self):
|
||||||
if not self._cameraInit:
|
if not self._cameraInit:
|
||||||
|
# No CameraInit node
|
||||||
|
return -1
|
||||||
|
if not self._cameraInit.graph:
|
||||||
|
# The CameraInit node is a temporary one not attached to a graph
|
||||||
return -1
|
return -1
|
||||||
return self._cameraInits.indexOf(self._cameraInit)
|
return self._cameraInits.indexOf(self._cameraInit)
|
||||||
|
|
||||||
|
@ -493,6 +506,24 @@ class Reconstruction(UIGraph):
|
||||||
""" Set the current FeatureExtraction node based on the current CameraInit node. """
|
""" Set the current FeatureExtraction node based on the current CameraInit node. """
|
||||||
self.depthMap = self.lastNodeOfType('DepthMapFilter', self.cameraInit) if self.cameraInit else None
|
self.depthMap = self.lastNodeOfType('DepthMapFilter', self.cameraInit) if self.cameraInit else None
|
||||||
|
|
||||||
|
def updateLdr2hdrNode(self):
|
||||||
|
""" Set the current LDR2HDR node based on the current CameraInit node. """
|
||||||
|
self.ldr2hdr = self.lastNodeOfType('LDRToHDR', self.cameraInit) if self.cameraInit else None
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def setupLDRToHDRCameraInit(self):
|
||||||
|
if not self.ldr2hdr:
|
||||||
|
self.hdrCameraInit = Node("CameraInit")
|
||||||
|
return
|
||||||
|
sfmFile = self.ldr2hdr.attribute("outSfMDataFilename").value
|
||||||
|
if not sfmFile or not os.path.isfile(sfmFile):
|
||||||
|
self.hdrCameraInit = Node("CameraInit")
|
||||||
|
return
|
||||||
|
nodeDesc = meshroom.core.nodesDesc["CameraInit"]()
|
||||||
|
views, intrinsics = nodeDesc.readSfMData(sfmFile)
|
||||||
|
tmpCameraInit = Node("CameraInit", viewpoints=views, intrinsics=intrinsics)
|
||||||
|
self.hdrCameraInit = tmpCameraInit
|
||||||
|
|
||||||
def lastSfmNode(self):
|
def lastSfmNode(self):
|
||||||
""" Retrieve the last SfM node from the initial CameraInit node. """
|
""" Retrieve the last SfM node from the initial CameraInit node. """
|
||||||
return self.lastNodeOfType("StructureFromMotion", self._cameraInit, Status.SUCCESS)
|
return self.lastNodeOfType("StructureFromMotion", self._cameraInit, Status.SUCCESS)
|
||||||
|
@ -778,6 +809,8 @@ class Reconstruction(UIGraph):
|
||||||
|
|
||||||
cameraInitChanged = Signal()
|
cameraInitChanged = Signal()
|
||||||
cameraInit = makeProperty(QObject, "_cameraInit", cameraInitChanged, resetOnDestroy=True)
|
cameraInit = makeProperty(QObject, "_cameraInit", cameraInitChanged, resetOnDestroy=True)
|
||||||
|
hdrCameraInitChanged = Signal()
|
||||||
|
hdrCameraInit = makeProperty(QObject, "_hdrCameraInit", hdrCameraInitChanged, resetOnDestroy=True)
|
||||||
cameraInitIndex = Property(int, getCameraInitIndex, setCameraInitIndex, notify=cameraInitChanged)
|
cameraInitIndex = Property(int, getCameraInitIndex, setCameraInitIndex, notify=cameraInitChanged)
|
||||||
viewpoints = Property(QObject, getViewpoints, notify=cameraInitChanged)
|
viewpoints = Property(QObject, getViewpoints, notify=cameraInitChanged)
|
||||||
cameraInits = Property(QObject, lambda self: self._cameraInits, constant=True)
|
cameraInits = Property(QObject, lambda self: self._cameraInits, constant=True)
|
||||||
|
@ -970,6 +1003,9 @@ class Reconstruction(UIGraph):
|
||||||
texturingChanged = Signal()
|
texturingChanged = Signal()
|
||||||
texturing = makeProperty(QObject, "_texturing", notify=texturingChanged)
|
texturing = makeProperty(QObject, "_texturing", notify=texturingChanged)
|
||||||
|
|
||||||
|
ldr2hdrChanged = Signal()
|
||||||
|
ldr2hdr = makeProperty(QObject, "_ldr2hdr", notify=ldr2hdrChanged, resetOnDestroy=True)
|
||||||
|
|
||||||
nbCameras = Property(int, reconstructedCamerasCount, notify=sfmReportChanged)
|
nbCameras = Property(int, reconstructedCamerasCount, notify=sfmReportChanged)
|
||||||
|
|
||||||
# Signals to propagate high-level messages
|
# Signals to propagate high-level messages
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue