mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-03 08:48:40 +02:00
[ui] Viewer2D: add FeaturesViewer + dedicated overlay
Make FeaturesViewer available in Viewer2D to display the feature points of the current view, based on the current FeatureExtraction node. * FeaturesInfoOverlay: overlay that displays info and provides controls over a FeaturesViewer component. * ColorChart: color picker based on a set of predefined colors.
This commit is contained in:
parent
8dd0a4be22
commit
4563d32e3e
4 changed files with 231 additions and 0 deletions
66
meshroom/ui/qml/Controls/ColorChart.qml
Normal file
66
meshroom/ui/qml/Controls/ColorChart.qml
Normal file
|
@ -0,0 +1,66 @@
|
|||
import QtQuick 2.10
|
||||
import QtQuick.Controls 2.10
|
||||
|
||||
import Utils 1.0
|
||||
|
||||
/**
|
||||
* ColorChart is a color picker based on a set of predefined colors.
|
||||
* It takes the form of a ToolButton that pops-up its palette when pressed.
|
||||
*/
|
||||
ToolButton {
|
||||
id: root
|
||||
|
||||
property var colors: ["red", "green", "blue"]
|
||||
property int currentIndex: 0
|
||||
|
||||
signal colorPicked(var colorIndex)
|
||||
|
||||
background: Rectangle {
|
||||
color: root.colors[root.currentIndex]
|
||||
border.width: hovered ? 1 : 0
|
||||
border.color: Colors.sysPalette.midlight
|
||||
}
|
||||
|
||||
onPressed: palettePopup.open()
|
||||
|
||||
// Popup for the color palette
|
||||
Popup {
|
||||
id: palettePopup
|
||||
|
||||
padding: 4
|
||||
// content width is missing side padding (hence the + padding*2)
|
||||
implicitWidth: colorChart.contentItem.width + padding*2
|
||||
|
||||
// center the current color
|
||||
y: - (root.height - padding) / 2
|
||||
x: - colorChart.currentItem.x - padding
|
||||
|
||||
// Colors palette
|
||||
ListView {
|
||||
id: colorChart
|
||||
implicitHeight: contentItem.childrenRect.height
|
||||
implicitWidth: contentWidth
|
||||
orientation: ListView.Horizontal
|
||||
spacing: 2
|
||||
currentIndex: root.currentIndex
|
||||
model: root.colors
|
||||
// display each color as a ToolButton with a custom background
|
||||
delegate: ToolButton {
|
||||
padding: 0
|
||||
width: root.width
|
||||
height: root.height
|
||||
background: Rectangle {
|
||||
color: modelData
|
||||
// display border of current/selected item
|
||||
border.width: hovered || index === colorChart.currentIndex ? 1 : 0
|
||||
border.color: Colors.sysPalette.midlight
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
colorPicked(index);
|
||||
palettePopup.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
module Controls
|
||||
|
||||
ColorChart 1.0 ColorChart.qml
|
||||
FloatingPane 1.0 FloatingPane.qml
|
||||
Group 1.0 Group.qml
|
||||
MessageDialog 1.0 MessageDialog.qml
|
||||
|
|
111
meshroom/ui/qml/Viewer/FeaturesInfoOverlay.qml
Normal file
111
meshroom/ui/qml/Viewer/FeaturesInfoOverlay.qml
Normal file
|
@ -0,0 +1,111 @@
|
|||
import QtQuick 2.11
|
||||
import QtQuick.Controls 2.11
|
||||
import QtQuick.Layouts 1.3
|
||||
import MaterialIcons 2.2
|
||||
|
||||
import Utils 1.0
|
||||
import Controls 1.0
|
||||
|
||||
/**
|
||||
* FeaturesInfoOverlay is an overlay that displays info and
|
||||
* provides controls over a FeaturesViewer component.
|
||||
*/
|
||||
FloatingPane {
|
||||
id: root
|
||||
|
||||
property int pluginStatus: Loader.Null
|
||||
property Item featuresViewer: null
|
||||
property var featureExtractionNode: null
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
// Header
|
||||
RowLayout {
|
||||
// FeatureExtraction node name
|
||||
Label {
|
||||
text: featureExtractionNode.label
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
// Settings menu
|
||||
Loader {
|
||||
active: root.pluginStatus === Loader.Ready
|
||||
sourceComponent: MaterialToolButton {
|
||||
text: MaterialIcons.settings
|
||||
font.pointSize: 10
|
||||
onClicked: settingsMenu.popup(width, 0)
|
||||
Menu {
|
||||
id: settingsMenu
|
||||
padding: 4
|
||||
implicitWidth: 210
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "Display Mode:"
|
||||
}
|
||||
ComboBox {
|
||||
id: displayModeCB
|
||||
flat: true
|
||||
Layout.fillWidth: true
|
||||
model: featuresViewer.displayModes
|
||||
onActivated: featuresViewer.displayMode = currentIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error message if AliceVision plugin is unavailable
|
||||
Label {
|
||||
visible: root.pluginStatus === Loader.Error
|
||||
text: "AliceVision plugin is required to display Features"
|
||||
color: Colors.red
|
||||
}
|
||||
|
||||
// Feature types
|
||||
ListView {
|
||||
implicitHeight: contentHeight
|
||||
implicitWidth: contentItem.childrenRect.width
|
||||
|
||||
model: featuresViewer !== null ? featuresViewer.model : 0
|
||||
|
||||
delegate: RowLayout {
|
||||
id: featureType
|
||||
|
||||
property var viewer: featuresViewer.itemAt(index)
|
||||
spacing: 4
|
||||
|
||||
// Visibility toogle
|
||||
MaterialToolButton {
|
||||
text: featureType.viewer.visible ? MaterialIcons.visibility : MaterialIcons.visibility_off
|
||||
onClicked: featureType.viewer.visible = !featureType.viewer.visible
|
||||
font.pointSize: 10
|
||||
opacity: featureType.viewer.visible ? 1.0 : 0.6
|
||||
}
|
||||
// ColorChart picker
|
||||
ColorChart {
|
||||
implicitWidth: 12
|
||||
implicitHeight: implicitWidth
|
||||
colors: featuresViewer.colors
|
||||
currentIndex: featureType.viewer.colorIndex
|
||||
// offset FeaturesViewer color set when changing the color of one feature type
|
||||
onColorPicked: featuresViewer.colorOffset = colorIndex - index
|
||||
}
|
||||
// Feature type name
|
||||
Label {
|
||||
text: featureType.viewer.describerType + (featureType.viewer.loading ? "" : ": " + featureType.viewer.features.length)
|
||||
}
|
||||
// Feature loading status
|
||||
Loader {
|
||||
active: featureType.viewer.loading
|
||||
sourceComponent: BusyIndicator {
|
||||
padding: 0
|
||||
implicitWidth: 12
|
||||
implicitHeight: 12
|
||||
running: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -77,8 +77,39 @@ FocusScope {
|
|||
|
||||
visible: image.status === Image.Loading
|
||||
}
|
||||
|
||||
// FeatureViewer: display view extracted feature points
|
||||
// note: requires QtAliceVision plugin - use a Loader to evaluate plugin avaibility at runtime
|
||||
Loader {
|
||||
id: featuresViewerLoader
|
||||
|
||||
active: displayFeatures.checked
|
||||
|
||||
// handle rotation/position based on available metadata
|
||||
rotation: {
|
||||
var orientation = metadata ? metadata["Orientation"] : 0
|
||||
switch(orientation) {
|
||||
case "6": return 90;
|
||||
case "8": return -90;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
x: rotation === 90 ? image.paintedWidth : 0
|
||||
y: rotation === -90 ? image.paintedHeight : 0
|
||||
|
||||
Component.onCompleted: {
|
||||
// instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource
|
||||
setSource("FeaturesViewer.qml", {
|
||||
'active': Qt.binding(function() { return displayFeatures.checked; }),
|
||||
'viewId': Qt.binding(function() { return _reconstruction.selectedViewId; }),
|
||||
'model': Qt.binding(function() { return _reconstruction.featureExtraction.attribute("describerTypes").value; }),
|
||||
'folder': Qt.binding(function() { return Filepath.stringToUrl(_reconstruction.featureExtraction.attribute("output").value); }),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Busy indicator
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
|
@ -147,6 +178,21 @@ FocusScope {
|
|||
metadata: visible ? root.metadata : {}
|
||||
}
|
||||
|
||||
|
||||
Loader {
|
||||
id: featuresOverlay
|
||||
anchors.bottom: bottomToolbar.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: 2
|
||||
active: displayFeatures.checked
|
||||
|
||||
sourceComponent: FeaturesInfoOverlay {
|
||||
featureExtractionNode: _reconstruction.featureExtraction
|
||||
pluginStatus: featuresViewerLoader.status
|
||||
featuresViewer: featuresViewerLoader.item
|
||||
}
|
||||
}
|
||||
|
||||
FloatingPane {
|
||||
id: bottomToolbar
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -163,6 +209,13 @@ FocusScope {
|
|||
text: (image.status == Image.Ready ? image.scale.toFixed(2) : "1.00") + "x"
|
||||
state: "xsmall"
|
||||
}
|
||||
MaterialToolButton {
|
||||
id: displayFeatures
|
||||
font.pointSize: 11
|
||||
ToolTip.text: "Display Features"
|
||||
checkable: true
|
||||
text: MaterialIcons.scatter_plot
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue