Merge branch 'develop' into dev_ml

This commit is contained in:
Laureηt 2022-09-01 16:34:44 +02:00
commit 4e4fce03eb
No known key found for this signature in database
GPG key ID: D88C6B294FD40994
36 changed files with 236 additions and 78 deletions

View file

@ -62,7 +62,7 @@ If you use this project for a publication, please cite the [paper](https://hal.a
```
@inproceedings{alicevision2021,
title={{A}liceVision {M}eshroom: An open-source {3D} reconstruction pipeline},
authors={Carsten Griwodz and Simone Gasparini and Lilian Calvet and Pierre Gurdjos and Fabien Castan and Benoit Maujean and Gregoire De Lillo and Yann Lanthony},
author={Carsten Griwodz and Simone Gasparini and Lilian Calvet and Pierre Gurdjos and Fabien Castan and Benoit Maujean and Gregoire De Lillo and Yann Lanthony},
booktitle={Proceedings of the 12th ACM Multimedia Systems Conference - {MMSys '21}},
doi = {10.1145/3458305.3478443},
publisher = {ACM Press},

View file

@ -177,7 +177,7 @@ with multiview.GraphModification(graph):
if args.paramOverrides:
print("\n")
import re
reExtract = re.compile('(\w+)([:.])(\w+)=(.*)')
reExtract = re.compile('(\w+)([:.])(\w[\w.]*)=(.*)')
for p in args.paramOverrides:
result = reExtract.match(p)
if not result:

View file

@ -5,6 +5,7 @@ import argparse
import os
import re
import sys
import shlex
from pprint import pprint
def trim(s):
@ -60,7 +61,7 @@ parser.add_argument('node', metavar='NODE_NAME', type=str,
help='New node name')
parser.add_argument('bin', metavar='CMDLINE', type=str,
default=None,
help='Output plugin folder')
help='Input executable')
parser.add_argument('--output', metavar='DIR', type=str,
default=os.path.dirname(__file__),
help='Output plugin folder')
@ -77,7 +78,7 @@ soft = "{nodeType}"
if args.bin:
soft = args.bin
import subprocess
proc = subprocess.Popen(args=[args.bin, '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc = subprocess.Popen(args=shlex.split(args.bin) + ['--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
inputCmdLineDoc = stdout if stdout else stderr
elif sys.stdin.isatty():
@ -137,7 +138,7 @@ choiceValues1_re = re.compile('\* (?P<value>\w+):')
choiceValues2_re = re.compile('\((?P<value>.+?)\)')
choiceValues3_re = re.compile('\{(?P<value>.+?)\}')
cmdLineArgs = args_re.findall(inputCmdLineDoc)
cmdLineArgs = args_re.findall(inputCmdLineDoc.decode('utf-8'))
print('='*80)
pprint(cmdLineArgs)

View file

@ -272,9 +272,17 @@ def loadSubmitters(folder, packageName):
meshroomFolder = os.path.dirname(os.path.dirname(__file__))
additionalNodesPath = os.environ.get("MESHROOM_NODES_PATH", "").split(os.pathsep)
# filter empty strings
additionalNodesPath = [i for i in additionalNodesPath if i]
# Load plugins:
# - Nodes
loadAllNodes(folder=os.path.join(meshroomFolder, 'nodes'))
nodesFolders = [os.path.join(meshroomFolder, 'nodes')] + additionalNodesPath
for f in nodesFolders:
loadAllNodes(folder=f)
# - Submitters
subs = loadSubmitters(os.environ.get("MESHROOM_SUBMITTERS_PATH", meshroomFolder), 'submitters')

7
meshroom/core/desc.py Normal file → Executable file
View file

@ -5,6 +5,8 @@ import math
import os
import psutil
import ast
import distutils.util
class Attribute(BaseObject):
"""
@ -191,7 +193,10 @@ class BoolParam(Param):
def validateValue(self, value):
try:
return bool(int(value)) # int cast is useful to handle string values ('0', '1')
if isinstance(value, pyCompatibility.basestring):
# use distutils.util.strtobool to handle (1/0, true/false, on/off, y/n)
return bool(distutils.util.strtobool(value))
return bool(value)
except:
raise ValueError('BoolParam only supports bool value (param:{}, value:{}, type:{})'.format(self.name, value, type(value)))

View file

@ -95,23 +95,34 @@ class ComputerStatistics:
return
try:
p = subprocess.Popen([self.nvidia_smi, "-q", "-x"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
xmlGpu, stdError = p.communicate(timeout=10) # 10 seconds
if sys.version_info[0] == 2:
# no timeout in python-2
xmlGpu, stdError = p.communicate()
else:
xmlGpu, stdError = p.communicate(timeout=10) # 10 seconds
smiTree = ET.fromstring(xmlGpu)
gpuTree = smiTree.find('gpu')
try:
self._addKV('gpuMemoryUsed', gpuTree.find('fb_memory_usage').find('used').text.split(" ")[0])
gpuMemoryUsed = gpuTree.find('fb_memory_usage').find('used').text.split(" ")[0]
self._addKV('gpuMemoryUsed', gpuMemoryUsed)
except Exception as e:
logging.debug('Failed to get gpuMemoryUsed: "{}".'.format(str(e)))
pass
try:
self._addKV('gpuUsed', gpuTree.find('utilization').find('gpu_util').text.split(" ")[0])
self.gpuMemoryTotal = gpuTree.find('fb_memory_usage').find('total').text.split(" ")[0]
except Exception as e:
pass
try:
gpuUsed = gpuTree.find('utilization').find('gpu_util').text.split(" ")[0]
self._addKV('gpuUsed', gpuUsed)
except Exception as e:
logging.debug('Failed to get gpuUsed: "{}".'.format(str(e)))
pass
try:
self._addKV('gpuTemperature', gpuTree.find('temperature').find('gpu_temp').text.split(" ")[0])
gpuTemperature = gpuTree.find('temperature').find('gpu_temp').text.split(" ")[0]
self._addKV('gpuTemperature', gpuTemperature)
except Exception as e:
logging.debug('Failed to get gpuTemperature: "{}".'.format(str(e)))
pass
@ -191,7 +202,7 @@ class ProcStatistics:
data = proc.as_dict(self.dynamicKeys)
for k, v in data.items():
self._addKV(k, v)
## Note: Do not collect stats about open files for now,
# as there is bug in psutil-5.7.2 on Windows which crashes the application.
# https://github.com/giampaolo/psutil/issues/1763

View file

@ -136,7 +136,7 @@ def findFilesByTypeInFolder(folder, recursive=False):
else:
output.addFiles([os.path.join(currentFolder, filename) for filename in os.listdir(currentFolder)])
else:
# if not a diretory or a file, it may be an expression
# if not a directory or a file, it may be an expression
import glob
paths = glob.glob(currentFolder)
filesByType = findFilesByTypeInFolder(paths, recursive=recursive)
@ -186,7 +186,7 @@ def panoramaFisheyeHdr(inputImages=None, inputViewpoints=None, inputIntrinsics=N
# when using fisheye images, 'sift' performs better than 'dspsift'
featureExtraction.attribute("describerTypes").value = ['sift']
# when using fisheye images, the overlap between images can be small
# and thus requires many features to get enough correspondances for cameras estimation
# and thus requires many features to get enough correspondences for cameras estimation
featureExtraction.attribute("describerPreset").value = 'high'
return graph

View file

@ -1,4 +1,4 @@
__version__ = "6.0"
__version__ = "7.0"
import os
import json
@ -28,16 +28,17 @@ Viewpoint = [
Intrinsic = [
desc.IntParam(name="intrinsicId", label="Id", description="Intrinsic UID", value=-1, uid=[0], range=None),
desc.FloatParam(name="pxInitialFocalLength", label="Initial Focal Length",
desc.FloatParam(name="initialFocalLength", label="Initial Focal Length",
description="Initial Guess on the Focal Length (in pixels). \n"
"When we have an initial value from EXIF, this value is not accurate but cannot be wrong. \n"
"So this value is used to limit the range of possible values in the optimization. \n"
"If you put -1, this value will not be used and the focal length will not be bounded.",
value=-1.0, uid=[0], range=None),
desc.GroupAttribute(name="pxFocalLength", label="Focal Length", description="Known/Calibrated Focal Length (in pixels)", groupDesc=[
desc.FloatParam(name="x", label="x", description="", value=-1, uid=[], range=(0, 10000, 1)),
desc.FloatParam(name="y", label="y", description="", value=-1, uid=[], range=(0, 10000, 1)),
]),
desc.FloatParam(name="focalLength", label="Focal Length", description="Known/Calibrated Focal Length (in mm)", value=1000, uid=[], range=(0, 10000, 1)),
desc.FloatParam(name="pixelRatio", label="pixel Ratio", description="ratio between pixel width and pixel height", value=1, uid=[], range=(0, 10, 0.1)),
desc.BoolParam(name='pixelRatioLocked', label='Pixel ratio Locked',
description='the pixelRatio value is locked for estimation',
value=True, uid=[0]),
desc.ChoiceParam(name="type", label="Camera Type",
description="Mathematical Model used to represent a camera:\n"
" * pinhole: Simplest projective camera model without optical distortion (focal and optical center).\n"
@ -107,11 +108,6 @@ def readSfMData(sfmFile):
intrinsic['principalPoint']['x'] = pp[0]
intrinsic['principalPoint']['y'] = pp[1]
f = intrinsic['pxFocalLength']
intrinsic['pxFocalLength'] = {}
intrinsic['pxFocalLength']['x'] = f[0]
intrinsic['pxFocalLength']['y'] = f[1]
# convert empty string distortionParams (i.e: Pinhole model) to empty list
if intrinsic['distortionParams'] == '':
intrinsic['distortionParams'] = list()
@ -255,12 +251,6 @@ The metadata needed are:
]
def upgradeAttributeValues(self, attrValues, fromVersion):
# Starting with version 5, the focal length is now split on x and y
if fromVersion < Version(5, 0):
for intrinsic in attrValues['intrinsics']:
pxFocalLength = intrinsic['pxFocalLength']
if not isinstance(pxFocalLength, dict):
intrinsic['pxFocalLength'] = {"x": pxFocalLength, "y": pxFocalLength}
# Starting with version 6, the principal point is now relative to the image center
if fromVersion < Version(6, 0):
@ -271,6 +261,20 @@ The metadata needed are:
"y": int(principalPoint["y"] - 0.5 * intrinsic['height'])
}
# Starting with version 7, the focal length is now in mm
if fromVersion < Version(7, 0):
for intrinsic in attrValues['intrinsics']:
pxInitialFocalLength = intrinsic['pxInitialFocalLength']
pxFocalLength = intrinsic['pxFocalLength']
sensorWidth = intrinsic['sensorWidth']
width = intrinsic['width']
focalLength = (pxFocalLength / width) * sensorWidth
initialFocalLength = (pxInitialFocalLength / width) * sensorWidth
intrinsic['initialFocalLength'] = initialFocalLength
intrinsic['focalLength'] = focalLength
intrinsic['pixelRatio'] = 1.0
intrinsic['pixelRatioLocked'] = False
return attrValues
def readSfMData(self, sfmFile):
@ -329,7 +333,6 @@ The metadata needed are:
intrinsics = node.intrinsics.getPrimitiveValue(exportDefault=True)
for intrinsic in intrinsics:
intrinsic['principalPoint'] = [intrinsic['principalPoint']['x'], intrinsic['principalPoint']['y']]
intrinsic['pxFocalLength'] = [intrinsic['pxFocalLength']['x'], intrinsic['pxFocalLength']['y']]
views = node.viewpoints.getPrimitiveValue(exportDefault=False)
# convert the metadata string into a map
@ -338,7 +341,7 @@ The metadata needed are:
view['metadata'] = json.loads(view['metadata'])
sfmData = {
"version": [1, 2, 1],
"version": [1, 2, 2],
"views": views + newViews,
"intrinsics": intrinsics,
"featureFolder": "",

View file

@ -17,7 +17,7 @@ Performs Macbeth color checker chart detection.
Outputs:
- the detected color charts position and colors
- the associated tranform matrix from "theoric" to "measured"
- the associated transform matrix from "theoric" to "measured"
assuming that the "theoric" Macbeth chart corners coordinates are:
(0, 0), (1675, 0), (1675, 1125), (0, 1125)

View file

@ -63,6 +63,38 @@ Use a downscale factor of one (full-resolution) only if the quality of the input
uid=[0],
advanced=True,
),
desc.IntParam(
name='sgmScale',
label='SGM: Downscale factor',
description='Semi Global Matching: Downscale factor used to compute the similarity volume.',
value=-1,
range=(-1, 10, 1),
uid=[0],
),
desc.IntParam(
name='sgmStepXY',
label='SGM: Step XY',
description='Semi Global Matching: Step used to compute the similarity volume on X and Y axis.',
value=-1,
range=(-1, 10, 1),
uid=[0],
),
desc.IntParam(
name='sgmStepZ',
label='SGM: Step Z',
description='Semi Global Matching: Step used to compute the similarity volume on Z axis.',
value=-1,
range=(-1, 10, 1),
uid=[0],
),
desc.IntParam(
name='sgmMaxSideXY',
label='SGM: Max Side',
description='Semi Global Matching: Max side in pixels used to automatically decide for sgmScale/sgmStep if not defined.',
value=700,
range=(-1, 1000, 1),
uid=[0],
),
desc.IntParam(
name='sgmMaxTCams',
label='SGM: Nb Neighbour Cameras',
@ -98,6 +130,59 @@ Use a downscale factor of one (full-resolution) only if the quality of the input
uid=[0],
advanced=True,
),
desc.FloatParam(
name='sgmP1',
label='SGM: P1',
description='Semi Global Matching: P1.',
value=10.0,
range=(0.0, 255.0, 0.5),
uid=[0],
advanced=True,
),
desc.FloatParam(
name='sgmP2',
label='SGM: P2',
description='Semi Global Matching: P2 weight.',
value=100.0,
range=(-255.0, 255.0, 0.5),
uid=[0],
advanced=True,
),
desc.IntParam(
name='sgmMaxDepths',
label='SGM: Max Depths',
description='Semi Global Matching: Max number of depths in the overall similarity volume.',
value=3000,
range=(1, 5000, 1),
uid=[0],
advanced=True,
),
desc.IntParam(
name='sgmMaxDepthsPerTc',
label='SGM: Max Depths Per Camera Pairs',
description='Semi Global Matching: Max number of depths to sweep in the similarity volume per Rc/Tc cameras.',
value=1500,
range=(1, 5000, 1),
uid=[0],
advanced=True,
),
desc.BoolParam(
name='sgmUseSfmSeeds',
label='SGM: Use SfM Landmarks',
description='Semi Global Matching: Use landmarks from SfM to define the ranges for the plane sweeping.',
value=True,
uid=[0],
advanced=True,
),
desc.StringParam(
name='sgmFilteringAxes',
label='SGM: Filtering Axes',
description="Semi Global Matching: Define axes for the filtering of the similarity volume.",
value='YX',
uid=[0],
advanced=True,
),
desc.IntParam(
name='refineMaxTCams',
label='Refine: Nb Neighbour Cameras',

View file

@ -74,6 +74,15 @@ This allows to filter unstable points before starting the fusion of all depth ma
range=(0, 10, 1),
uid=[0],
),
desc.FloatParam(
name='pixToleranceFactor',
label='Tolerance Size',
description='Filtering tolerance size factor (in px).',
value=2.0,
range=(0.001, 10.0, 0.1),
uid=[0],
advanced=True,
),
desc.IntParam(
name="pixSizeBall",
label="Filtering Size in Pixels",

View file

@ -170,7 +170,7 @@ then it checks the number of features that validates this model and iterate thro
desc.BoolParam(
name='crossMatching',
label='Cross Matching',
description='Make sure that the matching process is symmetric (same matches for I->J than fo J->I)',
description='Make sure that the matching process is symmetric (same matches for I->J than for J->I)',
value=False,
uid=[0],
),

View file

@ -43,7 +43,7 @@ Estimate the seams lines between the inputs to provide an optimal compositing in
desc.BoolParam(
name='useGraphCut',
label='Use Smart Seams',
description='Use a graphcut algorithm to optmize seams for better transitions between images.',
description='Use a graphcut algorithm to optimize seams for better transitions between images.',
value=True,
uid=[0],
),

View file

@ -200,7 +200,7 @@ Upload a textured mesh on Sketchfab.
modelEndpoint, **{'data': body, 'headers': headers})
chunk.logManager.completeProgressBar()
except requests.exceptions.RequestException as e:
chunk.logger.error(u'An error occured: {}'.format(e))
chunk.logger.error(u'An error occurred: {}'.format(e))
raise RuntimeError()
if r.status_code != requests.codes.created:
chunk.logger.error(u'Upload failed with error: {}'.format(r.json()))

View file

@ -6,7 +6,7 @@ class Split360Images(desc.CommandLineNode):
commandLine = 'aliceVision_utils_split360Images {allParams}'
category = 'Utils'
documentation = '''This node is used to extract multiple images from equirectangular or dualfisheye images or image folder'''
documentation = "This node is used to extract multiple images from equirectangular or dualfisheye images."
inputs = [
desc.File(

View file

@ -116,7 +116,7 @@ It iterates like that, adding cameras and triangulating new 2D features into 3D
desc.ChoiceParam(
name='observationConstraint',
label='Observation Constraint',
description='Observation contraint mode used in the optimization:\n'
description='Observation constraint mode used in the optimization:\n'
' * Basic: Use standard reprojection error in pixel coordinates\n'
' * Scale: Use reprojection error in pixel coordinates but relative to the feature scale',
value='Scale',
@ -308,6 +308,13 @@ It iterates like that, adding cameras and triangulating new 2D features into 3D
value=False,
uid=[0],
),
desc.BoolParam(
name='computeStructureColor',
label='Compute Structure Color',
description='Enable/Disable color computation of each 3D point.',
value=True,
uid=[0],
),
desc.File(
name='initialPairA',
label='Initial Pair A',

View file

@ -273,7 +273,7 @@ Many cameras are contributing to the low frequencies and only the best ones cont
desc.BoolParam(
name='forceVisibleByAllVertices',
label='Force Visible By All Vertices',
description='''Triangle visibility is based on the union of vertices visiblity.''',
description='''Triangle visibility is based on the union of vertices visibility.''',
value=False,
uid=[0],
advanced=True,

View file

@ -31,7 +31,7 @@ def main():
parser.add_argument(
"--useBackground", type=strtobool, required=True,
help="Diplay the background image or not.",
help="Display the background image or not.",
)
parser.add_argument(
@ -262,8 +262,8 @@ def main():
# For showing an outline of the object, we need to add two materials to the mesh:
# Center and Edge, we are using a method that consists in having a "bold" effect on the Edge Material so we can see it
# around the Center material. We use a Solidify Modifier on which we flip normals and reduce Thickness to bellow zero.
# The more the thickness get bellow zero, the more the egde will be largely revealed.
# around the Center material. We use a Solidify Modifier on which we flip normals and reduce Thickness to below zero.
# The more the thickness get below zero, the more the edge will be largely revealed.
elif args.model.lower().endswith('.obj'):
print("Import OBJ")

View file

@ -12,7 +12,7 @@
},
"GPU": {
"NONE": [],
"NORMAL": ["!\"*rnd*\""],
"INTENSIVE": ["!\"*rnd*\"", "@.nCPUs>=12"]
"NORMAL": ["cuda8G"],
"INTENSIVE": ["cuda16G"]
}
}

View file

@ -3,6 +3,7 @@
import os
import json
import logging
import simpleFarm
from meshroom.core.desc import Level
@ -12,14 +13,12 @@ currentDir = os.path.dirname(os.path.realpath(__file__))
binDir = os.path.dirname(os.path.dirname(os.path.dirname(currentDir)))
class SimpleFarmSubmitter(BaseSubmitter):
if 'REZ_MESHROOM_VERSION' in os.environ:
MESHROOM_PACKAGE = "meshroom-{}".format(os.environ.get('REZ_MESHROOM_VERSION', ''))
else:
MESHROOM_PACKAGE = None
filepath = os.environ.get('SIMPLEFARMCONFIG', os.path.join(currentDir, 'simpleFarmConfig.json'))
config = json.load(open(filepath))
reqPackages = []
environment = {}
ENGINE = ''
DEFAULT_TAGS = {'prod': ''}
@ -28,6 +27,32 @@ class SimpleFarmSubmitter(BaseSubmitter):
self.engine = os.environ.get('MESHROOM_SIMPLEFARM_ENGINE', 'tractor')
self.share = os.environ.get('MESHROOM_SIMPLEFARM_SHARE', 'vfx')
self.prod = os.environ.get('PROD', 'mvg')
if 'REZ_REQUEST' in os.environ:
packages = os.environ.get('REZ_REQUEST', '').split()
resolvedPackages = os.environ.get('REZ_RESOLVE', '').split()
resolvedVersions = {}
for r in resolvedPackages:
# remove implict packages
if r.startswith('~'):
continue
# logging.info('REZ: {}'.format(str(r)))
v = r.split('-')
# logging.info(' v: {}'.format(str(v)))
if len(v) == 2:
resolvedVersions[v[0]] = v[1]
for p in packages:
if p.startswith('~'):
continue
v = p.split('-')
self.reqPackages.append('-'.join([v[0], resolvedVersions[v[0]]]))
logging.debug('REZ Packages: {}'.format(str(self.reqPackages)))
elif 'REZ_MESHROOM_VERSION' in os.environ:
self.reqPackages = ["meshroom-{}".format(os.environ.get('REZ_MESHROOM_VERSION', ''))]
else:
self.reqPackages = None
if 'REZ_DEV_PACKAGES_ROOT' in os.environ:
self.environment['REZ_DEV_PACKAGES_ROOT'] = os.environ['REZ_DEV_PACKAGES_ROOT']
def createTask(self, meshroomFile, node):
tags = self.DEFAULT_TAGS.copy() # copy to not modify default tags
@ -50,10 +75,10 @@ class SimpleFarmSubmitter(BaseSubmitter):
task = simpleFarm.Task(
name=node.nodeType,
command='{exe} --node {nodeName} "{meshroomFile}" {parallelArgs} --extern'.format(
exe='meshroom_compute' if self.MESHROOM_PACKAGE else os.path.join(binDir, 'meshroom_compute'),
exe='meshroom_compute' if self.reqPackages else os.path.join(binDir, 'meshroom_compute'),
nodeName=node.name, meshroomFile=meshroomFile, parallelArgs=parallelArgs),
tags=tags,
rezPackages=[self.MESHROOM_PACKAGE] if self.MESHROOM_PACKAGE else None,
rezPackages=self.reqPackages,
requirements={'service': str(','.join(allRequirements))},
**arguments)
return task
@ -74,6 +99,7 @@ class SimpleFarmSubmitter(BaseSubmitter):
job = simpleFarm.Job(name,
tags=mainTags,
requirements={'service': str(','.join(allRequirements))},
environment=self.environment,
)
nodeNameToTask = {}

View file

@ -515,7 +515,7 @@ class UIGraph(QObject):
@Slot(Node, QPoint, QObject)
def moveNode(self, node, position, nodes=None):
"""
Move 'node' to the given 'position' and also update the positions of 'nodes' if neccessary.
Move 'node' to the given 'position' and also update the positions of 'nodes' if necessary.
Args:
node (Node): the node to move

View file

@ -118,7 +118,7 @@ Dialog {
font.pointSize: 10
}
Label {
text: "2010-2021 AliceVision contributors"
text: "2010-2022 AliceVision contributors"
}
}

View file

@ -20,7 +20,7 @@ Dialog {
/// Return the text content of this dialog as a simple string.
/// Used when copying the message in the system clipboard.
/// Can be overriden in components extending MessageDialog
/// Can be overridden in components extending MessageDialog
function getAsString() {
return asString
}

View file

@ -7,7 +7,7 @@ import Controls 1.0
*/
QtObject {
readonly property string defaultErrorText: "An unexpected error has occured"
readonly property string defaultErrorText: "An unexpected error has occurred"
property Component infoDialog: Component {
MessageDialog {

View file

@ -63,7 +63,7 @@ Item {
}
}
/// Duplicate a node and optionnally all the following ones
/// Duplicate a node and optionally all the following ones
function duplicateNode(duplicateFollowingNodes) {
if (duplicateFollowingNodes) {
var nodes = uigraph.duplicateNodesFrom(uigraph.selectedNodes)

View file

@ -48,6 +48,10 @@ Panel {
parseIntr()
}
function changeCurrentIndex(newIndex) {
_reconstruction.cameraInitIndex = newIndex
}
function populate_model()
{
intrinsicModel.clear()
@ -474,9 +478,8 @@ Panel {
property var columnWidths: [105, 75, 75, 75, 125, 60, 60, 45, 45, 200, 60, 60]
property var columnNames: [
"intrinsicId",
"pxInitialFocalLength",
"pxFocalLength.x",
"pxFocalLength.y",
"initialFocalLength",
"focalLength",
"type",
"width",
"height",
@ -499,7 +502,6 @@ Panel {
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[9]]} }
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[10]]} }
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[11]]} }
TableModelColumn { display: function(modelIndex){return parsedIntrinsic[modelIndex.row][intrinsicModel.columnNames[12]]} }
//https://doc.qt.io/qt-5/qml-qt-labs-qmlmodels-tablemodel.html#appendRow-method
}
@ -541,7 +543,7 @@ Panel {
font.family: MaterialIcons.fontFamily
ToolTip.text: "Next Group (Alt+Right)"
ToolTip.visible: hovered
enabled: root.cameraInitIndex < root.cameraInits.count - 1
enabled: nodesCB.currentIndex < root.cameraInits.count - 1
onClicked: nodesCB.incrementCurrentIndex()
}
}

View file

@ -5,12 +5,12 @@ import QtQuick.Controls 2.3
/**
* SortFilderDelegateModel adds sorting and filtering capabilities on a source model.
*
* The way model data is accessed can be overriden by redefining the modelData function.
* The way model data is accessed can be overridden by redefining the modelData function.
* This is useful if the value is not directly accessible from the model and needs
* some extra logic.
*
* Regarding filtering, any type of value can be used as 'filterValue' (variant).
* Filtering behavior can also be overriden by redefining the respectFilter function.
* Filtering behavior can also be overridden by redefining the respectFilter function.
*
* Based on http://doc.qt.io/qt-5/qtquick-tutorials-dynamicview-dynamicview4-example.html
*/

View file

@ -1,7 +1,7 @@
.pragma library
/**
* Perform 'GET' request on url, and bind 'callback' to onreadystatechange (with XHR objet as parameter).
* Perform 'GET' request on url, and bind 'callback' to onreadystatechange (with XHR object as parameter).
*/
function get(url, callback) {
var xhr = new XMLHttpRequest();

View file

@ -4,8 +4,8 @@ Item {
id: root
// required for perspective transform
property real sizeX: 1675.0 // might be overrided in ColorCheckerViewer
property real sizeY: 1125.0 // might be overrided in ColorCheckerViewer
property real sizeX: 1675.0 // might be overridden in ColorCheckerViewer
property real sizeY: 1125.0 // might be overridden in ColorCheckerViewer
property var colors: null
property var window: null

View file

@ -200,7 +200,7 @@ FloatingPane {
font.pointSize: 10
opacity: featureType.viewer.visible ? 1.0 : 0.6
}
// Tracks visibility toogle
// Tracks visibility toggle
MaterialToolButton {
id: tracksVisibilityButton
checkable: true
@ -213,7 +213,7 @@ FloatingPane {
}
font.pointSize: 10
}
// Matches visibility toogle
// Matches visibility toggle
MaterialToolButton {
id: matchesVisibilityButton
checkable: true
@ -225,7 +225,7 @@ FloatingPane {
}
font.pointSize: 10
}
// Landmarks visibility toogle
// Landmarks visibility toggle
MaterialToolButton {
id: landmarksVisibilityButton
checkable: true

View file

@ -94,7 +94,7 @@ void main()
else
{
// Viewport projection breaks down for one or two vertices.
// Caclulate what we can here and defer rest to fragment shader.
// Calculate what we can here and defer rest to fragment shader.
// Since this is coherent for the entire primitive the conditional
// in the fragment shader is still cheap as all concurrent
// fragment shader invocations will take the same code path.

View file

@ -21,7 +21,7 @@ Entity {
property Layer frontLayerComponent
property var window
/// Camera to consider for positionning
/// Camera to consider for positioning
property Camera camera: null
/// True while at least one media is being loaded
@ -190,7 +190,7 @@ Entity {
// whether MediaLoader has been fully instantiated by the NodeInstantiator
property bool fullyInstantiated: false
// explicitely store some attached model properties for outside use and ease binding
// explicitly store some attached model properties for outside use and ease binding
readonly property var attribute: model.attribute
readonly property int idx: index
readonly property var modelSource: attribute || model.source
@ -216,7 +216,7 @@ Entity {
property string finalSource: model.requested ? currentSource : ""
// To use only if we want to draw the input source and not the current node output (Warning: to use with caution)
// There is maybe a better way to do this to avoid overwritting bindings which should be readonly properties
// There is maybe a better way to do this to avoid overwriting bindings which should be readonly properties
function drawInputSource() {
rawSource = Qt.binding(() => instantiatedEntity.currentNode ? instantiatedEntity.currentNode.attribute("input").value: "")
currentSource = Qt.binding(() => rawSource)

View file

@ -120,7 +120,7 @@ Item {
}
Action {
id: displayLensDistortionToolBarAction
text: "Display Lens Distorsion Toolbar"
text: "Display Lens Distortion Toolbar"
checkable: true
checked: true
enabled: viewer2D.useLensDistortionViewer

View file

@ -613,7 +613,7 @@ ApplicationWindow {
Action {
text: "About Meshroom"
onTriggered: aboutDialog.open()
// shoud be StandardKey.HelpContents, but for some reason it's not stable
// should be StandardKey.HelpContents, but for some reason it's not stable
// (may cause crash, requires pressing F1 twice after closing the popup)
shortcut: "F1"
}

View file

@ -358,8 +358,9 @@ class ViewpointWrapper(QObject):
""" Get camera vertical field of view in degrees. """
if not self.solvedIntrinsics:
return None
pxFocalLength = self.solvedIntrinsics["pxFocalLength"]
return 2.0 * math.atan(self.orientedImageSize.height() / (2.0 * float(pxFocalLength[0]))) * 180 / math.pi
focalLength = self.solvedIntrinsics["focalLength"]
sensorHeight = self.solvedIntrinsics["sensorHeight"]
return 2.0 * math.atan(float(sensorHeight) / (2.0 * float(focalLength))) * 180.0 / math.pi
@Property(type=QUrl, notify=denseSceneParamsChanged)
def undistortedImageSource(self):

View file

@ -87,7 +87,7 @@ class QmlInstantEngine(QQmlApplicationEngine):
self._extensions = extensions
def setVerbose(self, verboseValue):
""" Activate (True) or desactivate (False) the verbose. """
""" Activate (True) or deactivate (False) the verbose. """
self._verbose = verboseValue
def addFile(self, filename):