CloudCompare / CloudComPy

Python wrapper for CloudCompare
Other
292 stars 41 forks source link

Add default arguments to ICP function? #163

Open mcgregorian1 opened 6 months ago

mcgregorian1 commented 6 months ago

Hi,

Overview

I wanted to use the cc.ICP function similar to when we used it in the command line call to CloudCompare. However, I found that the function would not run without named argument definitions for everything despite not being required in the command line option.

Question

Given the command line version of the ICP function works without specifying every individual argument, then I'm assuming it's working with internal defaults. It appears the CloudComPy ICP function already has some pre-defined defaults, so can the other argument defaults be added as well, please?

Context

In the command line script, we only defined the overlap and the random sampling limit:

path1 = "path/to/input/cloud.las"
path2 = "path/to/reference/cloud.las"
path3 = "output/cloud.las"

open -W -g -a CloudCompare.app --args -SILENT -O -GLOBAL_SHIFT -620000.00 -1010000.00 0 "$path1" -O -GLOBAL_SHIFT -620000.00 -1010000.00 0 "$path2" -ICP -OVERLAP 98 -RANDOM_SAMPLING_LIMIT 100000 -C_EXPORT_FMT LAS -SAVE_CLOUDS FILE "$path3" -CLEAR

Initial attempt

In CloudComPy, we tried doing the following, which gave us the error:

clouds = [cc.loadPointCloud(w, mode = cc.CC_SHIFT_MODE.XYZ, 
                                x = shiftX, y = shiftY, z = shiftZ)
                for w in [pathInput, pathRef]]

res = cc.ICP(data = clouds[0],
                model = clouds[1], 
                finalOverlapRatio = 0.98,
                randomSamplingLimit = 100000)

>>> res = cc.ICP(data = clouds[0],
...             model = clouds[1], 
...             finalOverlapRatio = 0.98,
...             randomSamplingLimit = 100000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ICP(): incompatible function arguments. The following argument types are supported:
    1. (data: _cloudComPy.ccHObject, model: _cloudComPy.ccHObject, minRMSDecrease: float, maxIterationCount: int, randomSamplingLimit: int, removeFarthestPoints: bool, method: _cloudComPy.CONVERGENCE_TYPE, adjustScale: bool, finalOverlapRatio: float = 1.0, useDataSFAsWeights: bool = False, useModelSFAsWeights: bool = False, transformationFilters: int = <TRANSFORMATION_FILTERS.SKIP_NONE: 0>, maxThreadCount: int = 0) -> _cloudComPy.ICPres

Invoked with: kwargs: data=<_cloudComPy.ccPointCloud object at 0x102f5ab30>, model=<_cloudComPy.ccPointCloud object at 0x102f5afb0>, finalOverlapRatio=98, randomSamplingLimit=100000

Second attempt

I thought maybe the issue is that the function has no defaults and therefore is expecting arguments. I thus used the arguments as defined in test010.py from Section 4.1 in the documentation, and this worked.

res = cc.ICP(data = clouds[0], model = clouds[1], 
                minRMSDecrease=1.e-5, maxIterationCount=20,         # defaults
                removeFarthestPoints=False,                         # defaults
                method=cc.CONVERGENCE_TYPE.MAX_ITER_CONVERGENCE,    # defaults
                adjustScale=False,                                  # defaults
                finalOverlapRatio = 0.98,
                randomSamplingLimit = 100000)
>>>
rasclep commented 6 months ago

Hi, you're right, the current implementation in CloudComPy requires at least 8 arguments, and only 5 are optional. It should be easy to define more arguments as optional, I'll add that to my TODO list! Regards, Paul

mcgregorian1 commented 6 months ago

Thanks!

In the meantime, do you know what the actual defaults are for each of the arguments as they were used in the command line version of the ICP function? The best I can tell from the documentation along with the CloudCompare GUI (and separate docs is

minRMSDecrease = 1.e-5
maxIterationCount = 20
removeFarthestPoints = False
method = ?? (I assume MAX_ITER_CONVERGENCE because the other option is MAX_ERROR_CONVERGENCE)
adjustScale = False
finalOverlapRatio = 100 (1)
randomSamplingLimit = 20,000
prascle commented 6 months ago

Sorry, I forgot your question!

From the code (https://github.com/CloudCompare/CloudCompare/blob/master/qCC/ccCommandLineCommands.cpp) line 6631, you can get some default values in command mode (C++ names are quite similar to the names used in GUI or Command Mode) If iterationCount is not 0, MAX_ITER_CONVERGENCE is selected, otherwise it is MAX_ERROR_CONVERGENCE

bool CommandICP::process(ccCommandLineInterface& cmd)
{
    //look for local options
    bool referenceIsFirst = false;
    bool adjustScale = false;
    bool enableFarthestPointRemoval = false;
    double minErrorDiff = 1.0e-6;
    unsigned iterationCount = 0;
    unsigned randomSamplingLimit = 20000;
    unsigned overlap = 100;
    int modelWeightsSFIndex = -1;
    QString modelWeightsSFIndexName;
    int dataWeightsSFIndex = -1;
    QString dataWeightsSFIndexName;
    int maxThreadCount = 0;
    int transformationFilters = CCCoreLib::RegistrationTools::SKIP_NONE;
    bool useC2MDistances = false;
    bool robustC2MDistances = true;
    CCCoreLib::ICPRegistrationTools::NORMALS_MATCHING normalsMatching = CCCoreLib::ICPRegistrationTools::NO_NORMAL;

Best regards, Paul

mcgregorian1 commented 6 months ago

No worries, thanks for pointing me to the defaults!