コード例 #1
0
class SampleNodeV4(desc.Node):
    """
    Changes from V3:
        * 'paramA' has been added
    """
    inputs = [
        desc.File(
            name='in',
            label='Input',
            description='',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(name='paramA',
                           label='ParamA',
                           elementDesc=desc.GroupAttribute(
                               groupDesc=SampleGroupV1,
                               name='gA',
                               label='gA',
                               description=''),
                           description='')
    ]
    outputs = [
        desc.File(name='output',
                  label='Output',
                  description='',
                  value=desc.Node.internalFolder,
                  uid=[])
    ]
コード例 #2
0
    def attributeDescFromValue(attrName, value, isOutput):
        """
        Generate an attribute description (desc.Attribute) that best matches 'value'.

        Args:
            attrName (str): the name of the attribute
            value: the value of the attribute
            isOutput (bool): whether the attribute is an output

        Returns:
            desc.Attribute: the generated attribute description
        """
        params = {
            "name": attrName,
            "label": attrName,
            "description": "Incompatible parameter",
            "value": value,
            "uid": (),
            "group": "incompatible"
        }
        if isinstance(value, bool):
            return desc.BoolParam(**params)
        if isinstance(value, int):
            return desc.IntParam(range=None, **params)
        elif isinstance(value, float):
            return desc.FloatParam(range=None, **params)
        elif isinstance(value, pyCompatibility.basestring):
            if isOutput or os.path.isabs(value) or Attribute.isLinkExpression(
                    value):
                return desc.File(**params)
            else:
                return desc.StringParam(**params)
        # List/GroupAttribute: recursively build descriptions
        elif isinstance(value, (list, dict)):
            del params["value"]
            del params["uid"]
            attrDesc = None
            if isinstance(value, list):
                elt = value[
                    0] if value else ""  # fallback: empty string value if list is empty
                eltDesc = CompatibilityNode.attributeDescFromValue(
                    "element", elt, isOutput)
                attrDesc = desc.ListAttribute(elementDesc=eltDesc, **params)
            elif isinstance(value, dict):
                groupDesc = []
                for key, value in value.items():
                    eltDesc = CompatibilityNode.attributeDescFromValue(
                        key, value, isOutput)
                    groupDesc.append(eltDesc)
                attrDesc = desc.GroupAttribute(groupDesc=groupDesc, **params)
            # override empty default value with
            attrDesc._value = value
            return attrDesc
        # handle any other type of parameters as Strings
        return desc.StringParam(**params)
コード例 #3
0
class Publish(desc.Node):
    size = desc.DynamicNodeSize('inputFiles')
    inputs = [
        desc.ListAttribute(
            elementDesc=desc.File(
                name="input",
                label="Input",
                description="",
                value="",
                uid=[0],
            ),
            name="inputFiles",
            label="Input Files",
            description="Input Files to publish.",
            group="",
        ),
        desc.File(
            name="output",
            label="Output Folder",
            description="",
            value="",
            uid=[0],
        ),
    ]

    def resolvedPaths(self, inputFiles, outDir):
        paths = {}
        for inputFile in inputFiles:
            for f in glob.glob(inputFile.value):
                paths[f] = os.path.join(outDir, os.path.basename(f))
        return paths

    def processChunk(self, chunk):
        print("Publish")
        if not chunk.node.inputFiles:
            print("Nothing to publish")
            return
        if not chunk.node.output.value:
            return

        outFiles = self.resolvedPaths(chunk.node.inputFiles.value,
                                      chunk.node.output.value)

        if not outFiles:
            raise RuntimeError(
                "Publish: input files listed, but nothing to publish. "
                "Listed input files: {}".format(chunk.node.inputFiles.value))

        if not os.path.exists(chunk.node.output.value):
            os.mkdir(chunk.node.output.value)

        for iFile, oFile in outFiles.items():
            print('Publish file', iFile, 'into', oFile)
            shutil.copyfile(iFile, oFile)
        print('Publish end')
コード例 #4
0
class PanoramaExternalInfo(desc.CommandLineNode):
    commandLine = 'aliceVision_panoramaExternalInfo {allParams}'
    size = desc.DynamicNodeSize('input')

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description="SfM Data File",
            value='',
            uid=[0],
        ),
        desc.File(
            name='config',
            label='Xml Config',
            description="XML Data File",
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name='matchesFolder',
                label='Matches Folder',
                description="",
                value='',
                uid=[0],
            ),
            name='matchesFolders',
            label='Matches Folders',
            description=
            "Folder(s) in which computed matches are stored. (WORKAROUND for valid Tractor graph submission)",
            group='forDependencyOnly',
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'Verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='outSfMDataFilename',
            label='Output SfMData File',
            description='Path to the output sfmdata file',
            value=desc.Node.internalFolder + 'sfmData.abc',
            uid=[],
        )
    ]
コード例 #5
0
class SampleNodeV5(desc.Node):
    """
    Changes from V4:
        * 'paramA' elementDesc has changed from SampleGroupV1 to SampleGroupV2
    """
    inputs = [
        desc.File(name='in', label='Input', description='', value='', uid=[0]),
        desc.ListAttribute(name='paramA', label='ParamA',
                           elementDesc=desc.GroupAttribute(
                               groupDesc=SampleGroupV2, name='gA', label='gA', description=''),
                           description='')
    ]
    outputs = [
        desc.File(name='output', label='Output', description='', value=desc.Node.internalFolder, uid=[])
    ]
コード例 #6
0
class Publish(desc.Node):
    size = desc.DynamicNodeSize('inputFiles')
    inputs = [
        desc.ListAttribute(
            elementDesc=desc.File(
                name="input",
                label="Input",
                description="",
                value="",
                uid=[0],
            ),
            name="inputFiles",
            label="Input Files",
            description="Input Files to publish.",
            group="",
        ),
        desc.File(
            name="output",
            label="Output Folder",
            description="",
            value="",
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            '''verbosity level (critical, error, warning, info, debug).''',
            value='info',
            values=['critical', 'error', 'warning', 'info', 'debug'],
            exclusive=True,
            uid=[],
        ),
    ]

    def resolvedPaths(self, inputFiles, outDir):
        paths = {}
        for inputFile in inputFiles:
            for f in glob.glob(inputFile.value):
                paths[f] = os.path.join(outDir, os.path.basename(f))
        return paths

    def processChunk(self, chunk):
        chunk.logManager.waitUntilCleared()
        chunk.logger.setLevel(
            chunk.logManager.textToLevel(chunk.node.verboseLevel.value))

        if not chunk.node.inputFiles:
            chunk.logger.warning('Nothing to publish')
            return
        if not chunk.node.output.value:
            return

        outFiles = self.resolvedPaths(chunk.node.inputFiles.value,
                                      chunk.node.output.value)

        if not outFiles:
            error = 'Publish: input files listed, but nothing to publish'
            chunk.logger.error(error)
            chunk.logger.info('Listed input files: {}'.format(
                [i.value for i in chunk.node.inputFiles.value]))
            raise RuntimeError(error)

        if not os.path.exists(chunk.node.output.value):
            os.mkdir(chunk.node.output.value)

        for iFile, oFile in outFiles.items():
            chunk.logger.info('Publish file {} into {}'.format(iFile, oFile))
            shutil.copyfile(iFile, oFile)
        chunk.logger.info('Publish end')
コード例 #7
0
class ConvertSfMFormat(desc.CommandLineNode):
    commandLine = 'aliceVision_convertSfMFormat {allParams}'
    size = desc.DynamicNodeSize('input')

    documentation = '''
Convert an SfM scene from one file format to another.
It can also be used to remove specific parts of from an SfM scene (like filter all 3D landmarks or filter 2D observations).
'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file.',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='fileExt',
            label='SfM File Format',
            description='SfM File Format',
            value='abc',
            values=['abc', 'sfm', 'json', 'ply', 'baf'],
            exclusive=True,
            uid=[0],
            group='',  # exclude from command line
        ),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types to keep.',
            value=['sift'],
            values=['sift', 'sift_float', 'sift_upright', 'dspsift', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv', 'unknown'],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="imageId",
                label="Image id",
                description="",
                value="",
                uid=[0],
            ),
            name="imageWhiteList",
            label="Image White List",
            description='image white list (uids or image paths).',
        ),
        desc.BoolParam(
            name='views',
            label='Views',
            description='Export views.',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='intrinsics',
            label='Intrinsics',
            description='Export intrinsics.',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='extrinsics',
            label='Extrinsics',
            description='Export extrinsics.',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='structure',
            label='Structure',
            description='Export structure.',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='observations',
            label='Observations',
            description='Export observations.',
            value=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            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],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output',
            description='Path to the output SfM Data file.',
            value=desc.Node.internalFolder + 'sfm.{fileExtValue}',
            uid=[],
            ),
    ]
コード例 #8
0
class SketchfabUpload(desc.Node):
    size = desc.DynamicNodeSize('inputFiles')

    documentation = '''
Upload a textured mesh on Sketchfab.
'''

    inputs = [
        desc.ListAttribute(
            elementDesc=desc.File(
                name="input",
                label="Input",
                description="",
                value="",
                uid=[0],
            ),
            name="inputFiles",
            label="Input Files",
            description="Input Files to export.",
            group="",
        ),
        desc.StringParam(
            name='apiToken',
            label='API Token',
            description=
            'Get your token from https://sketchfab.com/settings/password',
            value='',
            uid=[0],
        ),
        desc.StringParam(
            name='title',
            label='Title',
            description='Title cannot be longer than 48 characters.',
            value='',
            uid=[0],
        ),
        desc.StringParam(
            name='description',
            label='Description',
            description='Description cannot be longer than 1024 characters.',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='license',
            label='License',
            description='License label.',
            value='CC Attribution',
            values=[
                'CC Attribution', 'CC Attribution-ShareAlike',
                'CC Attribution-NoDerivs', 'CC Attribution-NonCommercial',
                'CC Attribution-NonCommercial-ShareAlike',
                'CC Attribution-NonCommercial-NoDerivs'
            ],
            exclusive=True,
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.StringParam(
                name='tag',
                label='Tag',
                description='Tag cannot be longer than 48 characters.',
                value='',
                uid=[0],
            ),
            name="tags",
            label="Tags",
            description="Maximum of 42 separate tags.",
            group="",
        ),
        desc.ChoiceParam(
            name='category',
            label='Category',
            description=
            'Adding categories helps improve the discoverability of your model.',
            value='none',
            values=[
                'none', 'animals-pets', 'architecture', 'art-abstract',
                'cars-vehicles', 'characters-creatures',
                'cultural-heritage-history', 'electronics-gadgets',
                'fashion-style', 'food-drink', 'furniture-home', 'music',
                'nature-plants', 'news-politics', 'people', 'places-travel',
                'science-technology', 'sports-fitness', 'weapons-military'
            ],
            exclusive=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='isPublished',
            label='Publish',
            description=
            'If the model is not published it will be saved as a draft.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='isInspectable',
            label='Inspectable',
            description='Allow 2D view in model inspector.',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='isPrivate',
            label='Private',
            description='Requires a pro account.',
            value=False,
            uid=[0],
        ),
        desc.StringParam(
            name='password',
            label='Password',
            description='Requires a pro account.',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            '''verbosity level (critical, error, warning, info, debug).''',
            value='info',
            values=['critical', 'error', 'warning', 'info', 'debug'],
            exclusive=True,
            uid=[],
        ),
    ]

    def upload(self, apiToken, modelFile, data, chunk):
        modelEndpoint = 'https://api.sketchfab.com/v3/models'
        f = open(modelFile, 'rb')
        file = {'modelFile': (os.path.basename(modelFile), f.read())}
        file.update(data)
        f.close()
        (files, contentType
         ) = requests.packages.urllib3.filepost.encode_multipart_formdata(file)
        headers = {
            'Authorization': 'Token {}'.format(apiToken),
            'Content-Type': contentType
        }
        body = BufferReader(files,
                            progressUpdate,
                            cb_kwargs={'logManager': chunk.logManager},
                            stopped=self.stopped)
        chunk.logger.info('Uploading...')
        try:
            r = requests.post(modelEndpoint, **{
                'data': body,
                'headers': headers
            })
            chunk.logManager.completeProgressBar()
        except requests.exceptions.RequestException as e:
            chunk.logger.error(u'An error occured: {}'.format(e))
            raise RuntimeError()
        if r.status_code != requests.codes.created:
            chunk.logger.error(u'Upload failed with error: {}'.format(
                r.json()))
            raise RuntimeError()

    def resolvedPaths(self, inputFiles):
        paths = []
        for inputFile in inputFiles:
            if os.path.isdir(inputFile.value):
                for path, subdirs, files in os.walk(inputFile.value):
                    for name in files:
                        paths.append(os.path.join(path, name))
            else:
                for f in glob.glob(inputFile.value):
                    paths.append(f)
        return paths

    def stopped(self):
        return self._stopped

    def processChunk(self, chunk):
        try:
            self._stopped = False
            chunk.logManager.start(chunk.node.verboseLevel.value)
            uploadFile = ''

            if not chunk.node.inputFiles:
                chunk.logger.warning('Nothing to upload')
                return
            if chunk.node.apiToken.value == '':
                chunk.logger.error('Need API token.')
                raise RuntimeError()
            if len(chunk.node.title.value) > 48:
                chunk.logger.error(
                    'Title cannot be longer than 48 characters.')
                raise RuntimeError()
            if len(chunk.node.description.value) > 1024:
                chunk.logger.error(
                    'Description cannot be longer than 1024 characters.')
                raise RuntimeError()
            tags = [
                i.value.replace(' ', '-')
                for i in chunk.node.tags.value.values()
            ]
            if all(len(i) > 48 for i in tags) and len(tags) > 0:
                chunk.logger.error('Tags cannot be longer than 48 characters.')
                raise RuntimeError()
            if len(tags) > 42:
                chunk.logger.error('Maximum of 42 separate tags.')
                raise RuntimeError()

            data = {
                'name': chunk.node.title.value,
                'description': chunk.node.description.value,
                'license': chunk.node.license.value,
                'tags': str(tags),
                'isPublished': chunk.node.isPublished.value,
                'isInspectable': chunk.node.isInspectable.value,
                'private': chunk.node.isPrivate.value,
                'password': chunk.node.password.value
            }
            if chunk.node.category.value != 'none':
                data.update({'categories': chunk.node.category.value})
            chunk.logger.debug('Data to be sent: {}'.format(str(data)))

            # pack files into .zip to reduce file size and simplify process
            uploadFile = os.path.join(chunk.node.internalFolder, 'temp.zip')
            files = self.resolvedPaths(chunk.node.inputFiles.value)
            zf = zipfile.ZipFile(uploadFile, 'w')
            for file in files:
                zf.write(file, os.path.basename(file))
            zf.close()
            chunk.logger.debug('Files added to zip: {}'.format(str(files)))
            chunk.logger.debug('Created {}'.format(uploadFile))
            chunk.logger.info('File size: {}MB'.format(
                round(os.path.getsize(uploadFile) / (1024 * 1024), 3)))

            self.upload(chunk.node.apiToken.value, uploadFile, data, chunk)
            chunk.logger.info(
                'Upload successful. Your model is being processed on Sketchfab. It may take some time to show up on your "models" page.'
            )
        except Exception as e:
            chunk.logger.error(e)
            raise RuntimeError()
        finally:
            if os.path.isfile(uploadFile):
                os.remove(uploadFile)
                chunk.logger.debug('Deleted {}'.format(uploadFile))

            chunk.logManager.end()

    def stopProcess(self, chunk):
        self._stopped = True
コード例 #9
0
ファイル: LDRToHDR.py プロジェクト: awilby/meshroom-nonrigid
class LDRToHDR(desc.CommandLineNode):
    commandLine = 'aliceVision_convertLDRToHDR {allParams}'

    inputs = [
        desc.ListAttribute(
            elementDesc=desc.File(
                name='inputFolder',
                label='Input File/Folder',
                description="Folder containing LDR images",
                value='',
                uid=[0],
                ),
            name="input",
            label="Input Files or Folders",
            description='Folders containing LDR images.',
        ),
        desc.BoolParam(
            name='fisheyeLens',
            label='Fisheye Lens',
            description="Enable if a fisheye lens has been used.\n "
                        "This will improve the estimation of the Camera's Response Function by considering only the pixels in the center of the image\n"
                        "and thus ignore undefined/noisy pixels outside the circle defined by the fisheye lens.",
            value=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='calibrationMethod',
            label='Calibration Method',
            description="Method used for camera calibration \n"
                        " * linear \n"
                        " * robertson \n"
                        " * debevec \n"
                        " * grossberg",
            values=['linear', 'robertson', 'debevec', 'grossberg'],
            value='linear',
            exclusive=True,
            uid=[0],
        ),
        desc.File(
            name='inputResponse',
            label='Input Response',
            description="external camera response file path to fuse all LDR images together.",
            value='',
            uid=[0],
        ),
        desc.StringParam(
            name='targetExposureImage',
            label='Target Exposure Image',
            description="LDR image(s) name(s) at the target exposure for the output HDR image(s) to be centered.",
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='calibrationWeight',
            label='Calibration Weight',
            description="Weight function used to calibrate camera response \n"
                        " * default (automatically selected according to the calibrationMethod) \n"
                        " * gaussian \n"
                        " * triangle \n"
                        " * plateau",
            value='default',
            values=['default', 'gaussian', 'triangle', 'plateau'],
            exclusive=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='fusionWeight',
            label='Fusion Weight',
            description="Weight function used to fuse all LDR images together \n"
                        " * gaussian \n"
                        " * triangle \n" 
                        " * plateau",
            value='gaussian',
            values=['gaussian', 'triangle', 'plateau'],
            exclusive=True,
            uid=[0],
        ),
        desc.FloatParam(
            name='expandDynamicRange',
            label='Expand Dynamic Range',
            description="Correction of clamped high values in dynamic range: \n"
                        " - use 0 for no correction \n"
                        " - use 0.5 for interior lighting \n" 
                        " - use 1 for outdoor lighting",
            value=1,
            range=(0, 1, 0.1),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description="Verbosity level (fatal, error, warning, info, debug, trace).",
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
        desc.File(
            name='recoverPath',
            label='Output Recovered Files',
            description="(debug) Folder for recovered LDR images at target exposures.",
            advanced=True,
            value='',
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output Folder',
            description="Output folder for HDR images",
            value=desc.Node.internalFolder,
            uid=[],
        ),
        desc.File(
            name='outputResponse',
            label='Output Response',
            description="Output response function path.",
            value=desc.Node.internalFolder + 'response.csv',
            uid=[],
        ),
    ]
コード例 #10
0
ファイル: PanoramaInit.py プロジェクト: ys-forks/meshroom
class PanoramaInit(desc.CommandLineNode):
    commandLine = 'aliceVision_panoramaInit {allParams}'
    size = desc.DynamicNodeSize('input')

    category = 'Panorama HDR'
    documentation = '''
This node allows to setup the Panorama:

1/ Enables the initialization the cameras from known position in an XML file (provided by
["Roundshot VR Drive"](https://www.roundshot.com/xml_1/internet/fr/application/d394/d395/f396.cfm) ).

2/ Enables to setup Full Fisheye Optics (to use an Equirectangular camera model).

3/ To automatically detects the Fisheye Circle (radius + center) in input images or manually adjust it.

'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description="SfM Data File",
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='initializeCameras',
            label='Initialize Cameras',
            description='Initialize cameras.',
            value='No',
            values=['No', 'File', 'Horizontal', 'Horizontal+Zenith', 'Zenith+Horizontal', 'Spherical'],
            exclusive=True,
            uid=[0],
        ),
        desc.File(
            name='config',
            label='Xml Config',
            description="XML Data File",
            value='',
            uid=[0],
            enabled=lambda node: node.initializeCameras.value == 'File',
        ),
        desc.BoolParam(
            name='yawCW',
            label='Yaw CW',
            description="Yaw ClockWise or CounterClockWise",
            value=1,
            uid=[0],
            enabled=lambda node: ('Horizontal' in node.initializeCameras.value) or (node.initializeCameras.value == "Spherical"),
        ),
        desc.ListAttribute(
            elementDesc=desc.IntParam(
                name='nbViews',
                label='',
                description='',
                value=-1,
                range=[-1, 20],
                uid=[0],
            ),
            name='nbViewsPerLine',
            label='Spherical: Nb Views Per Line',
            description='Number of views per line in Spherical acquisition. Assumes angles from [-90,+90deg] for pitch and [-180,+180deg] for yaw. Use -1 to estimate the number of images automatically.',
            joinChar=',',
            enabled=lambda node: node.initializeCameras.value == 'Spherical',
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name='dependency',
                label='',
                description="",
                value='',
                uid=[],
            ),
            name='dependency',
            label='Dependency',
            description="Folder(s) in which computed features are stored. (WORKAROUND for valid Tractor graph submission)",
            group='forDependencyOnly', # not a command line argument
        ),
        desc.BoolParam(
            name='useFisheye',
            label='Full Fisheye',
            description='To declare a full fisheye panorama setup',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='estimateFisheyeCircle',
            label='Estimate Fisheye Circle',
            description='Automatically estimate the Fisheye Circle center and radius instead of using user values.',
            value=True,
            uid=[0],
            enabled=lambda node: node.useFisheye.value,
        ),
        desc.GroupAttribute(
            name="fisheyeCenterOffset",
            label="Fisheye Center",
            description="Center of the Fisheye circle (XY offset to the center in pixels).",
            groupDesc=[
                desc.FloatParam(
                    name="fisheyeCenterOffset_x", label="x", description="X Offset in pixels",
                    value=0.0,
                    uid=[0],
                    range=(-1000.0, 10000.0, 1.0)),
                desc.FloatParam(
                    name="fisheyeCenterOffset_y", label="y", description="Y Offset in pixels",
                    value=0.0,
                    uid=[0],
                    range=(-1000.0, 10000.0, 1.0)),
                ],
            group=None, # skip group from command line
            enabled=lambda node: node.useFisheye.value and not node.estimateFisheyeCircle.value,
        ),
        desc.FloatParam(
            name='fisheyeRadius',
            label='Radius',
            description='Fisheye visibillity circle radius (% of image shortest side).',
            value=96.0,
            range=(0.0, 150.0, 0.01),
            uid=[0],
            enabled=lambda node: node.useFisheye.value and not node.estimateFisheyeCircle.value,
        ),
        desc.ChoiceParam(
            name='inputAngle',
            label='input Angle offset',
            description='Add a rotation to the input XML given poses (CCW).',
            value='None',
            values=['None', 'rotate90', 'rotate180', 'rotate270'],
            exclusive=True,
            uid=[0]
        ),
        desc.BoolParam(
            name='debugFisheyeCircleEstimation',
            label='Debug Fisheye Circle Detection',
            description='Debug fisheye circle detection.',
            value=False,
            uid=[0],
            enabled=lambda node: node.useFisheye.value,
            advanced=True,
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='Verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='outSfMData',
            label='Output SfMData File',
            description='Path to the output sfmdata file',
            value=desc.Node.internalFolder + 'sfmData.sfm',
            uid=[],
        )
    ]
コード例 #11
0
ファイル: CameraInit.py プロジェクト: zkov96/meshroom
class CameraInit(desc.CommandLineNode):
    commandLine = 'aliceVision_cameraInit {allParams} --allowSingleView 1' # don't throw an error if there is only one image

    size = desc.DynamicNodeSize('viewpoints')

    inputs = [
        desc.ListAttribute(
            name="viewpoints",
            elementDesc=desc.GroupAttribute(name="viewpoint", label="Viewpoint", description="", groupDesc=Viewpoint),
            label="Viewpoints",
            description="Input viewpoints",
            group="",
        ),
        desc.ListAttribute(
            name="intrinsics",
            elementDesc=desc.GroupAttribute(name="intrinsic", label="Intrinsic", description="", groupDesc=Intrinsic),
            label="Intrinsics",
            description="Camera Intrinsics",
            group="",
        ),
        desc.File(
            name='sensorDatabase',
            label='Sensor Database',
            description='''Camera sensor width database path.''',
            value=os.environ.get('ALICEVISION_SENSOR_DB', ''),
            uid=[],
        ),
        desc.FloatParam(
            name='defaultFieldOfView',
            label='Default Field Of View',
            description='Empirical value for the field of view in degree.',
            value=45.0,
            range=(0, 180.0, 1),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='''verbosity level (fatal, error, warning, info, debug, trace).''',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output SfMData File',
            description='''Output SfMData.''',
            value=desc.Node.internalFolder + 'cameraInit.sfm',
            uid=[],
        ),
    ]

    def buildIntrinsics(self, node, additionalViews=()):
        """ Build intrinsics from node current views and optional additional views

        Args:
            node: the CameraInit node instance to build intrinsics for
            additionalViews: (optional) the new views (list of path to images) to add to the node's viewpoints

        Returns:
            The updated views and intrinsics as two separate lists
        """
        assert isinstance(node.nodeDesc, CameraInit)
        assert node.graph is None

        tmpCache = tempfile.mkdtemp()
        node.updateInternals(tmpCache)

        try:
            os.makedirs(os.path.join(tmpCache, node.internalFolder))
            self.createViewpointsFile(node, additionalViews)
            cmd = self.buildCommandLine(node.chunks[0])
            cmd += " --allowIncompleteOutput 1" # don't throw an error if the image intrinsic is undefined
            # logging.debug(' - commandLine:', cmd)
            subprocess = psutil.Popen(cmd, stdout=None, stderr=None, shell=True)
            stdout, stderr = subprocess.communicate()
            subprocess.wait()
            if subprocess.returncode != 0:
                raise RuntimeError('CameraInit failed with error code {}. Command was: "{}"'.format(
                    subprocess.returncode, cmd)
                )

            # Reload result of aliceVision_cameraInit
            cameraInitSfM = node.output.value
            import io  # use io.open for Python2/3 compatibility (allow to specify encoding + errors handling)
            # skip decoding errors to avoid potential exceptions due to non utf-8 characters in images metadata
            with io.open(cameraInitSfM, 'r', encoding='utf-8', errors='ignore') as f:
                data = json.load(f)

            intrinsicsKeys = [i.name for i in Intrinsic]
            intrinsics = [{k: v for k, v in item.items() if k in intrinsicsKeys} for item in data.get("intrinsics", [])]
            for intrinsic in intrinsics:
                pp = intrinsic['principalPoint']
                intrinsic['principalPoint'] = {}
                intrinsic['principalPoint']['x'] = pp[0]
                intrinsic['principalPoint']['y'] = pp[1]
                # convert empty string distortionParams (i.e: Pinhole model) to empty list
                if intrinsic['distortionParams'] == '':
                    intrinsic['distortionParams'] = list()
            # print('intrinsics:', intrinsics)
            viewsKeys = [v.name for v in Viewpoint]
            views = [{k: v for k, v in item.items() if k in viewsKeys} for item in data.get("views", [])]
            for view in views:
                view['metadata'] = json.dumps(view['metadata'])  # convert metadata to string
            # print('views:', views)
            return views, intrinsics

        except Exception:
            raise
        finally:
            shutil.rmtree(tmpCache)

    def createViewpointsFile(self, node, additionalViews=()):
        node.viewpointsFile = ""
        if node.viewpoints or additionalViews:
            newViews = []
            for path in additionalViews:  # format additional views to match json format
                newViews.append({"path": path})
            intrinsics = node.intrinsics.getPrimitiveValue(exportDefault=True)
            for intrinsic in intrinsics:
                intrinsic['principalPoint'] = [intrinsic['principalPoint']['x'], intrinsic['principalPoint']['y']]
            views = node.viewpoints.getPrimitiveValue(exportDefault=False)

            # convert the metadata string into a map
            for view in views:
                if 'metadata' in view:
                    view['metadata'] = json.loads(view['metadata'])

            sfmData = {
                "version": [1, 0, 0],
                "views": views + newViews,
                "intrinsics": intrinsics,
                "featureFolder": "",
                "matchingFolder": "",
            }
            node.viewpointsFile = (node.nodeDesc.internalFolder + '/viewpoints.sfm').format(**node._cmdVars)
            with open(node.viewpointsFile, 'w') as f:
                json.dump(sfmData, f, indent=4)

    def buildCommandLine(self, chunk):
        cmd = desc.CommandLineNode.buildCommandLine(self, chunk)
        if chunk.node.viewpointsFile:
            cmd += ' --input "{}"'.format(chunk.node.viewpointsFile)
        return cmd

    def processChunk(self, chunk):
        self.createViewpointsFile(chunk.node)
        desc.CommandLineNode.processChunk(self, chunk)
コード例 #12
0
ファイル: PrepareDenseScene.py プロジェクト: cs210/Worldsight
class PrepareDenseScene(desc.CommandLineNode):
    commandLine = 'aliceVision_prepareDenseScene {allParams}'
    size = desc.DynamicNodeSize('input')
    parallelization = desc.Parallelization(blockSize=40)
    commandLineRange = '--rangeStart {rangeStart} --rangeSize {rangeBlockSize}'

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='''SfMData file.''',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="imagesFolder",
                label="Images Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="imagesFolders",
            label="Images Folders",
            description=
            'Use images from specific folder(s). Filename should be the same or the image uid.',
        ),
        desc.ChoiceParam(
            name='outputFileType',
            label='Output File Type',
            description='Output file type for the undistorted images.',
            value='exr',
            values=['jpg', 'png', 'tif', 'exr'],
            exclusive=True,
            uid=[0],
            advanced=True),
        desc.BoolParam(
            name='saveMetadata',
            label='Save Metadata',
            description=
            'Save projections and intrinsics information in images metadata (only for .exr images).',
            value=True,
            uid=[0],
            advanced=True),
        desc.BoolParam(
            name='saveMatricesTxtFiles',
            label='Save Matrices Text Files',
            description=
            'Save projections and intrinsics information in text files.',
            value=False,
            uid=[0],
            advanced=True),
        desc.BoolParam(
            name='evCorrection',
            label='Correct images exposure',
            description='Apply a correction on images Exposure Value',
            value=False,
            uid=[0],
            advanced=True),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            '''verbosity level (fatal, error, warning, info, debug, trace).''',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output',
            description='''Output folder.''',
            value=desc.Node.internalFolder,
            uid=[],
        ),
        desc.File(name='outputUndistorted',
                  label='Undistorted images',
                  description='List of undistorted images.',
                  value=desc.Node.internalFolder + '*.{outputFileTypeValue}',
                  uid=[],
                  group='',
                  advanced=True),
    ]
コード例 #13
0
class KeyframeSelection(desc.CommandLineNode):
    commandLine = 'aliceVision_utils_keyframeSelection {allParams}'

    category = 'Utils'
    documentation = '''
Allows to extract keyframes from a video and insert metadata.
It can extract frames from a synchronized multi-cameras rig.

You can extract frames at regular interval by configuring only the min/maxFrameStep.
'''

    inputs = [
        desc.ListAttribute(
            elementDesc=desc.File(
                name="mediaPath",
                label="Media Path",
                description="Media path.",
                value="",
                uid=[0],
            ),
            name='mediaPaths',
            label='Media Paths',
            description='Input video files or image sequence directories.',
        ),
        desc.ListAttribute(elementDesc=desc.File(
            name="brand",
            label="Brand",
            description="Camera brand.",
            value="",
            uid=[0],
        ),
                           name="brands",
                           label="Brands",
                           description="Camera brands."),
        desc.ListAttribute(elementDesc=desc.File(
            name="model",
            label="Model",
            description="Camera model.",
            value="",
            uid=[0],
        ),
                           name="models",
                           label="Models",
                           description="Camera models."),
        desc.ListAttribute(elementDesc=desc.FloatParam(
            name="mmFocal",
            label="mmFocal",
            description="Focal in mm (will be use if not 0).",
            value=0.0,
            range=(0.0, 500.0, 1.0),
            uid=[0],
        ),
                           name="mmFocals",
                           label="mmFocals",
                           description="Focals in mm (will be use if not 0)."),
        desc.ListAttribute(
            elementDesc=desc.FloatParam(
                name="pxFocal",
                label="pxFocal",
                description=
                "Focal in px (will be use and convert in mm if not 0).",
                value=0.0,
                range=(0.0, 500.0, 1.0),
                uid=[0],
            ),
            name="pxFocals",
            label="pxFocals",
            description="Focals in px (will be use and convert in mm if not 0)."
        ),
        desc.ListAttribute(elementDesc=desc.IntParam(
            name="frameOffset",
            label="Frame Offset",
            description="Frame offset.",
            value=0,
            range=(0, 100.0, 1.0),
            uid=[0],
        ),
                           name="frameOffsets",
                           label="Frame Offsets",
                           description="Frame offsets."),
        desc.File(
            name='sensorDbPath',
            label='Sensor Db Path',
            description='''Camera sensor width database path.''',
            value=os.environ.get('ALICEVISION_SENSOR_DB', ''),
            uid=[0],
        ),
        desc.File(
            name='voctreePath',
            label='Voctree Path',
            description='''Vocabulary tree path.''',
            value=os.environ.get('ALICEVISION_VOCTREE', ''),
            uid=[0],
        ),
        desc.BoolParam(
            name='useSparseDistanceSelection',
            label='Use Sparse Distance Selection',
            description=
            'Use sparseDistance selection in order to avoid similar keyframes.',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='useSharpnessSelection',
            label='Use Sharpness Selection',
            description='Use frame sharpness score for keyframe selection.',
            value=True,
            uid=[0],
        ),
        desc.FloatParam(
            name='sparseDistMaxScore',
            label='Sparse Distance Max Score',
            description=
            'Maximum number of strong common points between two keyframes.',
            value=100.0,
            range=(1.0, 200.0, 1.0),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='sharpnessPreset',
            label='Sharpness Preset',
            description=
            'Preset for sharpnessSelection : {ultra, high, normal, low, very_low, none}',
            value='normal',
            values=['ultra', 'high', 'normal', 'low', 'very_low', 'none'],
            exclusive=True,
            uid=[0],
        ),
        desc.IntParam(
            name='sharpSubset',
            label='Sharp Subset',
            description=
            '''sharp part of the image (1 = all, 2 = size/2, ...)''',
            value=4,
            range=(1, 100, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='minFrameStep',
            label='Min Frame Step',
            description='''minimum number of frames between two keyframes''',
            value=12,
            range=(1, 100, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='maxFrameStep',
            label='Max Frame Step',
            description=
            '''maximum number of frames after which a keyframe can be taken''',
            value=36,
            range=(2, 1000, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='maxNbOutFrame',
            label='Max Nb Out Frame',
            description='''maximum number of output frames (0 = no limit)''',
            value=0,
            range=(0, 10000, 1),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='outputFolder',
            label='Output Folder',
            description='''Output keyframes folder for extracted frames.''',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]
コード例 #14
0
class FeatureMatching(desc.CommandLineNode):
    commandLine = 'aliceVision_featureMatching {allParams}'
    size = desc.DynamicNodeSize('input')
    parallelization = desc.Parallelization(blockSize=20)
    commandLineRange = '--rangeStart {rangeStart} --rangeSize {rangeBlockSize}'

    documentation = '''
This node performs the matching of all features between the candidate image pairs.

It is performed in 2 steps:

 1/ **Photometric Matches**

It performs the photometric matches between the set of features descriptors from the 2 input images.
For each feature descriptor on the first image, it looks for the 2 closest descriptors in the second image and uses a relative threshold between them.
This assumption kill features on repetitive structure but has proved to be a robust criterion.

 2/ **Geometric Filtering**

It performs a geometric filtering of the photometric match candidates.
It uses the features positions in the images to make a geometric filtering by using epipolar geometry in an outlier detection framework
called RANSAC (RANdom SAmple Consensus). It randomly selects a small set of feature correspondences and compute the fundamental (or essential) matrix,
then it checks the number of features that validates this model and iterate through the RANSAC framework.

## Online
[https://alicevision.org/#photogrammetry/feature_matching](https://alicevision.org/#photogrammetry/feature_matching)
'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file.',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description="Folder(s) containing the extracted features and descriptors."
        ),
        desc.File(
            name='imagePairsList',
            label='Image Pairs List',
            description='Path to a file which contains the list of image pairs to match.',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=['sift', 'sift_float', 'sift_upright', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv'],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ChoiceParam(
            name='photometricMatchingMethod',
            label='Photometric Matching Method',
            description='For Scalar based regions descriptor\n'
                        ' * BRUTE_FORCE_L2: L2 BruteForce matching\n'
                        ' * ANN_L2: L2 Approximate Nearest Neighbor matching\n'
                        ' * CASCADE_HASHING_L2: L2 Cascade Hashing matching\n'
                        ' * FAST_CASCADE_HASHING_L2: L2 Cascade Hashing with precomputed hashed regions (faster than CASCADE_HASHING_L2 but use more memory) \n'
                        'For Binary based descriptor\n'
                        ' * 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],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='geometricEstimator',
            label='Geometric Estimator',
            description='Geometric estimator: (acransac: A-Contrario Ransac, loransac: LO-Ransac (only available for "fundamental_matrix" model)',
            value='acransac',
            values=['acransac', 'loransac'],
            exclusive=True,
            uid=[0],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='geometricFilterType',
            label='Geometric Filter Type',
            description='Geometric validation method to filter features matches: \n'
                        ' * fundamental_matrix\n'
                        ' * fundamental_with_distortion\n'
                        ' * essential_matrix\n'
                        ' * homography_matrix\n'
                        ' * homography_growing\n'
                        ' * no_filtering',
            value='fundamental_matrix',
            values=['fundamental_matrix', 'fundamental_with_distortion', 'essential_matrix', 'homography_matrix', 'homography_growing', 'no_filtering'],
            exclusive=True,
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='distanceRatio',
            label='Distance Ratio',
            description='Distance ratio to discard non meaningful matches.',
            value=0.8,
            range=(0.0, 1.0, 0.01),
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='maxIteration',
            label='Max Iteration',
            description='Maximum number of iterations allowed in ransac step.',
            value=2048,
            range=(1, 20000, 1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='geometricError',
            label='Geometric Validation Error',
            description='Maximum error (in pixels) allowed for features matching during geometric verification.\n'
                        'If set to 0, it will select a threshold according to the localizer estimator used\n'
                        '(if ACRansac, it will analyze the input data to select the optimal value).',
            value=0.0,
            range=(0.0, 10.0, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='knownPosesGeometricErrorMax',
            label='Known Poses Geometric Error Max',
            description='Maximum error (in pixels) allowed for features matching guided by geometric information from known camera poses.\n'
                        'If set to 0 it lets the ACRansac select an optimal value.',
            value=5.0,
            range=(0.0, 100.0, 1.0),
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='maxMatches',
            label='Max Matches',
            description='Maximum number of matches to keep.',
            value=0,
            range=(0, 10000, 1),
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='savePutativeMatches',
            label='Save Putative Matches',
            description='putative matches.',
            value=False,
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='guidedMatching',
            label='Guided Matching',
            description='the found model to improve the pairwise correspondences.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='matchFromKnownCameraPoses',
            label='Match From Known Camera Poses',
            description='Enable the usage of geometric information from known camera poses to guide the feature matching.\n'
                        'If some cameras have unknown poses (so there is no geometric prior), the standard feature matching will be performed.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='exportDebugFiles',
            label='Export Debug Files',
            description='debug files (svg, dot).',
            value=False,
            uid=[],
            advanced=True
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]
    outputs = [
        desc.File(
            name='output',
            label='Output Folder',
            description='Path to a folder in which computed matches will be stored.',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]
コード例 #15
0
ファイル: ImageMatching.py プロジェクト: zhuofusong/meshroom
class ImageMatching(desc.CommandLineNode):
    commandLine = 'aliceVision_imageMatching {allParams}'
    size = desc.DynamicNodeSize('input')

    documentation = '''
The goal of this node is to select the image pairs to match. The ambition is to find the images that are looking to the same areas of the scene.
Thanks to this node, the FeatureMatching node will only compute the matches between the selected image pairs.

It provides multiple methods:
 * **VocabularyTree**
It uses image retrieval techniques to find images that share some content without the cost of resolving all feature matches in details.
Each image is represented in a compact image descriptor which allows to compute the distance between all images descriptors very efficiently.
If your scene contains less than "Voc Tree: Minimal Number of Images", all image pairs will be selected.
 * **Sequential**
If your input is a video sequence, you can use this option to link images between them over time.
 * **SequentialAndVocabularyTree**
Combines sequential approach with Voc Tree to enable connections between keyframes at different times.
 * **Exhaustive**
Export all image pairs.
 * **Frustum**
If images have known poses, computes the intersection between cameras frustums to create the list of image pairs.
 * **FrustumOrVocabularyTree**
If images have known poses, use frustum intersection else use VocabularuTree.

## Online
[https://alicevision.org/#photogrammetry/image_matching](https://alicevision.org/#photogrammetry/image_matching)
'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file .',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description=
            "Folder(s) containing the extracted features and descriptors."),
        desc.ChoiceParam(
            name='method',
            label='Method',
            description='Method used to select the image pairs to match:\n'
            ' * VocabularyTree:  It uses image retrieval techniques to find images that share some content without the cost of resolving all \n'
            'feature matches in details. Each image is represented in a compact image descriptor which allows to compute the distance between all \n'
            'images descriptors very efficiently. If your scene contains less than "Voc Tree: Minimal Number of Images", all image pairs will be selected.\n'
            ' * Sequential: If your input is a video sequence, you can use this option to link images between them over time.\n'
            ' * SequentialAndVocabularyTree:  Combines sequential approach with VocTree to enable connections between keyframes at different times.\n'
            ' * Exhaustive: Export all image pairs.\n'
            ' * Frustum: If images have known poses, computes the intersection between cameras frustums to create the list of image pairs.\n'
            ' * FrustumOrVocabularyTree: If images have known poses, use frustum intersection else use VocabularyTree.\n',
            value='VocabularyTree',
            values=[
                'VocabularyTree', 'Sequential', 'SequentialAndVocabularyTree',
                'Exhaustive', 'Frustum', 'FrustumOrVocabularyTree'
            ],
            exclusive=True,
            uid=[0],
        ),
        desc.File(
            name='tree',
            label='Voc Tree: Tree',
            description='Input name for the vocabulary tree file.',
            value=os.environ.get('ALICEVISION_VOCTREE', ''),
            uid=[],
            enabled=lambda node: 'VocabularyTree' in node.method.value,
        ),
        desc.File(
            name='weights',
            label='Voc Tree: Weights',
            description=
            'Input name for the weight file, if not provided the weights will be computed on the database built with the provided set.',
            value='',
            uid=[0],
            advanced=True,
            enabled=lambda node: 'VocabularyTree' in node.method.value,
        ),
        desc.IntParam(
            name='minNbImages',
            label='Voc Tree: Minimal Number of Images',
            description=
            'Minimal number of images to use the vocabulary tree. If we have less features than this threshold, we will compute all matching combinations.',
            value=200,
            range=(0, 500, 1),
            uid=[0],
            advanced=True,
            enabled=lambda node: 'VocabularyTree' in node.method.value,
        ),
        desc.IntParam(
            name='maxDescriptors',
            label='Voc Tree: Max Descriptors',
            description=
            'Limit the number of descriptors you load per image. Zero means no limit.',
            value=500,
            range=(0, 100000, 1),
            uid=[0],
            advanced=True,
            enabled=lambda node: 'VocabularyTree' in node.method.value,
        ),
        desc.IntParam(
            name='nbMatches',
            label='Voc Tree: Nb Matches',
            description=
            'The number of matches to retrieve for each image (If 0 it will retrieve all the matches).',
            value=50,
            range=(0, 1000, 1),
            uid=[0],
            advanced=True,
            enabled=lambda node: 'VocabularyTree' in node.method.value,
        ),
        desc.IntParam(
            name='nbNeighbors',
            label='Sequential: Nb Neighbors',
            description=
            'The number of neighbors to retrieve for each image (If 0 it will retrieve all the neighbors).',
            value=50,
            range=(0, 1000, 1),
            uid=[0],
            advanced=True,
            enabled=lambda node: 'Sequential' in node.method.value,
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output List File',
            description=
            'Filepath to the output file with the list of selected image pairs.',
            value=desc.Node.internalFolder + 'imageMatches.txt',
            uid=[],
        ),
    ]
コード例 #16
0
class CameraInit(desc.CommandLineNode):
    commandLine = 'aliceVision_cameraInit {allParams} --allowSingleView 1'  # don't throw an error if there is only one image

    size = desc.DynamicNodeSize('viewpoints')

    inputs = [
        desc.ListAttribute(
            name="viewpoints",
            elementDesc=desc.GroupAttribute(name="viewpoint",
                                            label="Viewpoint",
                                            description="",
                                            groupDesc=Viewpoint),
            label="Viewpoints",
            description="Input viewpoints",
            group="",
        ),
        desc.ListAttribute(
            name="intrinsics",
            elementDesc=desc.GroupAttribute(name="intrinsic",
                                            label="Intrinsic",
                                            description="",
                                            groupDesc=Intrinsic),
            label="Intrinsics",
            description="Camera Intrinsics",
            group="",
        ),
        desc.File(
            name='sensorDatabase',
            label='Sensor Database',
            description='''Camera sensor width database path.''',
            value=os.environ.get('ALICEVISION_SENSOR_DB', ''),
            uid=[],
        ),
        desc.FloatParam(
            name='defaultFieldOfView',
            label='Default Field Of View',
            description='Empirical value for the field of view in degree.',
            value=45.0,
            range=(0, 180.0, 1),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='groupCameraFallback',
            label='Group Camera Fallback',
            description=
            "If there is no serial number in image metadata, devices cannot be accurately identified.\n"
            "Therefore, internal camera parameters cannot be shared among images reliably.\n"
            "A fallback grouping strategy must be chosen:\n"
            " * global: group images from comparable devices (same make/model/focal) globally.\n"
            " * folder: group images from comparable devices only within the same folder.\n"
            " * image: never group images from comparable devices",
            values=['global', 'folder', 'image'],
            value='folder',
            exclusive=True,
            uid=[0],
            advanced=True),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            '''verbosity level (fatal, error, warning, info, debug, trace).''',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output SfMData File',
            description='''Output SfMData.''',
            value=desc.Node.internalFolder + 'cameraInit.sfm',
            uid=[],
        ),
    ]

    def buildIntrinsics(self, node, additionalViews=()):
        """ Build intrinsics from node current views and optional additional views

        Args:
            node: the CameraInit node instance to build intrinsics for
            additionalViews: (optional) the new views (list of path to images) to add to the node's viewpoints

        Returns:
            The updated views and intrinsics as two separate lists
        """
        assert isinstance(node.nodeDesc, CameraInit)
        if node.graph:
            # make a copy of the node outside the graph
            # to change its cache folder without modifying the original node
            node = node.graph.copyNode(node)[0]

        tmpCache = tempfile.mkdtemp()
        node.updateInternals(tmpCache)

        try:
            os.makedirs(os.path.join(tmpCache, node.internalFolder))
            self.createViewpointsFile(node, additionalViews)
            cmd = self.buildCommandLine(node.chunks[0])
            # logging.debug(' - commandLine:', cmd)
            proc = psutil.Popen(cmd, stdout=None, stderr=None, shell=True)
            stdout, stderr = proc.communicate()
            # proc.wait()
            if proc.returncode != 0:
                raise RuntimeError(
                    'CameraInit failed with error code {}.\nCommand was: "{}".\n'
                    .format(proc.returncode, cmd))

            # Reload result of aliceVision_cameraInit
            cameraInitSfM = node.output.value
            return readSfMData(cameraInitSfM)

        except Exception:
            raise
        finally:
            shutil.rmtree(tmpCache)

    def createViewpointsFile(self, node, additionalViews=()):
        node.viewpointsFile = ""
        if node.viewpoints or additionalViews:
            newViews = []
            for path in additionalViews:  # format additional views to match json format
                newViews.append({"path": path})
            intrinsics = node.intrinsics.getPrimitiveValue(exportDefault=True)
            for intrinsic in intrinsics:
                intrinsic['principalPoint'] = [
                    intrinsic['principalPoint']['x'],
                    intrinsic['principalPoint']['y']
                ]
            views = node.viewpoints.getPrimitiveValue(exportDefault=False)

            # convert the metadata string into a map
            for view in views:
                if 'metadata' in view:
                    view['metadata'] = json.loads(view['metadata'])

            sfmData = {
                "version": [1, 0, 0],
                "views": views + newViews,
                "intrinsics": intrinsics,
                "featureFolder": "",
                "matchingFolder": "",
            }
            node.viewpointsFile = (node.nodeDesc.internalFolder +
                                   '/viewpoints.sfm').format(**node._cmdVars)
            with open(node.viewpointsFile, 'w') as f:
                json.dump(sfmData, f, indent=4)

    def buildCommandLine(self, chunk):
        cmd = desc.CommandLineNode.buildCommandLine(self, chunk)
        if chunk.node.viewpointsFile:
            cmd += ' --input "{}"'.format(chunk.node.viewpointsFile)
        return cmd

    def processChunk(self, chunk):
        self.createViewpointsFile(chunk.node)
        desc.CommandLineNode.processChunk(self, chunk)
コード例 #17
0
class StructureFromMotion(desc.CommandLineNode):
    commandLine = 'aliceVision_incrementalSfM {allParams}'
    size = desc.DynamicNodeSize('input')

    documentation = '''
This node will analyze feature matches to understand the geometric relationship behind all the 2D observations,
and infer the rigid scene structure (3D points) with the pose (position and orientation) and internal calibration of all cameras.
The pipeline is a growing reconstruction process (called incremental SfM): it first computes an initial two-view reconstruction that is iteratively extended by adding new views.

1/ Fuse 2-View Matches into Tracks

It fuses all feature matches between image pairs into tracks. Each track represents a candidate point in space, visible from multiple cameras.
However, at this step of the pipeline, it still contains many outliers.

2/ Initial Image Pair

It chooses the best initial image pair. This choice is critical for the quality of the final reconstruction.
It should indeed provide robust matches and contain reliable geometric information.
So, this image pair should maximize the number of matches and the repartition of the corresponding features in each image.
But at the same time, the angle between the cameras should also be large enough to provide reliable geometric information.

3/ Initial 2-View Geometry

It computes the fundamental matrix between the 2 images selected and consider that the first one is the origin of the coordinate system.

4/ Triangulate

Now with the pose of the 2 first cameras, it triangulates the corresponding 2D features into 3D points.

5/ Next Best View Selection

After that, it selects all the images that have enough associations with the features that are already reconstructed in 3D.

6/ Estimate New Cameras

Based on these 2D-3D associations it performs the resectioning of each of these new cameras.
The resectioning is a Perspective-n-Point algorithm (PnP) in a RANSAC framework to find the pose of the camera that validates most of the features associations.
On each camera, a non-linear minimization is performed to refine the pose.

7/ Triangulate

From these new cameras poses, some tracks become visible by 2 or more resected cameras and it triangulates them.

8/ Optimize

It performs a Bundle Adjustment to refine everything: extrinsics and intrinsics parameters of all cameras as well as the position of all 3D points.
It filters the results of the Bundle Adjustment by removing all observations that have high reprojection error or insufficient angles between observations.

9/ Loop from 5 to 9

As we have triangulated new points, we get more image candidates for next best views selection and we can iterate from 5 to 9.
It iterates like that, adding cameras and triangulating new 2D features into 3D points and removing 3D points that became invalidated, until we cannot localize new views.

## Online
[https://alicevision.org/#photogrammetry/sfm](https://alicevision.org/#photogrammetry/sfm)
'''

    inputs = [
        desc.File(
            name='input',
            label='SfMData',
            description='SfMData file.',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description=
            "Folder(s) containing the extracted features and descriptors."),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="matchesFolder",
                label="Matches Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="matchesFolders",
            label="Matches Folders",
            description="Folder(s) in which computed matches are stored."),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=[
                'sift', 'sift_float', 'sift_upright', 'dspsift', 'akaze',
                'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv',
                'akaze_ocv'
            ],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ChoiceParam(
            name='localizerEstimator',
            label='Localizer Estimator',
            description=
            'Estimator type used to localize cameras (acransac, ransac, lsmeds, loransac, maxconsensus).',
            value='acransac',
            values=[
                'acransac', 'ransac', 'lsmeds', 'loransac', 'maxconsensus'
            ],
            exclusive=True,
            uid=[0],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='observationConstraint',
            label='Observation Constraint',
            description='Observation contraint 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='Basic',
            values=['Basic', 'Scale'],
            exclusive=True,
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='localizerEstimatorMaxIterations',
            label='Localizer Max Ransac Iterations',
            description='Maximum number of iterations allowed in ransac step.',
            value=4096,
            range=(1, 20000, 1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='localizerEstimatorError',
            label='Localizer Max Ransac Error',
            description=
            'Maximum error (in pixels) allowed for camera localization (resectioning).\n'
            'If set to 0, it will select a threshold according to the localizer estimator used\n'
            '(if ACRansac, it will analyze the input data to select the optimal value).',
            value=0.0,
            range=(0.0, 100.0, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='lockScenePreviouslyReconstructed',
            label='Lock Scene Previously Reconstructed',
            description=
            'This option is useful for SfM augmentation. Lock previously reconstructed poses and intrinsics.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='useLocalBA',
            label='Local Bundle Adjustment',
            description=
            'It reduces the reconstruction time, especially for large datasets (500+ images),\n'
            'by avoiding computation of the Bundle Adjustment on areas that are not changing.',
            value=True,
            uid=[0],
        ),
        desc.IntParam(
            name='localBAGraphDistance',
            label='LocalBA Graph Distance',
            description=
            'Graph-distance limit to define the Active region in the Local Bundle Adjustment strategy.',
            value=1,
            range=(2, 10, 1),
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='maxNumberOfMatches',
            label='Maximum Number of Matches',
            description=
            'Maximum number of matches per image pair (and per feature type). \n'
            'This can be useful to have a quick reconstruction overview. \n'
            '0 means no limit.',
            value=0,
            range=(0, 50000, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='minNumberOfMatches',
            label='Minimum Number of Matches',
            description=
            'Minimum number of matches per image pair (and per feature type). \n'
            'This can be useful to have a meaningful reconstruction with accurate keypoints. 0 means no limit.',
            value=0,
            range=(0, 50000, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='minInputTrackLength',
            label='Min Input Track Length',
            description='Minimum track length in input of SfM',
            value=2,
            range=(2, 10, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='minNumberOfObservationsForTriangulation',
            label='Min Observation For Triangulation',
            description=
            'Minimum number of observations to triangulate a point.\n'
            'Set it to 3 (or more) reduces drastically the noise in the point cloud,\n'
            'but the number of final poses is a little bit reduced\n'
            '(from 1.5% to 11% on the tested datasets).',
            value=2,
            range=(2, 10, 1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='minAngleForTriangulation',
            label='Min Angle For Triangulation',
            description='Minimum angle for triangulation.',
            value=3.0,
            range=(0.1, 10, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='minAngleForLandmark',
            label='Min Angle For Landmark',
            description='Minimum angle for landmark.',
            value=2.0,
            range=(0.1, 10, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='maxReprojectionError',
            label='Max Reprojection Error',
            description='Maximum reprojection error.',
            value=4.0,
            range=(0.1, 10, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='minAngleInitialPair',
            label='Min Angle Initial Pair',
            description='Minimum angle for the initial pair.',
            value=5.0,
            range=(0.1, 10, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='maxAngleInitialPair',
            label='Max Angle Initial Pair',
            description='Maximum angle for the initial pair.',
            value=40.0,
            range=(0.1, 60, 0.1),
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='useOnlyMatchesFromInputFolder',
            label='Use Only Matches From Input Folder',
            description=
            'Use only matches from the input matchesFolder parameter.\n'
            'Matches folders previously added to the SfMData file will be ignored.',
            value=False,
            uid=[],
            advanced=True,
        ),
        desc.BoolParam(
            name='useRigConstraint',
            label='Use Rig Constraint',
            description='Enable/Disable rig constraint.',
            value=True,
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='lockAllIntrinsics',
            label='Force Lock of All Intrinsic Camera Parameters.',
            description=
            'Force to keep constant all the intrinsics parameters of the cameras (focal length, \n'
            'principal point, distortion if any) during the reconstruction.\n'
            'This may be helpful if the input cameras are already fully calibrated.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='filterTrackForks',
            label='Filter Track Forks',
            description=
            'Enable/Disable the track forks removal. A track contains a fork when incoherent matches \n'
            'lead to multiple features in the same image for a single track. \n',
            value=False,
            uid=[0],
        ),
        desc.File(
            name='initialPairA',
            label='Initial Pair A',
            description='Filename of the first image (without path).',
            value='',
            uid=[0],
        ),
        desc.File(
            name='initialPairB',
            label='Initial Pair B',
            description='Filename of the second image (without path).',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='interFileExtension',
            label='Inter File Extension',
            description='Extension of the intermediate file export.',
            value='.abc',
            values=('.abc', '.ply'),
            exclusive=True,
            uid=[],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'Verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='SfMData',
            description='Path to the output sfmdata file',
            value=desc.Node.internalFolder + 'sfm.abc',
            uid=[],
        ),
        desc.File(
            name='outputViewsAndPoses',
            label='Views and Poses',
            description=
            '''Path to the output sfmdata file with cameras (views and poses).''',
            value=desc.Node.internalFolder + 'cameras.sfm',
            uid=[],
        ),
        desc.File(
            name='extraInfoFolder',
            label='Output Folder',
            description=
            'Folder for intermediate reconstruction files and additional reconstruction information files.',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]
コード例 #18
0
class ExportMatches(desc.CommandLineNode):
    commandLine = 'aliceVision_exportMatches {allParams}'
    size = desc.DynamicNodeSize('input')

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file.',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=['sift', 'sift_float', 'sift_upright', 'dspsift', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv'],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description="Folder(s) containing the extracted features and descriptors."
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="matchesFolder",
                label="Matches Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="matchesFolders",
            label="Matches Folders",
            description="Folder(s) in which computed matches are stored."
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output Folder',
            description='Output path for the features and descriptors files (*.feat, *.desc).',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]
コード例 #19
0
import copy
import pytest

import meshroom.core
from meshroom.core import desc, registerNodeType, unregisterNodeType
from meshroom.core.exception import NodeUpgradeError
from meshroom.core.graph import Graph, loadGraph
from meshroom.core.node import CompatibilityNode, CompatibilityIssue, Node


SampleGroupV1 = [
    desc.IntParam(name="a", label="a", description="", value=0, uid=[0], range=None),
    desc.ListAttribute(
        name="b",
        elementDesc=desc.FloatParam(name="p", label="", description="", value=0.0, uid=[0], range=None),
        label="b",
        description="",
    )
]

SampleGroupV2 = [
    desc.IntParam(name="a", label="a", description="", value=0, uid=[0], range=None),
    desc.ListAttribute(
        name="b",
        elementDesc=desc.GroupAttribute(name="p", label="", description="", groupDesc=SampleGroupV1),
        label="b",
        description="",
    )
]

コード例 #20
0
class ImageProcessing(desc.CommandLineNode):
    commandLine = 'aliceVision_utils_imageProcessing {allParams}'
    size = desc.DynamicNodeSize('input')
    # parallelization = desc.Parallelization(blockSize=40)
    # commandLineRange = '--rangeStart {rangeStart} --rangeSize {rangeBlockSize}'

    documentation = '''
Convert or apply filtering to the input images.
'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description=
            'SfMData file input, image filenames or regex(es) on the image file path.\nsupported regex: \'#\' matches a single digit, \'@\' one or more digits, \'?\' one character and \'*\' zero or more.',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="inputFolder",
                label="input Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="inputFolders",
            label="Images input Folders",
            description='Use images from specific folder(s).',
        ),
        desc.ListAttribute(
            elementDesc=desc.StringParam(
                name="metadataFolder",
                label="Metadata Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="metadataFolders",
            label="Metadata input Folders",
            description='Use images metadata from specific folder(s).',
        ),
        desc.ChoiceParam(
            name='extension',
            label='Output File Extension',
            description='Output Image File Extension.',
            value='',
            values=['', 'exr', 'jpg', 'tiff', 'png'],
            exclusive=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='reconstructedViewsOnly',
            label='Only Reconstructed Views',
            description='Process Only Reconstructed Views',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='fixNonFinite',
            label='Fix Non-Finite',
            description=
            'Fix non-finite pixels based on neighboring pixels average.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='exposureCompensation',
            label='Exposure Compensation',
            description='Exposure Compensation',
            value=False,
            uid=[0],
        ),
        desc.FloatParam(
            name='scaleFactor',
            label='ScaleFactor',
            description='Scale Factor.',
            value=1.0,
            range=(0.0, 1.0, 0.01),
            uid=[0],
        ),
        desc.FloatParam(
            name='contrast',
            label='Contrast',
            description='Contrast.',
            value=1.0,
            range=(0.0, 100.0, 0.1),
            uid=[0],
        ),
        desc.IntParam(
            name='medianFilter',
            label='Median Filter',
            description='Median Filter.',
            value=0,
            range=(0, 10, 1),
            uid=[0],
        ),
        desc.BoolParam(
            name='fillHoles',
            label='Fill Holes',
            description='Fill holes based on the alpha channel.\n'
            'Note: It will enable fixNonFinite, as it is required for the image pyramid construction used to fill holes.',
            value=False,
            uid=[0],
        ),
        desc.GroupAttribute(name="sharpenFilter",
                            label="Sharpen Filter",
                            description="Sharpen Filtering Parameters.",
                            joinChar=":",
                            groupDesc=[
                                desc.BoolParam(
                                    name='sharpenFilterEnabled',
                                    label='Enable',
                                    description='Use sharpen.',
                                    value=False,
                                    uid=[0],
                                ),
                                desc.IntParam(
                                    name='width',
                                    label='Width',
                                    description='Sharpen Width.',
                                    value=3,
                                    range=(1, 9, 2),
                                    uid=[0],
                                    enabled=lambda node: node.sharpenFilter.
                                    sharpenFilterEnabled.value,
                                ),
                                desc.FloatParam(
                                    name='contrast',
                                    label='Contrast',
                                    description='Sharpen Contrast.',
                                    value=1.0,
                                    range=(0.0, 100.0, 0.1),
                                    uid=[0],
                                    enabled=lambda node: node.sharpenFilter.
                                    sharpenFilterEnabled.value,
                                ),
                                desc.FloatParam(
                                    name='threshold',
                                    label='Threshold',
                                    description='Sharpen Threshold.',
                                    value=0.0,
                                    range=(0.0, 1.0, 0.01),
                                    uid=[0],
                                    enabled=lambda node: node.sharpenFilter.
                                    sharpenFilterEnabled.value,
                                ),
                            ]),
        desc.GroupAttribute(
            name="bilateralFilter",
            label="Bilateral Filter",
            description="Bilateral Filtering Parameters.",
            joinChar=":",
            groupDesc=[
                desc.BoolParam(
                    name='bilateralFilterEnabled',
                    label='Enable',
                    description='Bilateral Filter.',
                    value=False,
                    uid=[0],
                ),
                desc.IntParam(
                    name='bilateralFilterDistance',
                    label='Distance',
                    description=
                    'Diameter of each pixel neighborhood that is used during bilateral filtering.\nCould be very slow for large filters, so it is recommended to use 5.',
                    value=0,
                    range=(0, 9, 1),
                    uid=[0],
                    enabled=lambda node: node.bilateralFilter.
                    bilateralFilterEnabled.value,
                ),
                desc.FloatParam(
                    name='bilateralFilterSigmaSpace',
                    label='Sigma Coordinate Space',
                    description=
                    'Bilateral Filter sigma in the coordinate space.',
                    value=0.0,
                    range=(0.0, 150.0, 0.01),
                    uid=[0],
                    enabled=lambda node: node.bilateralFilter.
                    bilateralFilterEnabled.value,
                ),
                desc.FloatParam(
                    name='bilateralFilterSigmaColor',
                    label='Sigma Color Space',
                    description='Bilateral Filter sigma in the color space.',
                    value=0.0,
                    range=(0.0, 150.0, 0.01),
                    uid=[0],
                    enabled=lambda node: node.bilateralFilter.
                    bilateralFilterEnabled.value,
                ),
            ]),
        desc.GroupAttribute(
            name="claheFilter",
            label="Clahe Filter",
            description="Clahe Filtering Parameters.",
            joinChar=":",
            groupDesc=[
                desc.BoolParam(
                    name='claheEnabled',
                    label='Enable',
                    description=
                    'Use Contrast Limited Adaptive Histogram Equalization (CLAHE) Filter.',
                    value=False,
                    uid=[0],
                ),
                desc.FloatParam(
                    name='claheClipLimit',
                    label='Clip Limit',
                    description='Sets Threshold For Contrast Limiting.',
                    value=4.0,
                    range=(0.0, 8.0, 1.0),
                    uid=[0],
                    enabled=lambda node: node.claheFilter.claheEnabled.value,
                ),
                desc.IntParam(
                    name='claheTileGridSize',
                    label='Tile Grid Size',
                    description=
                    'Sets Size Of Grid For Histogram Equalization. Input Image Will Be Divided Into Equally Sized Rectangular Tiles.',
                    value=8,
                    range=(4, 64, 4),
                    uid=[0],
                    enabled=lambda node: node.claheFilter.claheEnabled.value,
                ),
            ]),
        desc.GroupAttribute(
            name="noiseFilter",
            label="Noise Filter",
            description="Noise Filtering Parameters.",
            joinChar=":",
            groupDesc=[
                desc.BoolParam(
                    name='noiseEnabled',
                    label='Enable',
                    description='Add Noise.',
                    value=False,
                    uid=[0],
                ),
                desc.ChoiceParam(
                    name='noiseMethod',
                    label='Method',
                    description=
                    " * method: There are several noise types to choose from:\n"
                    " * uniform: adds noise values uninformly distributed on range [A,B).\n"
                    " * gaussian: adds Gaussian (normal distribution) noise values with mean value A and standard deviation B.\n"
                    " * salt: changes to value A a portion of pixels given by B.\n",
                    value='uniform',
                    values=['uniform', 'gaussian', 'salt'],
                    exclusive=True,
                    uid=[0],
                    enabled=lambda node: node.noiseFilter.noiseEnabled.value,
                ),
                desc.FloatParam(
                    name='noiseA',
                    label='A',
                    description=
                    'Parameter that have a different interpretation depending on the method chosen.',
                    value=0.0,
                    range=(0.0, 1.0, 0.0001),
                    uid=[0],
                    enabled=lambda node: node.noiseFilter.noiseEnabled.value,
                ),
                desc.FloatParam(
                    name='noiseB',
                    label='B',
                    description=
                    'Parameter that have a different interpretation depending on the method chosen.',
                    value=1.0,
                    range=(0.0, 1.0, 0.0001),
                    uid=[0],
                    enabled=lambda node: node.noiseFilter.noiseEnabled.value,
                ),
                desc.BoolParam(
                    name='noiseMono',
                    label='Mono',
                    description=
                    'If is Checked, a single noise value will be applied to all channels otherwise a separate noise value will be computed for each channel.',
                    value=True,
                    uid=[0],
                    enabled=lambda node: node.noiseFilter.noiseEnabled.value,
                ),
            ]),
        desc.ChoiceParam(
            name='outputFormat',
            label='Output Image Format',
            description='Allows you to choose the format of the output image.',
            value='rgba',
            values=['rgba', 'rgb', 'grayscale'],
            exclusive=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='storageDataType',
            label='Storage Data Type for EXR output',
            description='Storage image data type:\n'
            ' * float: Use full floating point (32 bits per channel)\n'
            ' * half: Use half float (16 bits per channel)\n'
            ' * halfFinite: Use half float, but clamp values to avoid non-finite values\n'
            ' * auto: Use half float if all values can fit, else use full float\n',
            value='float',
            values=['float', 'half', 'halfFinite', 'auto'],
            exclusive=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='outSfMData',
            label='Output sfmData',
            description='Output sfmData.',
            value=lambda attr: (desc.Node.internalFolder + os.path.basename(
                attr.node.input.value)) if (os.path.splitext(
                    attr.node.input.value)[1] in ['.abc', '.sfm']) else '',
            uid=[],
            group='',  # do not export on the command line
        ),
        desc.File(
            name='output',
            label='Output Folder',
            description='Output Images Folder.',
            value=desc.Node.internalFolder,
            uid=[],
        ),
        desc.File(
            name='outputImages',
            label='Output Images',
            description='Output Image Files.',
            value=outputImagesValueFunct,
            group='',  # do not export on the command line
            uid=[],
        ),
    ]
コード例 #21
0
class GlobalSfM(desc.CommandLineNode):
    commandLine = 'aliceVision_globalSfM {allParams}'
    size = desc.DynamicNodeSize('input')

    documentation = '''
Performs the Structure-From-Motion with a global approach.
It is known to be faster but less robust to challenging datasets than the Incremental approach.
'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description="SfM Data File",
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name='featuresFolder',
                label='Features Folder',
                description="",
                value='',
                uid=[0],
            ),
            name='featuresFolders',
            label='Features Folders',
            description="Folder(s) containing the extracted features."),
        desc.ListAttribute(
            elementDesc=desc.File(
                name='matchesFolder',
                label='Matches Folder',
                description="",
                value='',
                uid=[0],
            ),
            name='matchesFolders',
            label='Matches Folders',
            description="Folder(s) in which computed matches are stored."),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=[
                'sift', 'sift_float', 'sift_upright', 'dspsift', 'akaze',
                'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv',
                'akaze_ocv'
            ],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ChoiceParam(
            name='rotationAveraging',
            label='Rotation Averaging Method',
            description="Method for rotation averaging :\n"
            " * L1 minimization\n"
            " * L2 minimization\n",
            values=['L1_minimization', 'L2_minimization'],
            value='L2_minimization',
            exclusive=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='translationAveraging',
            label='Translation Averaging Method',
            description="Method for translation averaging :\n"
            " * L1 minimization\n"
            " * L2 minimization of sum of squared Chordal distances\n"
            " * L1 soft minimization",
            values=[
                'L1_minimization', 'L2_minimization', 'L1_soft_minimization'
            ],
            value='L1_soft_minimization',
            exclusive=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='lockAllIntrinsics',
            label='Force Lock of All Intrinsic Camera Parameters.',
            description=
            'Force to keep constant all the intrinsics parameters of the cameras (focal length, \n'
            'principal point, distortion if any) during the reconstruction.\n'
            'This may be helpful if the input cameras are already fully calibrated.',
            value=False,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'Verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output SfMData File',
            description='Path to the output sfmdata file',
            value=desc.Node.internalFolder + 'sfm.abc',
            uid=[],
        ),
        desc.File(
            name='outputViewsAndPoses',
            label='Output Poses',
            description=
            '''Path to the output sfmdata file with cameras (views and poses).''',
            value=desc.Node.internalFolder + 'cameras.sfm',
            uid=[],
        ),
        desc.File(
            name='extraInfoFolder',
            label='Output Folder',
            description=
            'Folder for intermediate reconstruction files and additional reconstruction information files.',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]
コード例 #22
0
class ImageMatchingMultiSfM(desc.CommandLineNode):
    commandLine = 'aliceVision_imageMatching {allParams}'
    # use both SfM inputs to define Node's size
    size = desc.MultiDynamicNodeSize(['input', 'inputB'])

    inputs = [
        desc.File(
            name='input',
            label='Input A',
            description='SfMData file .',
            value='',
            uid=[0],
        ),
        desc.File(
            name='inputB',
            label='Input B',
            description='SfMData file .',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description="Folder(s) containing the extracted features and descriptors."
        ),
        desc.ChoiceParam(
            name='method',
            label='Method',
            description='Method used to select the image pairs to match.',
            value='VocabularyTree',
            values=['VocabularyTree', 'Sequential', 'SequentialAndVocabularyTree','Exhaustive','Frustum'],
            exclusive=True,
            uid=[0],
        ),
        desc.File(
            name='tree',
            label='Voc Tree: Tree',
            description='Input name for the vocabulary tree file.',
            value=os.environ.get('ALICEVISION_VOCTREE', ''),
            uid=[],
        ),
        desc.File(
            name='weights',
            label='Voc Tree: Weights',
            description='Input name for the weight file, if not provided the weights will be computed on the database built with the provided set.',
            value='',
            uid=[0],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='matchingMode',
            label='Matching Mode',
            description='The mode to combine image matching between the input SfMData A and B:\n"a/a+a/b" for A with A + A with B.\n"a/ab" for A with A and B.\n"a/b" for A with B.',
            value='a/a+a/b',
            values=['a/a+a/b','a/ab', 'a/b'],
            exclusive=True,
            uid=[0],
        ),
        desc.IntParam(
            name='minNbImages',
            label='Voc Tree: Minimal Number of Images',
            description='Minimal number of images to use the vocabulary tree. If we have less features than this threshold, we will compute all matching combinations.',
            value=200,
            range=(0, 500, 1),
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='maxDescriptors',
            label='Voc Tree: Max Descriptors',
            description='Limit the number of descriptors you load per image. Zero means no limit.',
            value=500,
            range=(0, 100000, 1),
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='nbMatches',
            label='Voc Tree: Nb Matches',
            description='The number of matches to retrieve for each image (If 0 it will retrieve all the matches).',
            value=50,
            range=(0, 1000, 1),
            uid=[0],
            advanced=True,
        ),
        desc.IntParam(
            name='nbNeighbors',
            label='Sequential: Nb Neighbors',
            description='The number of neighbors to retrieve for each image (If 0 it will retrieve all the neighbors).',
            value=50,
            range=(0, 1000, 1),
            uid=[0],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output List File',
            description='Filepath to the output file with the list of selected image pairs.',
            value=desc.Node.internalFolder + 'imageMatches.txt',
            uid=[],
        ),
        desc.File(
            name='outputCombinedSfM',
            label='Output Combined SfM',
            description='Path for the combined SfMData file',
            value=desc.Node.internalFolder + 'combineSfM.sfm',
            uid=[],
        ),
    ]
コード例 #23
0
class SfMTransform(desc.CommandLineNode):
    commandLine = 'aliceVision_utils_sfmTransform {allParams}'
    size = desc.DynamicNodeSize('input')

    documentation = '''
This node allows to change the coordinate system of one SfM scene.

The transformation can be based on:
 * transformation: Apply a given transformation
 * auto_from_cameras: Fit all cameras into a box [-1,1]
 * auto_from_landmarks: Fit all landmarks into a box [-1,1]
 * from_single_camera: Use a specific camera as the origin of the coordinate system
 * from_markers: Align specific markers to custom coordinates

'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='''SfMData file .''',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='method',
            label='Transformation Method',
            description="Transformation method:\n"
                        " * transformation: Apply a given transformation\n"
                        " * manual: Apply the gizmo transformation (show the transformed input)\n"
                        " * auto_from_cameras: Use cameras\n"
                        " * auto_from_landmarks: Use landmarks\n"
                        " * from_single_camera: Use a specific camera as the origin of the coordinate system\n"
                        " * from_markers: Align specific markers to custom coordinates",
            value='auto_from_landmarks',
            values=['transformation', 'manual', 'auto_from_cameras', 'auto_from_landmarks', 'from_single_camera', 'from_markers'],
            exclusive=True,
            uid=[0],
        ),
        desc.StringParam(
            name='transformation',
            label='Transformation',
            description="Required only for 'transformation' and 'from_single_camera' methods:\n"
                        " * transformation: Align [X,Y,Z] to +Y-axis, rotate around Y by R deg, scale by S; syntax: X,Y,Z;R;S\n"
                        " * from_single_camera: Camera UID or image filename",
            value='',
            uid=[0],
            enabled=lambda node: node.method.value == "transformation" or node.method.value == "from_single_camera",
        ),
        desc.GroupAttribute(
            name="manualTransform",
            label="Manual Transform (Gizmo)",
            description="Translation, rotation (Euler ZXY) and uniform scale.",
            groupDesc=[
                desc.GroupAttribute(
                    name="manualTranslation",
                    label="Translation",
                    description="Translation in space.",
                    groupDesc=[
                        desc.FloatParam(
                            name="x", label="x", description="X Offset",
                            value=0.0,
                            uid=[0],
                            range=(-20.0, 20.0, 0.01)
                        ),
                        desc.FloatParam(
                            name="y", label="y", description="Y Offset",
                            value=0.0,
                            uid=[0],
                            range=(-20.0, 20.0, 0.01)
                        ),
                        desc.FloatParam(
                            name="z", label="z", description="Z Offset",
                            value=0.0,
                            uid=[0],
                            range=(-20.0, 20.0, 0.01)
                        )
                    ],
                    joinChar=","
                ),
                desc.GroupAttribute(
                    name="manualRotation",
                    label="Euler Rotation",
                    description="Rotation in Euler degrees.",
                    groupDesc=[
                        desc.FloatParam(
                            name="x", label="x", description="Euler X Rotation",
                            value=0.0,
                            uid=[0],
                            range=(-90.0, 90.0, 1)
                        ),
                        desc.FloatParam(
                            name="y", label="y", description="Euler Y Rotation",
                            value=0.0,
                            uid=[0],
                            range=(-180.0, 180.0, 1)
                        ),
                        desc.FloatParam(
                            name="z", label="z", description="Euler Z Rotation",
                            value=0.0,
                            uid=[0],
                            range=(-180.0, 180.0, 1)
                        )
                    ],
                    joinChar=","
                ),
                desc.FloatParam(
                    name="manualScale",
                    label="Scale",
                    description="Uniform Scale.",
                    value=1.0,
                    uid=[0],
                    range=(0.0, 20.0, 0.01)
                )
            ],
            joinChar=",",
            enabled=lambda node: node.method.value == "manual",
        ),
        desc.ChoiceParam(
            name='landmarksDescriberTypes',
            label='Landmarks Describer Types',
            description='Image describer types used to compute the mean of the point cloud. (only for "landmarks" method).',
            value=['sift', 'dspsift', 'akaze'],
            values=['sift', 'sift_float', 'sift_upright', 'dspsift', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv', 'unknown'],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.FloatParam(
            name='scale',
            label='Additional Scale',
            description='Additional scale to apply.',
            value=1.0,
            range=(0.0, 100.0, 0.1),
            uid=[0],
        ),
        desc.ListAttribute(
            name="markers",
            elementDesc=desc.GroupAttribute(name="markerAlign", label="Marker Align", description="", joinChar=":", groupDesc=[
                desc.IntParam(name="markerId", label="Marker", description="Marker Id", value=0, uid=[0], range=(0, 32, 1)),
                desc.GroupAttribute(name="markerCoord", label="Coord", description="", joinChar=",", groupDesc=[
                    desc.FloatParam(name="x", label="x", description="", value=0.0, uid=[0], range=(-2.0, 2.0, 1.0)),
                    desc.FloatParam(name="y", label="y", description="", value=0.0, uid=[0], range=(-2.0, 2.0, 1.0)),
                    desc.FloatParam(name="z", label="z", description="", value=0.0, uid=[0], range=(-2.0, 2.0, 1.0)),
                ])
            ]),
            label="Markers",
            description="Markers alignment points",
        ),
        desc.BoolParam(
            name='applyScale',
            label='Scale',
            description='Apply scale transformation.',
            value=True,
            uid=[0],
            enabled=lambda node: node.method.value != "manual",
        ),
        desc.BoolParam(
            name='applyRotation',
            label='Rotation',
            description='Apply rotation transformation.',
            value=True,
            uid=[0],
            enabled=lambda node: node.method.value != "manual",
        ),
        desc.BoolParam(
            name='applyTranslation',
            label='Translation',
            description='Apply translation transformation.',
            value=True,
            uid=[0],
            enabled=lambda node: node.method.value != "manual",
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='''verbosity level (fatal, error, warning, info, debug, trace).''',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output SfMData File',
            description='''Aligned SfMData file .''',
            value=lambda attr: desc.Node.internalFolder + (os.path.splitext(os.path.basename(attr.node.input.value))[0] or 'sfmData') + '.abc',
            uid=[],
        ),
        desc.File(
            name='outputViewsAndPoses',
            label='Output Poses',
            description='''Path to the output sfmdata file with cameras (views and poses).''',
            value=desc.Node.internalFolder + 'cameras.sfm',
            uid=[],
        ),
    ]
コード例 #24
0
class ImageMatching(desc.CommandLineNode):
    commandLine = 'aliceVision_imageMatching {allParams}'
    size = desc.DynamicNodeSize('input')

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file .',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description=
            "Folder(s) containing the extracted features and descriptors."),
        desc.File(
            name='tree',
            label='Tree',
            description='Input name for the vocabulary tree file.',
            value=os.environ.get('ALICEVISION_VOCTREE', ''),
            uid=[],
        ),
        desc.File(
            name='weights',
            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.',
            value='',
            uid=[0],
        ),
        desc.IntParam(
            name='minNbImages',
            label='Minimal Number of Images',
            description=
            'Minimal number of images to use the vocabulary tree. If we have less features than this threshold, we will compute all matching combinations.',
            value=200,
            range=(0, 500, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='maxDescriptors',
            label='Max Descriptors',
            description=
            'Limit the number of descriptors you load per image. Zero means no limit.',
            value=500,
            range=(0, 100000, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='nbMatches',
            label='Nb Matches',
            description=
            'The number of matches to retrieve for each image (If 0 it will retrieve all the matches).',
            value=50,
            range=(0, 1000, 1),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output List File',
            description=
            'Filepath to the output file with the list of selected image pairs.',
            value=desc.Node.internalFolder + 'imageMatches.txt',
            uid=[],
        ),
    ]
コード例 #25
0
ファイル: SfMAlignment.py プロジェクト: cs210/Worldsight
class SfMAlignment(desc.CommandLineNode):
    commandLine = 'aliceVision_utils_sfmAlignment {allParams}'
    size = desc.DynamicNodeSize('input')

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='''SfMData file .''',
            value='',
            uid=[0],
        ),
        desc.File(
            name='reference',
            label='Reference',
            description=
            '''Path to the scene used as the reference coordinate system.''',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='method',
            label='Alignment Method',
            description="Alignment Method:\n"
            " * from_cameras_viewid: Align cameras with same view Id\n"
            " * from_cameras_poseid: Align cameras with same pose Id\n"
            " * from_cameras_filepath: Align cameras with a filepath matching, using 'fileMatchingPattern'\n"
            " * from_cameras_metadata: Align cameras with matching metadata, using 'metadataMatchingList'\n"
            " * from_markers: Align from markers with the same Id\n",
            value='from_cameras_viewid',
            values=[
                'from_cameras_viewid', 'from_cameras_poseid',
                'from_cameras_filepath', 'from_cameras_metadata',
                'from_markers'
            ],
            exclusive=True,
            uid=[0],
        ),
        desc.StringParam(
            name='fileMatchingPattern',
            label='File Matching Pattern',
            description=
            'Matching regular expression for the "from_cameras_filepath" method. '
            'You should capture specific parts of the filepath with parenthesis to define matching elements.\n'
            'Some examples of patterns:\n'
            ' - Match the filename without extension (default value): ".*\/(.*?)\.\w{3}"\n'
            ' - Match the filename suffix after "_": ".*\/.*(_.*?\.\w{3})"\n'
            ' - Match the filename prefix before "_": ".*\/(.*?)_.*\.\w{3}"\n',
            value='.*\/(.*?)\.\w{3}',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="metadataMatching",
                label="Metadata",
                description="",
                value="",
                uid=[0],
            ),
            name="metadataMatchingList",
            label="Metadata Matching List",
            description=
            'List of metadata that should match to create the correspondences. If the list is empty, the default value will be used: ["Make", "Model", "Exif:BodySerialNumber", "Exif:LensSerialNumber"].',
        ),
        desc.BoolParam(name='applyScale',
                       label='Scale',
                       description='Apply scale transformation.',
                       value=True,
                       uid=[0]),
        desc.BoolParam(name='applyRotation',
                       label='Rotation',
                       description='Apply rotation transformation.',
                       value=True,
                       uid=[0]),
        desc.BoolParam(name='applyTranslation',
                       label='Translation',
                       description='Apply translation transformation.',
                       value=True,
                       uid=[0]),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            '''verbosity level (fatal, error, warning, info, debug, trace).''',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output',
            description='''Aligned SfMData file .''',
            value=desc.Node.internalFolder + 'alignedSfM.abc',
            uid=[],
        ),
    ]
コード例 #26
0
        description="Defines how this Intrinsic was initialized:\n"
        " * calibrated: calibrated externally.\n"
        " * estimated: estimated from metadata and/or sensor width. \n"
        " * unknown: unknown camera parameters (can still have default value guess)\n"
        " * none: not set",
        values=("calibrated", "estimated", "unknown", "none"),
        value="none",
        exclusive=True,
        uid=[],
        advanced=True),
    desc.ListAttribute(
        name="distortionParams",
        elementDesc=desc.FloatParam(name="p",
                                    label="",
                                    description="",
                                    value=0.0,
                                    uid=[0],
                                    range=(-0.1, 0.1, 0.01)),
        label="Distortion Params",
        description="Distortion Parameters",
    ),
    desc.BoolParam(
        name='locked',
        label='Locked',
        description=
        'If the camera has been calibrated, the internal camera parameters (intrinsics) can be locked. It should improve robustness and speedup the reconstruction.',
        value=False,
        uid=[0]),
]

コード例 #27
0
class StructureFromMotion(desc.CommandLineNode):
    commandLine = 'aliceVision_incrementalSfM {allParams}'
    size = desc.DynamicNodeSize('input')

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file.',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description="Folder(s) containing the extracted features and descriptors."
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="matchesFolder",
                label="Matches Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="matchesFolders",
            label="Matches Folders",
            description="Folder(s) in which computed matches are stored."
        ),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=['sift', 'sift_float', 'sift_upright', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv'],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ChoiceParam(
            name='localizerEstimator',
            label='Localizer Estimator',
            description='Estimator type used to localize cameras (acransac, ransac, lsmeds, loransac, maxconsensus).',
            value='acransac',
            values=['acransac', 'ransac', 'lsmeds', 'loransac', 'maxconsensus'],
            exclusive=True,
            uid=[0],
        ),
       desc.BoolParam(
            name='lockScenePreviouslyReconstructed',
            label='Lock Scene Previously Reconstructed',
            description='This option is useful for SfM augmentation. Lock previously reconstructed poses and intrinsics.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='useLocalBA',
            label='Local Bundle Adjustment',
            description='It reduces the reconstruction time, especially for large datasets (500+ images),\n'
                        'by avoiding computation of the Bundle Adjustment on areas that are not changing.',
            value=True,
            uid=[0],
        ),
        desc.IntParam(
            name='localBAGraphDistance',
            label='LocalBA Graph Distance',
            description='Graph-distance limit to define the Active region in the Local Bundle Adjustment strategy.',
            value=1,
            range=(2, 10, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='maxNumberOfMatches',
            label='Maximum Number of Matches',
            description='Maximum number of matches per image pair (and per feature type). \n'
                        'This can be useful to have a quick reconstruction overview. \n'
                        '0 means no limit.',
            value=0,
            range=(0, 50000, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='minInputTrackLength',
            label='Min Input Track Length',
            description='Minimum track length in input of SfM',
            value=2,
            range=(2, 10, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='minNumberOfObservationsForTriangulation',
            label='Min Observation For Triangulation',
            description='Minimum number of observations to triangulate a point.\n'
                        'Set it to 3 (or more) reduces drastically the noise in the point cloud,\n'
                        'but the number of final poses is a little bit reduced\n'
                        '(from 1.5% to 11% on the tested datasets).',
            value=2,
            range=(2, 10, 1),
            uid=[0],
        ),
        desc.FloatParam(
            name='minAngleForTriangulation',
            label='Min Angle For Triangulation',
            description='Minimum angle for triangulation.',
            value=3.0,
            range=(0.1, 10, 0.1),
            uid=[0],
        ),
        desc.FloatParam(
            name='minAngleForLandmark',
            label='Min Angle For Landmark',
            description='Minimum angle for landmark.',
            value=2.0,
            range=(0.1, 10, 0.1),
            uid=[0],
        ),
        desc.FloatParam(
            name='maxReprojectionError',
            label='Max Reprojection Error',
            description='Maximum reprojection error.',
            value=4.0,
            range=(0.1, 10, 0.1),
            uid=[0],
        ),
        desc.FloatParam(
            name='minAngleInitialPair',
            label='Min Angle Initial Pair',
            description='Minimum angle for the initial pair.',
            value=5.0,
            range=(0.1, 10, 0.1),
            uid=[0],
        ),
        desc.FloatParam(
            name='maxAngleInitialPair',
            label='Max Angle Initial Pair',
            description='Maximum angle for the initial pair.',
            value=40.0,
            range=(0.1, 60, 0.1),
            uid=[0],
        ),
        desc.BoolParam(
            name='useOnlyMatchesFromInputFolder',
            label='Use Only Matches From Input Folder',
            description='Use only matches from the input matchesFolder parameter.\n'
                        'Matches folders previously added to the SfMData file will be ignored.',
            value=False,
            uid=[],
        ),
        desc.File(
            name='initialPairA',
            label='Initial Pair A',
            description='Filename of the first image (without path).',
            value='',
            uid=[0],
        ),
        desc.File(
            name='initialPairB',
            label='Initial Pair B',
            description='Filename of the second image (without path).',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='interFileExtension',
            label='Inter File Extension',
            description='Extension of the intermediate file export.',
            value='.abc',
            values=('.abc', '.ply'),
            exclusive=True,
            uid=[],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='Verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output SfMData File',
            description='Path to the output sfmdata file',
            value=desc.Node.internalFolder + 'sfm.abc',
            uid=[],
        ),
        desc.File(
            name='outputViewsAndPoses',
            label='Output SfMData File',
            description='''Path to the output sfmdata file with cameras (views and poses).''',
            value=desc.Node.internalFolder + 'cameras.sfm',
            uid=[],
        ),
        desc.File(
            name='extraInfoFolder',
            label='Output Folder',
            description='Folder for intermediate reconstruction files and additional reconstruction information files.',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]

    @staticmethod
    def getViewsAndPoses(node):
        """
        Parse SfM result and return views and poses as two dict with viewId and poseId as keys.
        """
        reportFile = node.outputViewsAndPoses.value
        if not os.path.exists(reportFile):
            return {}, {}

        with open(reportFile) as jsonFile:
            report = json.load(jsonFile)

        views = dict()
        poses = dict()

        for view in report['views']:
            views[view['viewId']] = view

        for pose in report['poses']:
            poses[pose['poseId']] = pose['pose']

        return views, poses
コード例 #28
0
class CameraInit(desc.CommandLineNode):
    commandLine = 'aliceVision_cameraInit {allParams} --allowSingleView 1'  # don't throw an error if there is only one image

    size = desc.DynamicNodeSize('viewpoints')

    documentation = '''
This node describes your dataset. It lists the Viewpoints candidates, the guess about the type of optic, the initial focal length
and which images are sharing the same internal camera parameters, as well as potential cameras rigs.

When you import new images into Meshroom, this node is automatically configured from the analysis of the image metadata.
The software can support images without any metadata but it is recommended to have them for robustness.

### Metadata
Metadata allows images to be grouped together and provides an initialization of the focal length (in pixel unit).
The metadata needed are:
 * **Focal Length**: the focal length in mm.
 * **Make** & **Model**: this information allows to convert the focal in mm into a focal length in pixel using an embedded sensor database.
 * **Serial Number**: allows to uniquely identify a device so multiple devices with the same Make, Model can be differentiated and their internal parameters are optimized separately (in the photogrammetry case).
'''

    inputs = [
        desc.ListAttribute(
            name="viewpoints",
            elementDesc=desc.GroupAttribute(name="viewpoint",
                                            label="Viewpoint",
                                            description="",
                                            groupDesc=Viewpoint),
            label="Viewpoints",
            description="Input viewpoints",
            group="",
        ),
        desc.ListAttribute(
            name="intrinsics",
            elementDesc=desc.GroupAttribute(name="intrinsic",
                                            label="Intrinsic",
                                            description="",
                                            groupDesc=Intrinsic),
            label="Intrinsics",
            description="Camera Intrinsics",
            group="",
        ),
        desc.File(
            name='sensorDatabase',
            label='Sensor Database',
            description='''Camera sensor width database path.''',
            value=os.environ.get('ALICEVISION_SENSOR_DB', ''),
            uid=[],
        ),
        desc.FloatParam(
            name='defaultFieldOfView',
            label='Default Field Of View',
            description='Empirical value for the field of view in degree.',
            value=45.0,
            range=(0, 180.0, 1),
            uid=[],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='groupCameraFallback',
            label='Group Camera Fallback',
            description=
            "If there is no serial number in image metadata, devices cannot be accurately identified.\n"
            "Therefore, internal camera parameters cannot be shared among images reliably.\n"
            "A fallback grouping strategy must be chosen:\n"
            " * global: group images from comparable devices (same make/model/focal) globally.\n"
            " * folder: group images from comparable devices only within the same folder.\n"
            " * image: never group images from comparable devices",
            values=['global', 'folder', 'image'],
            value='folder',
            exclusive=True,
            uid=[],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='allowedCameraModels',
            label='Allowed Camera Models',
            description='the Camera Models that can be attributed.',
            value=[
                'pinhole', 'radial1', 'radial3', 'brown', 'fisheye4',
                'fisheye1'
            ],
            values=[
                'pinhole', 'radial1', 'radial3', 'brown', 'fisheye4',
                'fisheye1'
            ],
            exclusive=False,
            uid=[],
            joinChar=',',
            advanced=True,
        ),
        desc.BoolParam(
            name='useInternalWhiteBalance',
            label='Apply internal white balance',
            description='Apply image white balance (Only for raw images)',
            value=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='viewIdMethod',
            label='ViewId Method',
            description="Allows to choose the way the viewID is generated:\n"
            " * metadata : Generate viewId from image metadata.\n"
            " * filename : Generate viewId from file names using regex.",
            value='metadata',
            values=['metadata', 'filename'],
            exclusive=True,
            uid=[],
            advanced=True,
        ),
        desc.StringParam(
            name='viewIdRegex',
            label='ViewId Regex',
            description='Regex used to catch number used as viewId in filename.'
            'You should capture specific parts of the filename with parenthesis to define matching elements. (only number will works)\n'
            'Some examples of patterns:\n'
            ' - Match the longest number at the end of filename (default value): ".*?(\d+)"\n'
            ' - Match the first number found in filename : "(\d+).*"\n',
            value='.*?(\d+)',
            uid=[],
            advanced=True,
            enabled=lambda node: node.viewIdMethod.value == 'filename',
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            '''verbosity level (fatal, error, warning, info, debug, trace).''',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='SfMData',
            description='''Output SfMData.''',
            value=desc.Node.internalFolder + 'cameraInit.sfm',
            uid=[],
        ),
    ]

    def readSfMData(self, sfmFile):
        return readSfMData(sfmFile)

    def buildIntrinsics(self, node, additionalViews=()):
        """ Build intrinsics from node current views and optional additional views

        Args:
            node: the CameraInit node instance to build intrinsics for
            additionalViews: (optional) the new views (list of path to images) to add to the node's viewpoints

        Returns:
            The updated views and intrinsics as two separate lists
        """
        assert isinstance(node.nodeDesc, CameraInit)
        if node.graph:
            # make a copy of the node outside the graph
            # to change its cache folder without modifying the original node
            node = node.graph.copyNode(node)[0]

        tmpCache = tempfile.mkdtemp()
        node.updateInternals(tmpCache)

        try:
            os.makedirs(os.path.join(tmpCache, node.internalFolder))
            self.createViewpointsFile(node, additionalViews)
            cmd = self.buildCommandLine(node.chunks[0])
            logging.debug(' - commandLine: {}'.format(cmd))
            proc = psutil.Popen(cmd, stdout=None, stderr=None, shell=True)
            stdout, stderr = proc.communicate()
            # proc.wait()
            if proc.returncode != 0:
                raise RuntimeError(
                    'CameraInit failed with error code {}.\nCommand was: "{}".\n'
                    .format(proc.returncode, cmd))

            # Reload result of aliceVision_cameraInit
            cameraInitSfM = node.output.value
            return readSfMData(cameraInitSfM)

        except Exception as e:
            logging.debug(
                "[CameraInit] Error while building intrinsics: {}".format(
                    str(e)))
            raise
        finally:
            if os.path.exists(tmpCache):
                logging.debug(
                    "[CameraInit] Remove temp files in: {}".format(tmpCache))
                shutil.rmtree(tmpCache)

    def createViewpointsFile(self, node, additionalViews=()):
        node.viewpointsFile = ""
        if node.viewpoints or additionalViews:
            newViews = []
            for path in additionalViews:  # format additional views to match json format
                newViews.append({"path": path})
            intrinsics = node.intrinsics.getPrimitiveValue(exportDefault=True)
            for intrinsic in intrinsics:
                intrinsic['principalPoint'] = [
                    intrinsic['principalPoint']['x'],
                    intrinsic['principalPoint']['y']
                ]
            views = node.viewpoints.getPrimitiveValue(exportDefault=False)

            # convert the metadata string into a map
            for view in views:
                if 'metadata' in view:
                    view['metadata'] = json.loads(view['metadata'])

            sfmData = {
                "version": [1, 0, 0],
                "views": views + newViews,
                "intrinsics": intrinsics,
                "featureFolder": "",
                "matchingFolder": "",
            }
            node.viewpointsFile = (node.nodeDesc.internalFolder +
                                   '/viewpoints.sfm').format(**node._cmdVars)
            with open(node.viewpointsFile, 'w') as f:
                json.dump(sfmData, f, indent=4)

    def buildCommandLine(self, chunk):
        cmd = desc.CommandLineNode.buildCommandLine(self, chunk)
        if chunk.node.viewpointsFile:
            cmd += ' --input "{}"'.format(chunk.node.viewpointsFile)
        return cmd

    def processChunk(self, chunk):
        self.createViewpointsFile(chunk.node)
        desc.CommandLineNode.processChunk(self, chunk)
コード例 #29
0
class FeatureMatching(desc.CommandLineNode):
    commandLine = 'aliceVision_featureMatching {allParams}'
    size = desc.DynamicNodeSize('input')
    parallelization = desc.Parallelization(blockSize=20)
    commandLineRange = '--rangeStart {rangeStart} --rangeSize {rangeBlockSize}'

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description='SfMData file.',
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name="featuresFolder",
                label="Features Folder",
                description="",
                value="",
                uid=[0],
            ),
            name="featuresFolders",
            label="Features Folders",
            description=
            "Folder(s) containing the extracted features and descriptors."),
        desc.File(
            name='imagePairsList',
            label='Image Pairs List',
            description=
            'Path to a file which contains the list of image pairs to match.',
            value='',
            uid=[0],
        ),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=[
                'sift', 'sift_float', 'sift_upright', 'akaze', 'akaze_liop',
                'akaze_mldb', 'cctag3', 'cctag4', 'sift_ocv', 'akaze_ocv'
            ],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.ChoiceParam(
            name='photometricMatchingMethod',
            label='Photometric Matching Method',
            description='For Scalar based regions descriptor\n'
            ' * BRUTE_FORCE_L2: L2 BruteForce matching\n'
            ' * ANN_L2: L2 Approximate Nearest Neighbor matching\n'
            ' * CASCADE_HASHING_L2: L2 Cascade Hashing matching\n'
            ' * FAST_CASCADE_HASHING_L2: L2 Cascade Hashing with precomputed hashed regions (faster than CASCADE_HASHING_L2 but use more memory) \n'
            'For Binary based descriptor\n'
            ' * 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],
        ),
        desc.ChoiceParam(
            name='geometricEstimator',
            label='Geometric Estimator',
            description=
            'Geometric estimator: (acransac: A-Contrario Ransac, loransac: LO-Ransac (only available for "fundamental_matrix" model)',
            value='acransac',
            values=['acransac', 'loransac'],
            exclusive=True,
            uid=[0],
        ),
        desc.ChoiceParam(
            name='geometricFilterType',
            label='Geometric Filter Type',
            description=
            'Geometric validation method to filter features matches: \n'
            ' * fundamental_matrix\n'
            ' * essential_matrix\n'
            ' * homography_matrix\n'
            ' * homography_growing\n'
            ' * no_filtering',
            value='fundamental_matrix',
            values=[
                'fundamental_matrix', 'essential_matrix', 'homography_matrix',
                'homography_growing', 'no_filtering'
            ],
            exclusive=True,
            uid=[0],
        ),
        desc.FloatParam(
            name='distanceRatio',
            label='Distance Ratio',
            description='Distance ratio to discard non meaningful matches.',
            value=0.8,
            range=(0.0, 1.0, 0.01),
            uid=[0],
        ),
        desc.IntParam(
            name='maxIteration',
            label='Max Iteration',
            description='Maximum number of iterations allowed in ransac step.',
            value=2048,
            range=(1, 20000, 1),
            uid=[0],
        ),
        desc.IntParam(
            name='maxMatches',
            label='Max Matches',
            description='Maximum number of matches to keep.',
            value=0,
            range=(0, 10000, 1),
            uid=[0],
        ),
        desc.BoolParam(
            name='savePutativeMatches',
            label='Save Putative Matches',
            description='putative matches.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='guidedMatching',
            label='Guided Matching',
            description=
            'the found model to improve the pairwise correspondences.',
            value=False,
            uid=[0],
        ),
        desc.BoolParam(
            name='exportDebugFiles',
            label='Export Debug Files',
            description='debug files (svg, dot).',
            value=False,
            uid=[],
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description=
            'verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        )
    ]
    outputs = [
        desc.File(
            name='output',
            label='Output Folder',
            description=
            'Path to a folder in which computed matches will be stored.',
            value=desc.Node.internalFolder,
            uid=[],
        ),
    ]
コード例 #30
0
class PanoramaEstimation(desc.CommandLineNode):
    commandLine = 'aliceVision_panoramaEstimation {allParams}'
    size = desc.DynamicNodeSize('input')

    documentation = '''
Estimate relative camera rotations between input images.
'''

    inputs = [
        desc.File(
            name='input',
            label='Input',
            description="SfM Data File",
            value='',
            uid=[0],
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name='featuresFolder',
                label='Features Folder',
                description="",
                value='',
                uid=[0],
            ),
            name='featuresFolders',
            label='Features Folders',
            description="Folder(s) containing the extracted features."
        ),
        desc.ListAttribute(
            elementDesc=desc.File(
                name='matchesFolder',
                label='Matches Folder',
                description="",
                value='',
                uid=[0],
            ),
            name='matchesFolders',
            label='Matches Folders',
            description="Folder(s) in which computed matches are stored."
        ),
        desc.ChoiceParam(
            name='describerTypes',
            label='Describer Types',
            description='Describer types used to describe an image.',
            value=['sift'],
            values=['sift', 'sift_float', 'sift_upright', 'dspsift', 'akaze', 'akaze_liop', 'akaze_mldb', 'cctag3', 'cctag4',
                    'sift_ocv', 'akaze_ocv'],
            exclusive=False,
            uid=[0],
            joinChar=',',
        ),
        desc.FloatParam(
            name='offsetLongitude',
            label='Longitude offset (deg.)',
            description='''Offset to the panorama longitude''',
            value=0.0,
            range=(-180.0, 180.0, 1.0),
            uid=[0],
        ),
        desc.FloatParam(
            name='offsetLatitude',
            label='Latitude offset (deg.)',
            description='''Offset to the panorama latitude''',
            value=0.0,
            range=(-90.0, 90.0, 1.0),
            uid=[0],
        ),
        desc.ChoiceParam(
            name='rotationAveraging',
            label='Rotation Averaging Method',
            description="Method for rotation averaging :\n"
                        " * L1 minimization\n"
                        " * L2 minimization\n",
            values=['L1_minimization', 'L2_minimization'],
            value='L2_minimization',
            exclusive=True,
            uid=[0],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='relativeRotation',
            label='Relative Rotation Method',
            description="Method for relative rotation :\n"
                        " * from essential matrix\n"
                        " * from homography matrix\n"
                        " * from rotation matrix",
            values=['essential_matrix', 'homography_matrix', 'rotation_matrix'],
            value='rotation_matrix',
            exclusive=True,
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='refine',
            label='Refine',
            description='Refine camera relative poses, points and optionally internal camera parameter',
            value=True,
            uid=[0],
        ),
        desc.BoolParam(
            name='lockAllIntrinsics',
            label='Force Lock of All Intrinsics',
            description='Force to keep constant all the intrinsics parameters of the cameras (focal length, \n'
                        'principal point, distortion if any) during the reconstruction.\n'
                        'This may be helpful if the input cameras are already fully calibrated.',
            value=False,
            uid=[0],
        ),
        desc.FloatParam(
            name='maxAngleToPrior',
            label='Max Angle To Priors (deg.)',
            description='''Maximal angle allowed regarding the input prior (in degrees).''',
            value=20.0,
            range=(0.0, 360.0, 1.0),
            uid=[0],
            advanced=True,
        ),
        desc.FloatParam(
            name='maxAngularError',
            label='Max Angular Error (deg.)',
            description='''Maximal angular error in global rotation averging (in degrees).''',
            value=100.0,
            range=(0.0, 360.0, 1.0),
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='intermediateRefineWithFocal',
            label='Intermediate Refine: Focal',
            description='Intermediate refine with rotation and focal length only.',
            value=False,
            uid=[0],
            advanced=True,
        ),
        desc.BoolParam(
            name='intermediateRefineWithFocalDist',
            label='Intermediate Refine: Focal And Distortion',
            description='Intermediate refine with rotation, focal length and distortion.',
            value=False,
            uid=[0],
            advanced=True,
        ),
        desc.ChoiceParam(
            name='verboseLevel',
            label='Verbose Level',
            description='Verbosity level (fatal, error, warning, info, debug, trace).',
            value='info',
            values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
            exclusive=True,
            uid=[],
        ),
    ]

    outputs = [
        desc.File(
            name='output',
            label='Output SfMData File',
            description='Path to the output sfmdata file',
            value=desc.Node.internalFolder + 'panorama.abc',
            uid=[],
        ),
        desc.File(
            name='outputViewsAndPoses',
            label='Output Poses',
            description='''Path to the output sfmdata file with cameras (views and poses).''',
            value=desc.Node.internalFolder + 'cameras.sfm',
            uid=[],
        ),
    ]