From 287c0f13ce1e3862e095d41f3b9b1295bbf8e17f Mon Sep 17 00:00:00 2001 From: Fabien Castan Date: Mon, 16 Oct 2017 10:56:05 +0200 Subject: [PATCH] [core] split Param into specific types and update nodes accordingly --- bin/meshroom_newNodeType | 176 ++++++++++--- meshroom/core/desc.py | 61 ++++- meshroom/nodes/aliceVision/CamPairs.py | 6 +- meshroom/nodes/aliceVision/CameraInit.py | 118 ++++----- meshroom/nodes/aliceVision/DepthMap.py | 4 +- meshroom/nodes/aliceVision/DepthMapFilter.py | 4 +- .../nodes/aliceVision/FeatureExtraction.py | 94 ++++--- meshroom/nodes/aliceVision/FeatureMatching.py | 243 ++++++++---------- meshroom/nodes/aliceVision/Fuse.py | 15 -- meshroom/nodes/aliceVision/ImageMatching.py | 75 +++--- meshroom/nodes/aliceVision/Meshing.py | 4 +- .../nodes/aliceVision/PrepareDenseScene.py | 54 ++-- .../nodes/aliceVision/StructureFromMotion.py | 176 +++++-------- meshroom/nodes/aliceVision/Texturing.py | 4 +- meshroom/nodes/test/appendText.py | 15 +- meshroom/nodes/test/ls.py | 10 +- 16 files changed, 558 insertions(+), 501 deletions(-) delete mode 100644 meshroom/nodes/aliceVision/Fuse.py diff --git a/bin/meshroom_newNodeType b/bin/meshroom_newNodeType index 3892a1fc..5cf2d51e 100755 --- a/bin/meshroom_newNodeType +++ b/bin/meshroom_newNodeType @@ -5,7 +5,7 @@ import argparse import os import re import sys - +from pprint import pprint def trim(s): """ @@ -40,35 +40,63 @@ def convertToLabel(name): snakeToLabel = ' '.join(word.capitalize() for word in snakeToLabel.split(' ')) return snakeToLabel +def is_int(s): + try: + int(s) + return True + except ValueError: + return False + +def is_float(s): + try: + float(s) + return True + except ValueError: + return False + parser = argparse.ArgumentParser(description='Create a new Node Type') -parser.add_argument('node', metavar='NodeName', type=str, +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') parser.add_argument('--output', metavar='DIR', type=str, default=os.path.dirname(__file__), help='Output plugin folder') parser.add_argument('--parser', metavar='PARSER', type=str, default='boost', help='Select the parser adapted for your command line: {boost,cmdLineLib,basic}.') -parser.add_argument("--force", help="Allows to ovewrite the output plugin file.", +parser.add_argument("--force", help="Allows to overwrite the output plugin file.", action="store_true") args = parser.parse_args() -if sys.stdin.isatty(): +inputCmdLineDoc = None +soft = "{nodeType}" +if args.bin: + soft = args.bin + import subprocess + proc = subprocess.Popen(args=[args.bin, '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = proc.communicate() + inputCmdLineDoc = stdout if stdout else stderr +elif sys.stdin.isatty(): + inputCmdLineDoc = ''.join([line for line in sys.stdin]) + +if not inputCmdLineDoc: print('No input documentation.') - print('Usage: YOUR_COMMAND --help | {cmd} YourCommand'.format(cmd=os.path.splitext(__file__)[0])) + print('Usage: YOUR_COMMAND --help | {cmd}'.format(cmd=os.path.splitext(__file__)[0])) exit(-1) -inputCmdLineDoc = ''.join([line for line in sys.stdin]) -outputNodeStr = ''' +outputNodeStr = '''import sys from meshroom.core import desc + class __COMMANDNAME__(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = '{nodeType} {allParams}' -'''.replace('__COMMANDNAME__', args.node) + commandLine = '__SOFT__ {allParams}' +'''.replace('__COMMANDNAME__', args.node).replace('__SOFT__', soft) print(inputCmdLineDoc) @@ -76,25 +104,25 @@ print(inputCmdLineDoc) args_re = None if args.parser == 'boost': args_re = re.compile( - '^\s+' # space(s) - '\[?\s*' # potential '[' - '(?:-(?P\w+)\|?)?' # potential argument short name - '\s*\[?' # potential '[' - '\s*--(?P\w+)' # argument long name + '^\s+' # space(s) + '(?:-(?P\w+)\|?)?' # potential argument short name + '\s*\[?' # potential '[' + '\s*--(?P\w+)' # argument long name '(?:\s*\])?' # potential ']' - '(?:\s+(?P\w+)?)?' # potential arg - '(?:\s+\(\=(?P\w+)\))?' # potential default value - '\s+(?P.*?)\n' # end of the line - '(?P(?:\s+[^-\s].+?\n)*)' # next documentation lines - , re.MULTILINE) + '(?:\s+(?P\w+)?)?' # potential arg + '(?:\s+\(\=(?P.+)\))?' # potential default value + '\s+(?P.*?)\n' # end of the line + '(?P(?:\s+[^-\s].+?\n)*)' # next documentation lines + '', + re.MULTILINE) elif args.parser == 'cmdLineLib': args_re = re.compile( '^' '\[' # '[' - '-(?P\w+)' # argument short name + '-(?P\w+)' # argument short name '\|' - '--(?P\w+)' # argument long name - '(?:\s+(?P\w+)?)?' # potential arg + '--(?P\w+)' # argument long name + '(?:\s+(?P\w+)?)?' # potential arg '\]' # ']' '()' # no default value '(?P.*?)?\n' # end of the line @@ -106,41 +134,131 @@ else: print('Error: Unknown input parser "{}"'.format(args.parser)) exit(-1) +choiceValues_re = re.compile('\* (?P\w+):') +choiceValues2_re = re.compile('\((?P.+?)\)') + inputArgs = args_re.findall(inputCmdLineDoc) print('='*80) +pprint(inputArgs) for inputArg in inputArgs: shortName = inputArg[0] longName = inputArg[1] if longName == 'help': - continue # skip help argument + continue # skip help argument + arg = inputArg[2] value = inputArg[3] description = trim(''.join(inputArg[4:])) + values = choiceValues_re.findall(description) + if not values: + possibleLists = choiceValues2_re.findall(description) + for possibleList in possibleLists: + candidate = possibleList.split(',') + if len(candidate) > 1: + values = [trim(v) for v in candidate] inputArgLower = ' '.join(inputArg).lower() + isBool = (arg == '' and value == '') isFile = 'path' in inputArgLower or 'folder' in inputArgLower or 'file' in inputArgLower + isChoice = bool(values) isOutput = 'output' in inputArgLower - outputNodeStr += """ - {name} = desc.{attributeType}( + isInt = is_int(value) + isFloat = is_float(value) + + if isBool: + outputNodeStr += """ + {name} = desc.BoolParam( + label='{label}', + description='''{description}''', + value={value}, + uid=[0], + )""".format( + name=longName, + label=convertToLabel(longName), + description=description, + value=quotesForStrings(value), + arg=arg, + ) + elif isFile: + outputNodeStr += """ + {name} = desc.File( label='{label}', description='''{description}''', value={value}, - shortName='{shortName}', - arg='{arg}', uid=[0], isOutput={isOutput}, )""".format( name=longName, - attributeType='FileAttribute' if isFile else 'ParamAttribute', label=convertToLabel(longName), description=description, value=quotesForStrings(value), - shortName=shortName, arg=arg, isOutput=isOutput, ) + elif isChoice: + outputNodeStr += """ + {name} = desc.ChoiceParam( + label='{label}', + description='''{description}''', + value={value}, + values={values}, + exclusive={exclusive}, + uid=[0], + )""".format( + name=longName, + label=convertToLabel(longName), + description=description, + value=quotesForStrings(value), + values=values, + exclusive=True, + ) + elif isInt: + outputNodeStr += """ + {name} = desc.IntParam( + label='{label}', + description='''{description}''', + value={value}, + range={range}, + uid=[0], + )""".format( + name=longName, + label=convertToLabel(longName), + description=description, + value=value, + range='(-sys.maxsize, sys.maxsize, 1)', + ) + elif isFloat: + outputNodeStr += """ + {name} = desc.FloatParam( + label='{label}', + description='''{description}''', + value={value}, + range={range}, + uid=[0], + )""".format( + name=longName, + label=convertToLabel(longName), + description=description, + value=value, + range='''(-float('inf'), float('inf'), 0.01)''', + ) + else: + outputNodeStr += """ + {name} = desc.StringParam( + label='{label}', + description='''{description}''', + value={value}, + uid=[0], + )""".format( + name=longName, + label=convertToLabel(longName), + description=description, + value=quotesForStrings(value), + range=range, + ) + outputFilepath = os.path.join(args.output, args.node + '.py') diff --git a/meshroom/core/desc.py b/meshroom/core/desc.py index 9ecacfdc..2975d683 100755 --- a/meshroom/core/desc.py +++ b/meshroom/core/desc.py @@ -7,23 +7,66 @@ class Attribute(object): group = 'allParams' commandLine = '{nodeType} --help' # need to be overridden - def __init__(self, **kwargs): - for k, v in kwargs.items(): - setattr(self, k, v) + def __init__(self, label, description, value, uid, group): + self.label = label + self.description = description + self.value = value + self.uid = uid + self.group = group -class FileAttribute(Attribute): +class Param(Attribute): """ """ - def __init__(self, **kwargs): - super(FileAttribute, self).__init__(**kwargs) + def __init__(self, label, description, value, uid, group): + super(Param, self).__init__(label=label, description=description, value=value, uid=uid, group=group) -class ParamAttribute(Attribute): +class File(Attribute): """ """ - def __init__(self, **kwargs): - super(ParamAttribute, self).__init__(**kwargs) + def __init__(self, label, description, value, uid, isOutput, group='allParams'): + self.isOutput = isOutput + super(File, self).__init__(label=label, description=description, value=value, uid=uid, group=group) + + +class BoolParam(Param): + """ + """ + def __init__(self, label, description, value, uid, group='allParams'): + super(BoolParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group) + + +class IntParam(Param): + """ + """ + def __init__(self, label, description, value, range, uid, group='allParams'): + self.range = range + super(IntParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group) + + +class FloatParam(Param): + """ + """ + def __init__(self, label, description, value, range, uid, group='allParams'): + self.range = range + super(FloatParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group) + + +class ChoiceParam(Param): + """ + """ + def __init__(self, label, description, value, values, exclusive, uid, group='allParams'): + self.values = values + self.exclusive = exclusive + super(ChoiceParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group) + + +class StringParam(Param): + """ + """ + def __init__(self, label, description, value, uid, group='allParams'): + super(StringParam, self).__init__(label=label, description=description, value=value, uid=uid, group=group) class Node(object): diff --git a/meshroom/nodes/aliceVision/CamPairs.py b/meshroom/nodes/aliceVision/CamPairs.py index dee87dba..e6a3d7e6 100644 --- a/meshroom/nodes/aliceVision/CamPairs.py +++ b/meshroom/nodes/aliceVision/CamPairs.py @@ -4,12 +4,10 @@ class CamPairs(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' commandLine = 'CMPMVS {mvsConfigValue} --computeCamPairs' - mvsConfig = desc.FileAttribute( + mvsConfig = desc.File( label='MVS Configuration file', description='', - value=None, - shortName='', - arg='', + value='', uid=[0], isOutput=False, ) diff --git a/meshroom/nodes/aliceVision/CameraInit.py b/meshroom/nodes/aliceVision/CameraInit.py index eae3cc21..a9fb02f6 100644 --- a/meshroom/nodes/aliceVision/CameraInit.py +++ b/meshroom/nodes/aliceVision/CameraInit.py @@ -1,114 +1,88 @@ - +import sys from meshroom.core import desc + class CameraInit(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'openMVG_main_SfMInit_ImageListing {allParams}' + commandLine = 'aliceVision_cameraInit {allParams}' - imageDirectory = desc.FileAttribute( + imageDirectory = desc.File( label='Image Directory', - description='''''', + description='''Input images folder.''', value='', - shortName='i', - arg='', uid=[0], isOutput=False, ) - jsonFile = desc.FileAttribute( + jsonFile = desc.File( label='Json File', description='''Input file with all the user options. It can be used to provide a list of images instead of a directory.''', value='', - shortName='j', - arg='', uid=[0], isOutput=False, ) - sensorWidthDatabase = desc.FileAttribute( - label='Sensor Width Database', - description='''''', + sensorDatabase = desc.File( + label='Sensor Database', + description='''Camera sensor width database path.''', value='', - shortName='d', - arg='', uid=[0], isOutput=False, ) - outputDirectory = desc.FileAttribute( - label='Output Directory', - description='''''', + output = desc.File( + label='Output', + description='''Output directory for the new SfMData file Optional parameters:''', value='{cache}/{nodeType}/{uid0}/', - shortName='o', - arg='', + uid=[], isOutput=True, ) - outputSfm = desc.FileAttribute( # not command line + outputSfm = desc.File( label='Output SfM', description='''''', value='{cache}/{nodeType}/{uid0}/sfm_data.json', - shortName='o', - arg='', + uid=[], isOutput=True, - group='', + group='', # not a command line argument ) - focal = desc.ParamAttribute( - label='Focal', - description='''(pixels)''', - value='', - shortName='f', - arg='', + defaultFocalLengthPix = desc.IntParam( + label='Default Focal Length Pix', + description='''Focal length in pixels.''', + value=-1, + range=(-sys.maxsize, sys.maxsize, 1), uid=[0], - isOutput=False, ) - sensorWidth = desc.ParamAttribute( - label='Sensor Width', - description='''(mm)''', - value='', - shortName='s', - arg='', + defaultSensorWidth = desc.IntParam( + label='Default Sensor Width', + description='''Sensor width in mm.''', + value=-1, + range=(-sys.maxsize, sys.maxsize, 1), uid=[0], - isOutput=False, ) - intrinsics = desc.ParamAttribute( - label='Intrinsics', - description='''Kmatrix: "f;0;ppx;0;f;ppy;0;0;1"''', + defaultIntrinsics = desc.StringParam( + label='Default Intrinsics', + description='''Intrinsics Kmatrix "f;0;ppx;0;f;ppy;0;0;1".''', value='', - shortName='k', - arg='', uid=[0], - isOutput=False, ) - camera_model = desc.ParamAttribute( - label='Camera Model', - description='''Camera model type (pinhole, radial1, radial3, brown or fisheye4)''', + defaultCameraModel = desc.ChoiceParam( + label='Default Camera Model', + description='''Camera model type (pinhole, radial1, radial3, brown, fisheye4).''', value='', - shortName='c', - arg='', + values=['', 'pinhole', 'radial1', 'radial3', 'brown', 'fisheye4'], + exclusive=True, uid=[0], - isOutput=False, ) - group_camera_model = desc.FileAttribute( + groupCameraModel = desc.ChoiceParam( label='Group Camera Model', - description='''0-> each view have its own camera intrinsic parameters, 1-> (default) view share camera intrinsic parameters based on metadata, if no metadata each view has its own camera intrinsic parameters 2-> view share camera intrinsic parameters based on metadata, if no metadata they are grouped by folder''', - value='', - shortName='g', - arg='', + description='''* 0: each view have its own camera intrinsic parameters * 1: view share camera intrinsic parameters based on metadata, if no metadata each view has its own camera intrinsic parameters * 2: view share camera intrinsic parameters based on metadata, if no metadata they are grouped by folder Log parameters:''', + value=1, + values=[0, 1, 2], + exclusive=True, uid=[0], - isOutput=False, ) - use_UID = desc.ParamAttribute( - label='Use U I D', - description='''Generate a UID (unique identifier) for each view. By default, the key is the image index.''', - value='', - shortName='u', - arg='', + verboseLevel = desc.ChoiceParam( + label='Verbose Level', + description='''verbosity level (fatal, error, warning, info, debug, trace).''', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, uid=[0], - isOutput=False, - ) - storeMetadata = desc.ParamAttribute( - label='Store Metadata', - description='''Store image metadata in the sfm data Unrecognized option --help''', - value='', - shortName='m', - arg='', - uid=[0], - isOutput=False, - ) + ) \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/DepthMap.py b/meshroom/nodes/aliceVision/DepthMap.py index 9a8174e5..881b59b7 100644 --- a/meshroom/nodes/aliceVision/DepthMap.py +++ b/meshroom/nodes/aliceVision/DepthMap.py @@ -4,12 +4,10 @@ class DepthMap(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' commandLine = 'CMPMVS {mvsConfigValue} --createDepthmap' - mvsConfig = desc.FileAttribute( + mvsConfig = desc.File( label='MVS Configuration file', description='', value='', - shortName='', - arg='', uid=[0], isOutput=False, ) diff --git a/meshroom/nodes/aliceVision/DepthMapFilter.py b/meshroom/nodes/aliceVision/DepthMapFilter.py index d15f6ebc..d4d5be62 100644 --- a/meshroom/nodes/aliceVision/DepthMapFilter.py +++ b/meshroom/nodes/aliceVision/DepthMapFilter.py @@ -4,12 +4,10 @@ class DepthMapFilter(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' commandLine = 'CMPMVS {mvsConfigValue} --filterDepthmap' - mvsConfig = desc.FileAttribute( + mvsConfig = desc.File( label='MVS Configuration file', description='', value='', - shortName='', - arg='', uid=[0], isOutput=False, ) diff --git a/meshroom/nodes/aliceVision/FeatureExtraction.py b/meshroom/nodes/aliceVision/FeatureExtraction.py index 784cc273..63eb4122 100644 --- a/meshroom/nodes/aliceVision/FeatureExtraction.py +++ b/meshroom/nodes/aliceVision/FeatureExtraction.py @@ -1,70 +1,64 @@ - +import sys from meshroom.core import desc + class FeatureExtraction(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'openMVG_main_ComputeFeatures {allParams}' + commandLine = 'aliceVision_featureExtraction {allParams}' - input_file = desc.FileAttribute( - label='Input File', - description='''a SfM_Data file''', + input = desc.File( + label='Input', + description='''SfMData file.''', value='', - shortName='i', - arg='', uid=[0], isOutput=False, ) - outdir = desc.FileAttribute( - label='Outdir', - description='''output path for the features and descriptors files (*.feat, *.desc) [Optional]''', + output = desc.File( + label='Output', + description='''Output path for the features and descriptors files (*.feat, *.desc). Optional parameters:''', value='{cache}/{nodeType}/{uid0}/', - shortName='o', - arg='path', - uid=[0], + uid=[], isOutput=True, ) - force = desc.ParamAttribute( - label='Force', - description='''Force to recompute data''', - value='', - shortName='f', - arg='', + describerTypes = desc.StringParam( + label='Describer Types', + description='''Describer types to use to describe an image:''', + value='SIFT', uid=[0], - isOutput=False, ) - describerMethods = desc.ParamAttribute( - label='Describer Methods', - description='''(methods to use to describe an image): SIFT (default), SIFT_FLOAT to use SIFT stored as float, AKAZE: AKAZE with floating point descriptors, AKAZE_MLDB: AKAZE with binary descriptors''', - value='', - shortName='m', - arg='', - uid=[0], - isOutput=False, - ) - upright = desc.ParamAttribute( - label='Upright', - description='''Use Upright feature 0 or 1''', - value='', - shortName='u', - arg='', - uid=[0], - isOutput=False, - ) - describerPreset = desc.ParamAttribute( + describerPreset = desc.ChoiceParam( label='Describer Preset', - description='''(used to control the Image_describer configuration): LOW, MEDIUM, NORMAL (default), HIGH, ULTRA: !!Can take long time!!''', - value='', - shortName='p', - arg='', + description='''Control the ImageDescriber configuration (low, medium, normal, high, ultra). Configuration 'ultra' can take long time !''', + value='NORMAL', + values=['low', 'medium', 'normal', 'high', 'ultra'], + exclusive=True, uid=[0], - isOutput=False, ) - jobs = desc.ParamAttribute( - label='Jobs', - description='''Specifies the number of jobs to run simultaneously. Use -j 0 for automatic mode. Unrecognized option --help''', + upright = desc.StringParam( + label='Upright', + description='''Upright feature.''', value='', - shortName='j', - arg='', uid=[0], - isOutput=False, + ) + rangeStart = desc.IntParam( + label='Range Start', + description='''Range image index start.''', + value=-1, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + rangeSize = desc.IntParam( + label='Range Size', + description='''Range size. Log parameters:''', + value=1, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + verboseLevel = desc.ChoiceParam( + label='Verbose Level', + description='''verbosity level (fatal, error, warning, info, debug, trace).''', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, + uid=[0], ) \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/FeatureMatching.py b/meshroom/nodes/aliceVision/FeatureMatching.py index 1242c373..d67ea5fc 100644 --- a/meshroom/nodes/aliceVision/FeatureMatching.py +++ b/meshroom/nodes/aliceVision/FeatureMatching.py @@ -1,187 +1,156 @@ - +import sys from meshroom.core import desc + class FeatureMatching(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'openMVG_main_ComputeMatches {allParams}' + commandLine = 'aliceVision_featureMatching {allParams}' - input_file = desc.FileAttribute( - label='Input File', - description='''a SfM_Data file''', + input = desc.File( + label='Input', + description='''SfMData file.''', value='', - shortName='i', - arg='', uid=[0], isOutput=False, ) - out_dir = desc.FileAttribute( - label='Out Dir', - description='''path to directory in which computed matches will be stored [Optional]''', + output = desc.File( + label='Output', + description='''Path to a directory in which computed matches will be stored. Optional parameters:''', value='{cache}/{nodeType}/{uid0}/', - shortName='o', - arg='path', - uid=[0], + uid=[], isOutput=True, ) - describerMethods = desc.ParamAttribute( - label='Describer Methods', - description='''(methods to use to describe an image): SIFT (default), SIFT_FLOAT to use SIFT stored as float, AKAZE: AKAZE with floating point descriptors, AKAZE_MLDB: AKAZE with binary descriptors use the found model to improve the pairwise correspondences.''', - value='', - shortName='m', - arg='', - uid=[0], - isOutput=False, - ) - featuresDir = desc.FileAttribute( - label='Features Dir', - description='''Path to directory containing the extracted features (default: $out_dir)''', - value='', - shortName='F', - arg='', - uid=[0], - isOutput=False, - ) - save_putative_matches = desc.ParamAttribute( - label='Save Putative Matches', - description='''Save putative matches''', - value='', - shortName='p', - arg='', - uid=[0], - isOutput=False, - ) - ratio = desc.ParamAttribute( - label='Ratio', - description='''Distance ratio to discard non meaningful matches 0.8: (default).''', - value='', - shortName='r', - arg='', - uid=[0], - isOutput=False, - ) - geometric_model = desc.ParamAttribute( + geometricModel = desc.ChoiceParam( label='Geometric Model', - description='''(pairwise correspondences filtering thanks to robust model estimation): f: (default) fundamental matrix, e: essential matrix, h: homography matrix.''', + description='''Pairwise correspondences filtering thanks to robust model estimation: * f: fundamental matrix * e: essential matrix * h: homography matrix''', + value='f', + values=['f', 'e', 'h'], + exclusive=True, + uid=[0], + ) + describerTypes = desc.StringParam( + label='Describer Types', + description='''Describer types to use to describe an image:''', + value='SIFT', + uid=[0], + ) + featuresDirectory = desc.File( + label='Features Directory', + description='''Path to a directory containing the extracted features.''', value='', - shortName='g', - arg='', uid=[0], isOutput=False, ) - video_mode_matching = desc.ParamAttribute( - label='Video Mode Matching', - description='''(sequence matching with an overlap of X images) X: with match 0 with (1->X), ...] 2: will match 0 with (1,2), 1 with (2,3), ... 3: will match 0 with (1,2,3), 1 with (2,3,4), ...''', + imagePairsList = desc.File( + label='Image Pairs List', + description='''Path to a file which contains the list of image pairs to match.''', value='', - shortName='v', - arg='', uid=[0], isOutput=False, ) - pair_list = desc.FileAttribute( - label='Pair List', - description='''filepath A file which contains the list of matches to perform.''', - value='', - shortName='l', - arg='', + photometricMatchingMethod = desc.ChoiceParam( + label='Photometric Matching Method', + description='''For Scalar based regions descriptor: * BRUTE_FORCE_L2: L2 BruteForce matching * ANN_L2: L2 Approximate Nearest Neighbor matching * CASCADE_HASHING_L2: L2 Cascade Hashing matching * FAST_CASCADE_HASHING_L2: L2 Cascade Hashing with precomputed hashed regions (faster than CASCADE_HASHING_L2 but use more memory) For Binary based descriptor: * BRUTE_FORCE_HAMMING: BruteForce Hamming matching''', + value='ANN_L2', + values=['BRUTE_FORCE_L2', 'ANN_L2', 'CASCADE_HASHING_L2', 'FAST_CASCADE_HASHING_L2', 'BRUTE_FORCE_HAMMING'], + exclusive=True, uid=[0], - isOutput=False, ) - range_start = desc.ParamAttribute( - label='Range Start', - description='''range image index start To compute only the matches for specified range. This allows to compute different matches on different computers in parallel.''', - value='', - shortName='s', - arg='', - uid=[0], - isOutput=False, - ) - range_size = desc.ParamAttribute( - label='Range Size', - description='''range size To compute only the matches for specified range. This allows to compute different matches on different computers in parallel.''', - value='', - shortName='d', - arg='', - uid=[0], - isOutput=False, - ) - nearest_matching_method = desc.ParamAttribute( - label='Nearest Matching Method', - description='''For Scalar based regions descriptor: BRUTE_FORCE_L2: L2 BruteForce matching, ANN_L2: L2 Approximate Nearest Neighbor matching (default), CASCADE_HASHING_L2: L2 Cascade Hashing matching. FAST_CASCADE_HASHING_L2: L2 Cascade Hashing with precomputed hashed regions (faster than CASCADE_HASHING_L2 but use more memory). For Binary based descriptor: BRUTE_FORCE_HAMMING: BruteForce Hamming matching.''', - value='', - shortName='n', - arg='', - uid=[0], - isOutput=False, - ) - geometricEstimator = desc.ParamAttribute( + geometricEstimator = desc.ChoiceParam( label='Geometric Estimator', - description='''Geometric estimator acransac: A-Contrario Ransac (default), loransac: LO-Ransac (only available for fundamental matrix)''', - value='', - shortName='G', - arg='', + description='''Geometric estimator: * acransac: A-Contrario Ransac * loransac: LO-Ransac (only available for fundamental matrix)''', + value='acransac', + values=['acransac', 'loransac'], + exclusive=True, uid=[0], - isOutput=False, ) - guided_matching = desc.ParamAttribute( + savePutativeMatches = desc.StringParam( + label='Save Putative Matches', + description='''putative matches.''', + value='', + uid=[0], + ) + guidedMatching = desc.StringParam( label='Guided Matching', - description='''use the found model to improve the pairwise correspondences.''', + description='''the found model to improve the pairwise correspondences.''', value='', - shortName='M', - arg='', uid=[0], - isOutput=False, ) - max_iteration = desc.ParamAttribute( - label='Max Iteration', - description='''number of maximum iterations allowed in ransac step.''', - value='', - shortName='I', - arg='', - uid=[0], - isOutput=False, - ) - match_file_per_image = desc.FileAttribute( + matchFilePerImage = desc.File( label='Match File Per Image', - description='''Save matches in a separate file per image''', + description='''matches in a separate file per image.''', value='', - shortName='x', - arg='', uid=[0], isOutput=False, ) - max_matches = desc.ParamAttribute( - label='Max Matches', - description='''''', - value='', - shortName='u', - arg='', + distanceRatio = desc.FloatParam( + label='Distance Ratio', + description='''Distance ratio to discard non meaningful matches.''', + value=0.800000012, + range=(-float('inf'), float('inf'), 0.01), uid=[0], - isOutput=False, ) - use_grid_sort = desc.ParamAttribute( + videoModeMatching = desc.ChoiceParam( + label='Video Mode Matching', + description='''sequence matching with an overlap of X images: * 0: will match 0 with (1->X), ... * 2: will match 0 with (1,2), 1 with (2,3), ... * 3: will match 0 with (1,2,3), 1 with (2,3,4), ...''', + value=0, + values=['0', '2', '3'], + exclusive=True, + uid=[0], + ) + maxIteration = desc.IntParam( + label='Max Iteration', + description='''Maximum number of iterations allowed in ransac step.''', + value=2048, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + useGridSort = desc.StringParam( label='Use Grid Sort', - description='''Use matching grid sort''', + description='''matching grid sort.''', value='', - shortName='y', - arg='', uid=[0], - isOutput=False, ) - export_debug_files = desc.FileAttribute( + exportDebugFiles = desc.File( label='Export Debug Files', - description='''Export debug files (svg, dot)''', + description='''debug files (svg, dot).''', value='', - shortName='e', - arg='', uid=[0], isOutput=False, ) - fileExtension = desc.FileAttribute( + fileExtension = desc.File( label='File Extension', - description='''File extension to store matches: bin (default), txt Unrecognized option --help''', - value='', - shortName='t', - arg='', + description='''File extension to store matches (bin or txt).''', + value='bin', uid=[0], isOutput=False, + ) + maxMatches = desc.IntParam( + label='Max Matches', + description='''Maximum number pf matches to keep.''', + value=0, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + rangeStart = desc.IntParam( + label='Range Start', + description='''Range image index start.''', + value=-1, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + rangeSize = desc.IntParam( + label='Range Size', + description='''Range size. Log parameters:''', + value=0, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + verboseLevel = desc.ChoiceParam( + label='Verbose Level', + description='''verbosity level (fatal, error, warning, info, debug, trace).''', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, + uid=[0], ) \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/Fuse.py b/meshroom/nodes/aliceVision/Fuse.py deleted file mode 100644 index 8bd9dd17..00000000 --- a/meshroom/nodes/aliceVision/Fuse.py +++ /dev/null @@ -1,15 +0,0 @@ -from meshroom.core import desc - -class Fuse(desc.CommandLineNode): - internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'CMPMVS {mvsConfigValue} --fuse' - - mvsConfig = desc.FileAttribute( - label='MVS Configuration file', - description='', - value='', - shortName='', - arg='', - uid=[0], - isOutput=False, - ) diff --git a/meshroom/nodes/aliceVision/ImageMatching.py b/meshroom/nodes/aliceVision/ImageMatching.py index 83a658d1..bf9e4452 100644 --- a/meshroom/nodes/aliceVision/ImageMatching.py +++ b/meshroom/nodes/aliceVision/ImageMatching.py @@ -1,55 +1,58 @@ - +import sys from meshroom.core import desc + class ImageMatching(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'openMVG_main_generatePairList {allParams}' + commandLine = 'aliceVision_imageMatching {allParams}' - verbose = desc.ParamAttribute( - label='Verbose', - description='''Verbosity level, 0 to mute.''', - value=1, - shortName='v', - arg='arg', - uid=[0], - ) - weights = desc.FileAttribute( - label='Weights', - description='''Input name for the weight file, if not provided the weights will be computed on the database built with the provided set.''', + input = desc.File( + label='Input', + description='''SfMData file or filepath to a simple text file with one image filepath per line, or path to the descriptors folder.''', value='', - shortName='w', - arg='arg', uid=[0], + isOutput=False, ) - tree = desc.FileAttribute( + tree = desc.File( label='Tree', - description='''Input name for the tree file''', + description='''Input name for the vocabulary tree file.''', value='', - shortName='t', - arg='arg', uid=[0], + isOutput=False, ) - keylist = desc.FileAttribute( - label='Keylist', - description='''Path to the list file (list.txt or sfm_data) generated by OpenMVG or the path to a directory containing the descriptors.''', - value='', - shortName='l', - arg='arg', - uid=[0], + output = desc.File( + label='Output', + description='''Filepath to the output file with the list of selected image pairs. Optional parameters:''', + value='{cache}/{nodeType}/{uid0}/', + uid=[], + isOutput=True, ) - nbMaxDescriptors = desc.ParamAttribute( - label='Nb Max Descriptors', + maxDescriptors = desc.IntParam( + label='Max Descriptors', description='''Limit the number of descriptors you load per image. Zero means no limit.''', - value=0, - shortName='m', - arg='arg', + value=500, + range=(-sys.maxsize, sys.maxsize, 1), uid=[0], ) - outfile = desc.FileAttribute( - label='Outfile', - description='''(=pairList.txt) Name of the output file.''', + nbMatches = desc.IntParam( + label='Nb Matches', + description='''The number of matches to retrieve for each image (If 0 it will retrieve all the matches).''', + value=50, + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + weights = desc.File( + label='Weights', + description='''Input name for the weight file, if not provided the weights will be computed on the database built with the provided set. Log parameters:''', value='', - shortName='o', - arg='arg', + uid=[0], + isOutput=False, + ) + verboseLevel = desc.ChoiceParam( + label='Verbose Level', + description='''verbosity level (fatal, error, warning, info, debug, trace).''', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, uid=[0], ) \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/Meshing.py b/meshroom/nodes/aliceVision/Meshing.py index 2bd7b966..9996ceab 100644 --- a/meshroom/nodes/aliceVision/Meshing.py +++ b/meshroom/nodes/aliceVision/Meshing.py @@ -4,12 +4,10 @@ class Meshing(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' commandLine = 'CMPMVS {mvsConfigValue} --meshing' - mvsConfig = desc.FileAttribute( + mvsConfig = desc.File( label='MVS Configuration file', description='', value='', - shortName='', - arg='', uid=[0], isOutput=False, ) diff --git a/meshroom/nodes/aliceVision/PrepareDenseScene.py b/meshroom/nodes/aliceVision/PrepareDenseScene.py index a95bd70f..b86e7c91 100644 --- a/meshroom/nodes/aliceVision/PrepareDenseScene.py +++ b/meshroom/nodes/aliceVision/PrepareDenseScene.py @@ -1,42 +1,46 @@ +import sys from meshroom.core import desc + class PrepareDenseScene(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'openMVG_main_openMVG2CMPMVS2 {allParams}' + commandLine = 'aliceVision_prepareDenseScene {allParams}' - outdir = desc.FileAttribute( - label='Outdir', - description='''path Invalid command line parameter.''', - value='{cache}/{nodeType}/{uid0}/', - shortName='o', - arg='', - isOutput=True, + input = desc.File( + label='Input', + description='''SfMData file.''', + value='', + uid=[0], + isOutput=False, ) - mvsConfig = desc.FileAttribute( # not a command line arg + mvsConfig = desc.File( label='MVS Configuration file', description='', value='{cache}/{nodeType}/{uid0}/_tmp_scale{scaleValue}/mvs.ini', - shortName='', - arg='', - group='', + uid=[0], isOutput=True, + group='', # not a command line arg ) - sfmdata = desc.FileAttribute( - label='Sfmdata', - description='''filename, the SfM_Data file to convert''', - value='', - shortName='i', - arg='', - uid=[0], - isOutput=False, + output = desc.File( + label='Output', + description='''Output directory.''', + value='{cache}/{nodeType}/{uid0}/', + uid=[], + isOutput=True, ) - scale = desc.ParamAttribute( + scale = desc.IntParam( label='Scale', - description='''downscale image factor''', + description='''Image downscale factor.''', value=2, - shortName='s', - arg='', + range=(-sys.maxsize, sys.maxsize, 1), uid=[0], - isOutput=False, ) + verboseLevel = desc.ChoiceParam( + label='Verbose Level', + description='''verbosity level (fatal, error, warning, info, debug, trace).''', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, + uid=[0], + ) \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/StructureFromMotion.py b/meshroom/nodes/aliceVision/StructureFromMotion.py index f2e5a54c..b964ce01 100644 --- a/meshroom/nodes/aliceVision/StructureFromMotion.py +++ b/meshroom/nodes/aliceVision/StructureFromMotion.py @@ -1,133 +1,99 @@ - +import sys from meshroom.core import desc + class StructureFromMotion(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' - commandLine = 'openMVG_main_IncrementalSfM {allParams}' + commandLine = 'aliceVision_incrementalSfM {allParams}' - input_file = desc.FileAttribute( - label='Input File', - description='''path to a SfM_Data scene''', + input = desc.File( + label='Input', + description='''SfMData file.''', value='', - shortName='i', - arg='', uid=[0], isOutput=False, ) - describerMethods = desc.ParamAttribute( - label='Describer Methods', - description='''(methods to use to describe an image): SIFT (default), SIFT_FLOAT to use SIFT stored as float, AKAZE: AKAZE with floating point descriptors, AKAZE_MLDB: AKAZE with binary descriptors''', - value='SIFT', - shortName='d', - arg='', - uid=[0], - isOutput=False, + output = desc.File( + label='Output SfM data file', + description='''Path to the output sfmdata file''', + value='{cache}/{nodeType}/{uid0}/sfm.abc', + uid=[], + isOutput=True, ) - matchdir = desc.FileAttribute( - label='Matchdir', - description='''path to the matches that corresponds to the provided SfM_Data scene''', - value='', - shortName='m', - arg='', - uid=[0], - isOutput=False, - ) - featuresDir = desc.FileAttribute( - label='Features Dir', - description='''path to directory containing the extracted features (default: $matchdir)''', - value='', - shortName='F', - arg='', - uid=[0], - isOutput=False, - ) - outdir = desc.FileAttribute( - label='Outdir', - description='''path where the output data will be stored''', + extraInfoDirectory = desc.File( + label='Output', + description='''Directory for intermediate reconstruction files and additional reconstruction information files.''', value='{cache}/{nodeType}/{uid0}/', - shortName='o', - arg='', uid=[0], isOutput=True, - ) - out_sfmdata_file = desc.FileAttribute( - label='Out Sfmdata File', - description='''path of the output sfmdata file (default: $outdir/sfm_data.json)''', - value='{cache}/{nodeType}/{uid0}/sfm.json', - shortName='s', - arg='', + ) + featuresDirectory = desc.File( + label='Features Directory', + description='''Path to a directory containing the extracted features.''', + value='', uid=[0], - isOutput=True, + isOutput=False, ) - inter_file_extension = desc.FileAttribute( + matchesDirectory = desc.File( + label='Matches Directory', + description='''Path to a directory in which computed matches are stored. Optional parameters:''', + value='', + uid=[0], + isOutput=False, + ) + describerTypes = desc.StringParam( + label='Describer Types', + description='''Describer types to use to describe an image:''', + value='SIFT', + uid=[0], + ) + interFileExtension = desc.File( label='Inter File Extension', - description='''extension of the intermediate file export (default: .ply)''', + description='''Extension of the intermediate file export.''', value='.ply', - shortName='e', - arg='', uid=[0], isOutput=False, ) - # initialPairA = desc.FileAttribute( - # label='Initial Pair A', - # description='''filename of the first image (without path)''', - # value='', - # shortName='a', - # arg='', - # uid=[0], - # isOutput=False, - # ) - # initialPairB = desc.FileAttribute( - # label='Initial Pair B', - # description='''filename of the second image (without path)''', - # value='', - # shortName='b', - # arg='', - # uid=[0], - # isOutput=False, - # ) - camera_model = desc.ParamAttribute( - label='Camera Model', - description='''Camera model type for view with unknown intrinsic: 1: Pinhole 2: Pinhole radial 1 3: Pinhole radial 3 (default)''', - value=3, - shortName='c', - arg='', - uid=[0], - isOutput=False, - ) - refineIntrinsics = desc.ParamAttribute( - label='Refine Intrinsics', - description='''0-> intrinsic parameters are kept as constant 1-> refine intrinsic parameters (default).''', - value=1, - shortName='f', - arg='', - uid=[0], - isOutput=False, - ) - minInputTrackLength = desc.ParamAttribute( + minInputTrackLength = desc.IntParam( label='Min Input Track Length', - description='''minimum track length in input of SfM (default: 2)''', + description='''Minimum track length in input of SfM''', value=2, - shortName='t', - arg='N', + range=(-sys.maxsize, sys.maxsize, 1), + uid=[0], + ) + cameraModel = desc.ChoiceParam( + label='Camera Model', + description='''* 1: Pinhole * 2: Pinhole radial 1 * 3: Pinhole radial 3''', + value=3, + values=['1', '2', '3'], + exclusive=True, + uid=[0], + ) + initialPairA = desc.File( + label='Initial Pair A', + description='''filename of the first image (without path).''', + value='', uid=[0], isOutput=False, ) - # matchFilePerImage = desc.FileAttribute( - # label='Match File Per Image', - # description='''To use one match file per image instead of a global file.''', - # value=1, - # shortName='p', - # arg='', - # uid=[0], - # isOutput=False, - # ) - allowUserInteraction = desc.ParamAttribute( - label='Allow User Interaction', - description='''Enable/Disable user interactions. (default: true) If the process is done on renderfarm, it doesn't make sense to wait for user inputs. Unrecognized option --help''', - value=0, - shortName='u', - arg='', + initialPairB = desc.File( + label='Initial Pair B', + description='''filename of the second image (without path).''', + value='', uid=[0], isOutput=False, + ) + refineIntrinsics = desc.StringParam( + label='Refine Intrinsics', + description='''intrinsic parameters. Log parameters:''', + value='', + uid=[0], + ) + verboseLevel = desc.ChoiceParam( + label='Verbose Level', + description='''verbosity level (fatal, error, warning, info, debug, trace).''', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, + uid=[0], ) \ No newline at end of file diff --git a/meshroom/nodes/aliceVision/Texturing.py b/meshroom/nodes/aliceVision/Texturing.py index 4113e6ee..23dd8eb4 100644 --- a/meshroom/nodes/aliceVision/Texturing.py +++ b/meshroom/nodes/aliceVision/Texturing.py @@ -4,12 +4,10 @@ class Texturing(desc.CommandLineNode): internalFolder = '{cache}/{nodeType}/{uid0}/' commandLine = 'CMPMVS {mvsConfigValue} --texturing' - mvsConfig = desc.FileAttribute( + mvsConfig = desc.File( label='MVS Configuration file', description='', value='', - shortName='', - arg='', uid=[0], isOutput=False, ) diff --git a/meshroom/nodes/test/appendText.py b/meshroom/nodes/test/appendText.py index da912113..665a08bb 100644 --- a/meshroom/nodes/test/appendText.py +++ b/meshroom/nodes/test/appendText.py @@ -3,18 +3,25 @@ from meshroom.core import desc class AppendText(desc.CommandLineNode): commandLine = 'cat {inputValue} > {outputValue} && echo {inputTextValue} >> {outputValue}' - input = desc.FileAttribute( + input = desc.File( label='Input File', + description='''''', + value='', uid=[0], + isOutput=False, ) - output = desc.FileAttribute( + output = desc.File( label='Output', + description='''''', value='{cache}/{nodeType}/{uid0}/appendText.txt', + uid=None, isOutput=True, - hasExpression=True, ) - inputText = desc.FileAttribute( + inputText = desc.File( label='Input Text', + description='''''', + value='', uid=[0], + isOutput=False, ) diff --git a/meshroom/nodes/test/ls.py b/meshroom/nodes/test/ls.py index 532be991..0ce4f0f5 100644 --- a/meshroom/nodes/test/ls.py +++ b/meshroom/nodes/test/ls.py @@ -3,14 +3,18 @@ from meshroom.core import desc class Ls(desc.CommandLineNode): commandLine = 'ls {inputValue} > {outputValue}' - input = desc.FileAttribute( + input = desc.File( label='Input', + description='''''', + value='', uid=[0], + isOutput=False, ) - output = desc.FileAttribute( + output = desc.File( label='Output', + description='''''', value='{cache}/{nodeType}/{uid0}/ls.txt', + uid=None, isOutput=True, - hasExpression=True, )