Batch synchronize process

Feel free to ask any question here
burcarjo
Posts: 8
Joined: Mon May 13, 2013 8:34 am

Batch synchronize process

Post by burcarjo »

Hi Daniel,
I did a batch process to register(ICP) and compute distance for two meses (I extract the associated cloud point to do the tasks).
I'm getting different alignment results depending the role that I use to choose cloud model or cloud data (I try to put the cloud with more number point as model).
If I do a synchronize process at begin then I can get best alignment results so I would like to add it at start of my batch process.
I'm trying this:

// Open MODEL FILE

ccHObject* db = FileIOFilter::LoadFromFile(modelFileQ,UNKNOWN_FILE,false);
if (!db)
return Error(QString("Failed to open file '%1'").arg(modelFileQ));
ccHObject::Container meshes1;
db->filterChildren(meshes1,false,CC_MESH);
ccGenericMesh* model = static_cast<ccGenericMesh*>(meshes1[0]);
model->setFlagState(CC_FATHER_DEPENDANT,false);
Print(QString("Found one mesh with %1 faces and %2 vertices").arg(model->size()).arg(model->getAssociatedCloud()->size()));
delete db;
db=0;

// Open DATA File
db = FileIOFilter::LoadFromFile(dataFileQ,UNKNOWN_FILE,false);
if (!db)
return Error(QString("Failed to open file '%1'").arg(dataFileQ));
ccHObject::Container meshes2;
db->filterChildren(meshes2,false,CC_MESH);
ccGenericMesh* data = static_cast<ccGenericMesh*>(meshes2[0]);
data->setFlagState(CC_FATHER_DEPENDANT,false);
Print(QString("Found one mesh with %1 faces and %2 vertices").arg(data->size()).arg(data->getAssociatedCloud()->size()));
delete db;
db=0;

dataCloud = static_cast<ccGenericMesh*>(data)->getAssociatedCloud();
modelCloud = static_cast<ccGenericMesh*>(model)->getAssociatedCloud();

// Synchronize process
ccHObject* refData = meshes2[0];
ccHObject* refModel = meshes1[0];

CCVector3 dataCenter = refData->getCenter();
CCVector3 modelCenter = refModel->getCenter();
CCVector3 newModelCenter = dataCenter - modelCenter;

//transformation (used only for translation)
ccGLMatrix glTrans;
glTrans += newModelCenter;
refModel->applyGLTransformation_recursive(&glTrans);

However, I obtain an "Access infraction" in the applyGLTransformation rutine:

applyGLTransformation(*trans);
ccHObject.cpp

I'm using some data structure wrong?

Thanks,

David.
daniel
Site Admin
Posts: 7674
Joined: Wed Oct 13, 2010 7:34 am
Location: Grenoble, France
Contact:

Re: Batch synchronize process

Post by daniel »

I'm not sure... first, I'll start with general considerations:
  • you should test that the 'filterChildren' has actually output at least one mesh (either test the number of found items returned by the method itself, or the size of the meshes1 and meshes2 vectors).
  • you should use the CC_GENERIC_MESH as filter type (it's more 'generic' and you won't miss composite meshes)
  • once you have saved the 'model' and 'data' pointers, you should use them and forgot about the vectors. In the same spirit, the refData and refModel instances are totally redundant.
Otherwise, the only issue I can think of when looking at your code is that you properly detach the mesh from its parent, but the vertices are not always 'children' of meshes (in terms of ccObject hierarchy - i.e. what appears in the DB tree). It happens with composite meshes (you can have several sub-meshes sharing all the same vertices - they typically come from OBJ or PDMS files - in this case, all sub-meshes depend on the same vertices cloud, but the vertices and the sub-meshes are all 'children' of a composite mesh - a ccMeshGroup structure). So just to be sure you should also detach the vertices clouds (with the CC_FATHER_DEPENDENT flag).

Keep me updated,

P.S. : have you integrated this code in the ccCommandLineParser structure?
Daniel, CloudCompare admin
burcarjo
Posts: 8
Joined: Mon May 13, 2013 8:34 am

Re: Batch synchronize process

Post by burcarjo »

>> I'm not sure... first, I'll start with general considerations:
>>• you should test that the 'filterChildren' has actually output at least one mesh (either test the number of found items returned by the method itself, or the size of the meshes1 and meshes2 vectors).
>>• you should use the CC_GENERIC_MESH as filter type (it's more 'generic' and you won't miss composite meshes)
>>• once you have saved the 'model' and 'data' pointers, you should use them and forgot about the vectors. In the same spirit, the refData and refModel instances are totally redundant.

Yes, I obtain correctly the data and model mesh objects. Then I use it to do the registration and compute distances without problems.
Debugging the code, the execution stops calling:

model->applyGLTransformation_recursive(&glTrans);

that calls

void ccGenericMesh::applyGLTransformation(const ccGLMatrix& trans)
{
//vertices should be handled another way!

//we must take care of the triangle normals!
if (m_triNormals && (!getParent() || !getParent()->isKindOf(CC_MESH)))

that calls

inline bool isKindOf(CC_CLASS_ENUM type) const { return (getClassID() & type) == type; }

type is CC_MESH so I think the error occurs accesing to getClassID method ?

I tried to put this: model->detachFromParent(); before model->applyGLTransformation_recursive(&glTrans); but the execution also fails.

Any idea ?

>> P.S. : have you integrated this code in the ccCommandLineParser structure?
Yes , but I'm using a configuration file to read all the parameters of registration and compute distances.

Thanks,

David.
daniel
Site Admin
Posts: 7674
Joined: Wed Oct 13, 2010 7:34 am
Location: Grenoble, France
Contact:

Re: Batch synchronize process

Post by daniel »

Indeed, I guess the issue here is that getParent() returns a pointer on an object that has already been deleted (db).

So right after you call 'setFlagState', you should also call:

Code: Select all

setParent(0);
Or equivalently you can simply replace both calls by 'detachFromParent'. You just have to do it before deleting 'db'.
Daniel, CloudCompare admin
burcarjo
Posts: 8
Joined: Mon May 13, 2013 8:34 am

Re: Batch synchronize process

Post by burcarjo »

OK, now synchronize goes fine. Thanks !

I attach a snapshot of the two aligned point clouds (with a previous segmentation task).
As you can see , the blue point cloud has a more reduced box that the brown point cloud. So, it is a problem when I do the compute distances because I would like to compute only the overlapping zones.

1. Is there any way to specify a compute distances for only the overlapping zones ?. I could do it cutting manually the clouds but I would like to do in the batch process. I also think to make a common box size for both clouds but I could lost some overlapping points.

2. I can use max. distance to limit the distance calculation only to the nearly overlapping points but if I do it, histogram will take into account only these points or also the full point distances ? . My batch process should obtain only true distances and make decisions based on percentages calculated in the histogram (only for the overlapping/nearly zones).

Thanks,

David.
Attachments
max distance to 10 cm
max distance to 10 cm
scene2.jpg (103.57 KiB) Viewed 8290 times
2 registered cloud points
2 registered cloud points
scene.jpg (47.67 KiB) Viewed 8290 times
daniel
Site Admin
Posts: 7674
Joined: Wed Oct 13, 2010 7:34 am
Location: Grenoble, France
Contact:

Re: Batch synchronize process

Post by daniel »

Differences in entities extent is indeed a (very) difficult issue.

Theoretically speaking, the only good way to handle it automatically is to know the 'reference' sensor point of view (and maximum range, etc.) and check that the 'compared' points do fall inside this point of view (i.e. that the compared points "could have been seen" by the sensor which has generated the reference data set).

In practical it's generally impossible, and you must use very rough heuristics such as the 'reference' bounding box as you suggested (maybe the convex hull could be better, but it's not even worse the cost). You'll always have points falling outside the bounding box that you would have 'wanted' compared, and points falling inside that you wouldn't want ;)

The 'max distance' parameter is just a slightly better heuristic (but you will still get some points of the compared cloud lying near the compared mesh borders with virtually high distances). And as you guessed all the points lying farther will have the same distance value (this 'max distance'). If you don't want to see them appear in the histogram, you should set them to 'NAN_VALUE' after the distance computation is done:

Code: Select all

for (unsigned i=0; i<sf->size(); ++i)
{
    if (sf->getValue() >= max_distance)
        sf->flagValueAsInvalid(i);
}
Note: graphically those points will appear in gray by default, and you can hide them with 'ccScalarField::showNaNValuesInGrey(false)'
Daniel, CloudCompare admin
burcarjo
Posts: 8
Joined: Mon May 13, 2013 8:34 am

Re: Batch synchronize process

Post by burcarjo »

Ok, I will try later to disable the further points from the SF.

Maybe, a partial solution could be to conserve only the points of the more dense point cloud where the normal has a nearly associated normal (overlapping point) at the less dense point cloud. So, the extended zones could automatically be deleted.

I'm trying to save the generated distance point cloud in a file and show it with the ccViewer, but when I open the file (as ASCII) ccViewer assign bad the order of columns for the SF field and normals components. You can reproduce this :

1. Open 2 point clouds and calculate the cc distance.
2. Compute the normals of the generated distance point cloud.
3. Save the point cloud as ASCII.
4. Open the point cloud with ccViewer and you can see that the dialog screen always assign normal columns before the SF distance column.

If I save from the batch process as a bin file then I directly get an unknown format error message .

Thanks,
David.
daniel
Site Admin
Posts: 7674
Joined: Wed Oct 13, 2010 7:34 am
Location: Grenoble, France
Contact:

Re: Batch synchronize process

Post by daniel »

Indeed, contrarily to CloudCompare, ccViewer tries to guess the ASCII files organization automatically. If it finds 3 consecutive values below 1.0 it will think that it's probably a normal vector... We could be smarter (check that the squared sum is also 1.0, etc.)

And for the BIN format, I couldn't reproduce the issue. Did you saved the file with ".bin" extension?
Daniel, CloudCompare admin
burcarjo
Posts: 8
Joined: Mon May 13, 2013 8:34 am

Re: Batch synchronize process

Post by burcarjo »

Ok, I had to put the enable flag to the point cloud before to sabe it:
compCloud->setEnabled(true);
compCloud->setVisible(true);

Now, I can automatically register, compute distances and get the associated histogram data.

I would like to show the histogram plot as the last task.
Now, I'm showing the histogram window after to computer distances but the batch task finish launching a modal message "QMessageBox::information(&consoleDlg,"Processed finished","Job done");" and I can't interact with the back histogram window.

is There any way to keep focused the histogram window and close the batch process only when I close this window ?

Thanks,

David.
daniel
Site Admin
Posts: 7674
Joined: Wed Oct 13, 2010 7:34 am
Location: Grenoble, France
Contact:

Re: Batch synchronize process

Post by daniel »

You just have to run the batch command with the "silent" option:

Code: Select all

CloudCompare -SILENT ... 
Daniel, CloudCompare admin
Post Reply