Skip to content

RBT: JSON Schema validation and explanation #1631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

SamFlt
Copy link
Contributor

@SamFlt SamFlt commented Mar 20, 2025

This PR proposes to include a cleaner JSON parsing and validation for the RBT Json configuration.

This is done through a base class vpRBJsonParsable which has three methods: schema parsing, verification and explanation. Explanation is used to describe every possible parameter for a given object, and indicates whether a given parameter is required or not.

An advantage of this solution is that the explanation document can be used to generate an HTML version of the documentation as well as give an on the fly explanation when the user gives an incorrect parameter.

For tracker features and other interchangeable RBT parts, a list of options is given.

  • A basic JSON explanation example
  • Schema verification
  • Generate a basic startup configuration

This is an incomplete example of a full explanation of the RBT Tracker parameters:

{
    "displaySilhouette": {
        "description": "Whether to display the object silhouette on top of the color image.This will work only if silhouette is extracted,and the displayed silhouette will be the one corresponding to the object pose estimated at the previous timestep",
        "exampleValue": false,
        "required": false,
        "type": "bool"
    },
    "model": {
        "description": "Path to the model of the object to track.This parameter is not required and the model can be specified using a setter.A model should be set before calling startTracking.",
        "exampleValue": true,
        "required": false,
        "type": "bool"
    },
    "camera": {
        "intrinsics": {
            "px": {
                "description": "Ratio between pixel width and focal length",
                "exampleValue": 800.0,
                "required": false,
                "type": "double"
            },
            "py": {
                "description": "Ratio between pixel height and focal length",
                "exampleValue": 800.0,
                "required": false,
                "type": "double"
            },
            "u0": {
                "description": "Principal point position (horizontal axis, in pixels)",
                "exampleValue": 320.0,
                "required": false,
                "type": "double"
            },
            "v0": {
                "description": "Principal point position (vertical axis, in pixels)",
                "exampleValue": 240.0,
                "required": false,
                "type": "double"
            }
        },
        "description": "Camera intrinsics and input image dimensions. The tracker assumes that there is no distortion and that color and depth images are aligned.",
        "height": {
            "description": "Image height",
            "exampleValue": 480,
            "required": false,
            "type": "int"
        },
        "width": {
            "description": "Image width",
            "exampleValue": 640,
            "required": false,
            "type": "int"
        }
    },
    "vvs": {
        "gain": {
            "description": "The gain used during levenberg-marquardt minimization of the feature error",
            "exampleValue": 1.0,
            "required": true,
            "type": "double"
        },
        "maxIterations": {
            "description": "The maximum number of iterations for the minimization process.",
            "exampleValue": 10,
            "required": true,
            "type": "int"
        },
        "mu": {
            "description": "The initial value for the regularization parameter of the LM algorithm.This value is multiplied by muIterfactor at every iteration.A low value of mu leads to a Gauss Newton minimizer, while a higher value is closer to a gradient descent solution.",
            "exampleValue": 0.1,
            "required": true,
            "type": "double"
        },
        "muIterFactor": {
            "description": "The factor with which to multiply the current regularization parameter value.",
            "exampleValue": 0.1,
            "required": true,
            "type": "double"
        },
        "scaleInvariant": {
            "description": "Whether to use the identity matrix as a regularizer (value of false) or the diagonal of the Hessian approximation (true)",
            "exampleValue": false,
            "required": true,
            "type": "bool"
        },
        "convergenceMetricThreshold": {
            "description": "Minimum value of the convergence metric  to not stop optimization. If the metric is below this threshold, then optimization is stopped.A value of 0 leads to running optimization for the full number of maxIterations.",
            "exampleValue": 0.0,
            "required": false,
            "type": "double"
        }
    },
    "silhouetteExtractionSettings": {
        "threshold": {
            "type": {
                "description": "Type of thresholding when extracting the silhouette from the rendered depth map.A pixel is considered as belonging to the silhouette when there is a strong depth disparity in its neighbourhood.This depends on a threshold. Type values can be either \"relative\" or \"absolute\". If it absolute, then the specified threshold is in meters. If it is \"relative\", then it is specified as a fraction (between 0 and 1) of the distance between the near and far clipping planes, e.g. the distance between the nearest and farthest object points to the camera.",
                "exampleValue": true,
                "required": true,
                "type": "bool"
            },
            "value": {
                "description": "Minimum threshold value for a pixel to be considered as belonging to the silhouette. See type for what value to use.",
                "exampleValue": 0.1,
                "required": true,
                "type": "double"
            }
        },
        "sampling": {
            "samplingRate": {
                "description": "Step size when subsampling the silhouette map",
                "exampleValue": 1,
                "required": true,
                "type": "int"
            },
            "numPoints": {
                "description": "Maximum number of silhouette candidates to use in feature trackers and other downstream tasks.Set to 0 to consider all silhouette points. Not recommended when setting samplingRate to 1.",
                "exampleValue": 512,
                "required": true,
                "type": "int"
            },
            "reusePreviousPoints": {
                "description": "Whether to try and reuse silhouette points from the previous frame.This may help improve tracking stability.",
                "exampleValue": true,
                "required": true,
                "type": "bool"
            }
        }
    },
    "features": {
        "description": "List of visual features to track. Multiple features can be combined. To disable a feature, add the ignored flag to it.",
        "options": {
            "depth": {
                "weight": {
                    "description": "Feature weight in the optimization step",
                    "exampleValue": 1.0,
                    "required": true,
                    "type": "double"
                },
                "display": {
                    "description": "Whether visual feature representations should be displayed when calling vpRBTracker::display()",
                    "exampleValue": true,
                    "required": true,
                    "type": "bool"
                },
                "step": {
                    "description": "Sampling step for the depth map. Should be greater than 0.",
                    "exampleValue": 2,
                    "required": true,
                    "type": "int"
                },
                "useMask": {
                    "description": "Whether the object membership mask (if available) should be used to filter out depth features",
                    "exampleValue": false,
                    "required": false,
                    "type": "bool"
                },
                "minMaskConfidence": {
                    "description": "If using mask, minimum confidence value to consider a feature as relevant for the tracking",
                    "exampleValue": 0.0,
                    "required": false,
                    "type": "double"
                },
                "displayType": {
                    "description": "When display is enabled, what information about the feature to display",
                    "exampleValue": 0,
                    "required": false,
                    "type": "int"
                }
            },
            "klt": {
                "weight": {
                    "description": "Feature weight in the optimization step",
                    "exampleValue": 1.0,
                    "required": true,
                    "type": "double"
                },
                "display": {
                    "description": "Whether visual feature representations should be displayed when calling vpRBTracker::display()",
                    "exampleValue": true,
                    "required": true,
                    "type": "bool"
                }
            },
            "silhouetteColor": {
                "weight": {
                    "description": "Feature weight in the optimization step",
                    "exampleValue": 1.0,
                    "required": true,
                    "type": "double"
                },
                "display": {
                    "description": "Whether visual feature representations should be displayed when calling vpRBTracker::display()",
                    "exampleValue": true,
                    "required": true,
                    "type": "bool"
                }
            },
            "silhouetteMe": {
                "weight": {
                    "description": "Feature weight in the optimization step",
                    "exampleValue": 1.0,
                    "required": true,
                    "type": "double"
                },
                "display": {
                    "description": "Whether visual feature representations should be displayed when calling vpRBTracker::display()",
                    "exampleValue": true,
                    "required": true,
                    "type": "bool"
                }
            }
        }
    },
    "mask": {
        "description": "Object segmentation algorithms. These are used to filter out potentially erronous data, such as occlusions or lighting artifacts.",
        "options": {
            "histogram": {
                "bins": {
                    "description": "",
                    "exampleValue": 16,
                    "required": true,
                    "type": "int"
                },
                "backgroundUpdateRate": {
                    "description": "",
                    "exampleValue": 0.10000000149011612,
                    "required": true,
                    "type": "double"
                },
                "objectUpdateRate": {
                    "description": "",
                    "exampleValue": 0.10000000149011612,
                    "required": true,
                    "type": "double"
                },
                "maxDepthError": {
                    "description": "",
                    "exampleValue": 0.009999999776482582,
                    "required": true,
                    "type": "double"
                },
                "likelihoodRatioThreshold": {
                    "description": "",
                    "exampleValue": 2.0,
                    "required": false,
                    "type": "double"
                },
                "computeOnlyOnBoundingBox": {
                    "description": "",
                    "exampleValue": false,
                    "required": false,
                    "type": "bool"
                }
            }
        }
    },
    "drift": {
        "description": "Drift and divergence detection methods. These are used to detect when object tracking is uncertain and a reinitialization is required.",
        "options": {
            "probabilistic": {
                "colorUpdateRate": {
                    "description": "Color update rate: How fast the color distribution associated to a surface point evolves. Between 0 and 1. A high value will lead to a confidence that converge to 1 faster. ",
                    "exampleValue": 0.2,
                    "required": false,
                    "type": "double"
                },
                "initialColorSigma": {
                    "description": "Initial color standard deviation when examining a new surface point. between 0 and 255.A high value will to an initial confidence that is stronger,but will slow convergence to the true distribution.",
                    "exampleValue": 25.0,
                    "required": false,
                    "type": "double"
                },
                "depthSigma": {
                    "description": "Depth standard deviation, in meters. When depth map is available, the point's distance and the actual depth are compared and are scored according to a Gaussian distribution, whose standard deviation is this parameter. A high value will to a higher depth error tolerance.",
                    "exampleValue": 0.04,
                    "required": false,
                    "type": "double"
                },
                "filteringMaxDistance": {
                    "description": "Filtering depth error threshold (in meters) when selecting which surface points to consider for the drift score computation. The depth error that is compared to the threshold is the distance between the stored surface point's distance to the camera and the rendered depth. This does not use the depth from the input frame.",
                    "exampleValue": 0.001,
                    "required": false,
                    "type": "double"
                },
                "minDistanceNewPoints": {
                    "description": "Minimum distance (in meters) that a new examined point should have to all other points for it to be considered for future drift score estimation. This threshold is mainly relevant to adapt the accuracy vs computation time tradeoff.",
                    "exampleValue": 0.003,
                    "required": false,
                    "type": "double"
                },
                "sampleStep": {
                    "description": "Sampling step (in pixels) when examining the input frame to select new surface point candidates",
                    "exampleValue": 4,
                    "required": false,
                    "type": "int"
                }
            }
        }
    }
}

Copy link

codecov bot commented Mar 20, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 54.48%. Comparing base (d7298c5) to head (6ccf614).
Report is 19 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1631      +/-   ##
==========================================
- Coverage   54.48%   54.48%   -0.01%     
==========================================
  Files         442      442              
  Lines       53449    53449              
==========================================
- Hits        29123    29122       -1     
- Misses      24326    24327       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

fspindle added a commit to SamFlt/visp that referenced this pull request Apr 2, 2025
… and that can't be set in the json file

There is something weird in the test:
- mu seems no more an array in PR lagadic#1631
- there should be a muIterFactor var as given in PR lagadic#1631
        "mu": {
            "description": "The initial value for the regularization parameter of the LM algorithm.This value is multiplied by muIterfactor at every iteration.A low value of mu leads to a Gauss Newton minimizer, while a higher value is closer to a gradient descent solution.",
            "exampleValue": 0.1,
            "required": true,
            "type": "double"
        },
        "muIterFactor": {
            "description": "The factor with which to multiply the current regularization parameter value.",
            "exampleValue": 0.1,
            "required": true,
            "type": "double"
        },
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant