[ui] Load image sequence from node output in SequencePlayer

This commit is contained in:
Aurore LAFAURIE 2024-04-16 16:51:24 +02:00
parent 3eb90322a8
commit b0063b0dde
3 changed files with 81 additions and 30 deletions

View file

@ -4,6 +4,7 @@ from PySide2.QtCore import QUrl, QFileInfo
from PySide2.QtCore import QObject, Slot
import os
import glob
class FilepathHelper(QObject):
@ -103,15 +104,26 @@ class FilepathHelper(QObject):
def resolve(self, path, vp):
# Resolve dynamic path that depends on viewpoint
replacements = {}
if vp == None:
replacements = FilepathHelper.getFilenamesFromFolder(FilepathHelper, FilepathHelper.dirname(FilepathHelper, path), FilepathHelper.extension(FilepathHelper, path))
resolved = [path for i in range(len(replacements))]
for key in replacements:
for i in range(len(resolved)):
resolved[i] = resolved[i].replace("<FRAMEID>", replacements[i])
return resolved
else:
vpPath = vp.childAttribute("path").value
filename = FilepathHelper.basename(FilepathHelper, vpPath)
replacements = {
"<VIEW_ID>": str(vp.childAttribute("viewId").value),
"<INTRINSIC_ID>": str(vp.childAttribute("intrinsicId").value),
"<POSE_ID>": str(vp.childAttribute("poseId").value),
"<PATH>": vpPath,
"<FILENAME>": FilepathHelper.basename(FilepathHelper, vpPath),
"<FILESTEM>": FilepathHelper.removeExtension(FilepathHelper, FilepathHelper.basename(FilepathHelper, vpPath)),
"<EXTENSION>": FilepathHelper.extension(FilepathHelper, vpPath),
"<FILENAME>": filename,
"<FILESTEM>": FilepathHelper.removeExtension(FilepathHelper, filename),
"<EXTENSION>": FilepathHelper.extension(FilepathHelper, filename),
}
resolved = path
@ -119,3 +131,17 @@ class FilepathHelper(QObject):
resolved = resolved.replace(key, replacements[key])
return resolved
@Slot(str, result="QVariantList")
@Slot(str, str, result="QVariantList")
def getFilenamesFromFolder(self, folderPath: str, extension: str = None):
"""
Get all filenames from a folder with a specific extension.
:param folderPath: Path to the folder.
:param extension: Extension of the files to get.
:return: List of filenames.
"""
if extension is None:
extension = ".*"
return [self.removeExtension(FilepathHelper, self.basename(FilepathHelper, f)) for f in glob.glob(os.path.join(folderPath, f"*{extension}")) if os.path.isfile(f)]

View file

@ -27,6 +27,7 @@ FloatingPane {
readonly property alias syncFeaturesSelected: m.syncFeaturesSelected
property bool loading: fetchButton.checked || m.playing
property alias settings_SequencePlayer: settings_SequencePlayer
property alias frameId: m.frame
Settings {
id: settings_SequencePlayer
@ -94,7 +95,7 @@ FloatingPane {
id: timer
repeat: true
running: m.playing
running: m.playing && root.visible
interval: 1000 / m.fps
onTriggered: {

View file

@ -30,6 +30,8 @@ FocusScope {
property bool enableSequencePlayer: enableSequencePlayerAction.checked
readonly property alias sync3DSelected: sequencePlayer.sync3DSelected
property var sequence: []
property int currentFrame: sequencePlayer.frameId
QtObject {
id: m
@ -181,7 +183,7 @@ FocusScope {
}
// node must have at least one output attribute with the image semantic
if (!node.hasImageOutput) {
if (!node.hasImageOutput && !node.hasSequenceOutput) {
return false
}
@ -223,7 +225,6 @@ FocusScope {
return undefined
}
function getImageFile() {
// Entry point for getting the image file URL
@ -237,6 +238,11 @@ FocusScope {
return Filepath.stringToUrl(path)
}
if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput) {
var path = sequence[currentFrame]
return Filepath.stringToUrl(path)
}
if (_reconstruction) {
let vp = getViewpoint(_reconstruction.pickedViewId)
let attr = getAttributeByName(displayedNode, outputAttribute.name)
@ -253,11 +259,17 @@ FocusScope {
// ordered by path
let objs = []
if (displayedNode && displayedNode.hasSequenceOutput) {
objs = Filepath.resolve(path_template, null)
//order by path
objs.sort()
return objs
} else {
for (let i = 0; i < _reconstruction.viewpoints.count; i++) {
objs.push(_reconstruction.viewpoints.at(i))
}
objs.sort((a, b) => { return a.childAttribute("path").value < b.childAttribute("path").value ? -1 : 1; })
let seq = [];
for (let i = 0; i < objs.length; i++) {
seq.push(Filepath.resolve(path_template, objs[i]))
@ -265,6 +277,7 @@ FocusScope {
return seq
}
}
function getSequence() {
// Entry point for getting the current image sequence
@ -300,12 +313,23 @@ FocusScope {
if (attr.isOutput && attr.desc.semantic === "image" && attr.enabled) {
names.push(attr.name)
}
if (attr.isOutput && attr.desc.semantic === "sequence" && attr.enabled) {
names.push(attr.name)
}
}
}
if (!displayedNode || displayedNode.isComputable) names.push("gallery")
outputAttribute.names = names
if (displayedNode && !displayedNode.hasSequenceOutput) {
root.source = getImageFile()
} else {
root.sequence = getSequence()
enableSequencePlayerAction.checked = true
}
}
Connections {
@ -457,11 +481,11 @@ FocusScope {
'sfmRequired': Qt.binding(function() { return displayLensDistortionViewer.checked ? true : false }),
'surface.msfmData': Qt.binding(function() { return (msfmDataLoader.status === Loader.Ready && msfmDataLoader.item != null && msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null }),
'canBeHovered': false,
'idView': Qt.binding(function() { return (_reconstruction ? _reconstruction.selectedViewId : -1) }),
'idView': Qt.binding(function() { return ((root.displayedNode && !root.displayedNode.hasSequenceOutput && _reconstruction) ? _reconstruction.selectedViewId : -1) }),
'cropFisheye': false,
'sequence': Qt.binding(function() { return ((root.enableSequencePlayer && _reconstruction && _reconstruction.viewpoints.count > 0) ? getSequence() : []) }),
'sequence': Qt.binding(function() { return ((root.enableSequencePlayer && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput))) ? getSequence() : []) }),
'targetSize': Qt.binding(function() { return floatImageViewerLoader.targetSize }),
'useSequence': Qt.binding(function() { return root.enableSequencePlayer && !useExternal && _reconstruction }),
'useSequence': Qt.binding(function() { return (root.enableSequencePlayer && !useExternal && (_reconstruction || (root.displayedNode && root.displayedNode.hasSequenceOutput))) }),
'fetchingSequence': Qt.binding(function() { return sequencePlayer.loading }),
'memoryLimit': Qt.binding(function() { return sequencePlayer.settings_SequencePlayer.maxCacheMemory }),
})
@ -1434,7 +1458,7 @@ FocusScope {
id: sequencePlayer
anchors.margins: 0
Layout.fillWidth: true
sortedViewIds: (root.enableSequencePlayer && _reconstruction && _reconstruction.viewpoints.count > 0) ? buildOrderedSequence("<VIEW_ID>") : []
sortedViewIds: { return (root.enableSequencePlayer && (root.displayedNode && root.displayedNode.hasSequenceOutput)) ? root.sequence : (_reconstruction && _reconstruction.viewpoints.count > 0) ? buildOrderedSequence("<VIEW_ID>") : [] }
viewer: floatImageViewerLoader.status === Loader.Ready ? floatImageViewerLoader.item : null
visible: root.enableSequencePlayer
enabled: root.enableSequencePlayer