mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-29 18:27:23 +02:00
Merge branch 'develop' into dev_ml
This commit is contained in:
commit
4e4fce03eb
36 changed files with 236 additions and 78 deletions
|
@ -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},
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
7
meshroom/core/desc.py
Normal file → Executable 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)))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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": "",
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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],
|
||||
),
|
||||
|
|
|
@ -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],
|
||||
),
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"GPU": {
|
||||
"NONE": [],
|
||||
"NORMAL": ["!\"*rnd*\""],
|
||||
"INTENSIVE": ["!\"*rnd*\"", "@.nCPUs>=12"]
|
||||
"NORMAL": ["cuda8G"],
|
||||
"INTENSIVE": ["cuda16G"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -118,7 +118,7 @@ Dialog {
|
|||
font.pointSize: 10
|
||||
}
|
||||
Label {
|
||||
text: "2010-2021 AliceVision contributors"
|
||||
text: "2010-2022 AliceVision contributors"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Add table
Reference in a new issue