Batch synchronize process
Batch synchronize process
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.
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.
Re: Batch synchronize process
I'm not sure... first, I'll start with general considerations:
Keep me updated,
P.S. : have you integrated this code in the ccCommandLineParser structure?
- 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.
Keep me updated,
P.S. : have you integrated this code in the ccCommandLineParser structure?
Daniel, CloudCompare admin
Re: Batch synchronize process
>> 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.
>>• 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.
Re: Batch synchronize process
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:
Or equivalently you can simply replace both calls by 'detachFromParent'. You just have to do it before deleting 'db'.
So right after you call 'setFlagState', you should also call:
Code: Select all
setParent(0);
Daniel, CloudCompare admin
Re: Batch synchronize process
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.
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
- scene2.jpg (103.57 KiB) Viewed 8383 times
-
- 2 registered cloud points
- scene.jpg (47.67 KiB) Viewed 8383 times
Re: Batch synchronize process
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:
Note: graphically those points will appear in gray by default, and you can hide them with 'ccScalarField::showNaNValuesInGrey(false)'
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);
}
Daniel, CloudCompare admin
Re: Batch synchronize process
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.
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.
Re: Batch synchronize process
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?
And for the BIN format, I couldn't reproduce the issue. Did you saved the file with ".bin" extension?
Daniel, CloudCompare admin
Re: Batch synchronize process
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.
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.
Re: Batch synchronize process
You just have to run the batch command with the "silent" option:
Code: Select all
CloudCompare -SILENT ...
Daniel, CloudCompare admin