Skip to content

Commit 38c12c5

Browse files
CAP: Association functions implemented, defensive checks added, and general cleanup
1 parent 111c484 commit 38c12c5

File tree

4 files changed

+39
-23
lines changed

4 files changed

+39
-23
lines changed

src/diffCheck/segmentation/DFSegmentation.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cilantro/utilities/point_cloud.hpp>
44
#include <cilantro/core/nearest_neighbors.hpp>
55
#include <cilantro/clustering/connected_component_extraction.hpp>
6+
#include <cmath>
67

78
namespace diffCheck::segmentation
89
{
@@ -101,7 +102,6 @@ namespace diffCheck::segmentation
101102
double associationThreshold)
102103
{
103104
std::shared_ptr<geometry::DFPointCloud> unifiedPointCloud = std::make_shared<geometry::DFPointCloud>();
104-
std::vector<std::shared_ptr<geometry::DFPointCloud>> segmentsRemainder;
105105

106106
// iterate through the mesh faces given as function argument
107107
if (referenceMesh.size() == 0)
@@ -139,7 +139,7 @@ namespace diffCheck::segmentation
139139

140140
double currentDistance = (faceCenter - segmentCenter).norm() / std::abs(segmentNormal.dot(faceNormal));
141141
// if the distance is smaller than the previous one, update the distance and the corresponding segment
142-
if (std::abs(faceNormal.dot(segmentNormal)) > angleThreshold && currentDistance < faceDistance)
142+
if (std::abs(sin(acos(faceNormal.dot(segmentNormal)))) < angleThreshold && currentDistance < faceDistance)
143143
{
144144
correspondingSegment = segment;
145145
faceDistance = currentDistance;
@@ -231,9 +231,8 @@ namespace diffCheck::segmentation
231231
}
232232
clusterNormal.normalize();
233233

234-
std::shared_ptr<diffCheck::geometry::DFMesh> testMesh;
235-
int meshIndex;
236-
int faceIndex ;
234+
int meshIndex = std::numeric_limits<int>::max();
235+
int faceIndex = std::numeric_limits<int>::max() ;
237236
double distance = std::numeric_limits<double>::max();
238237

239238
if (meshes.size() == 0)
@@ -270,17 +269,21 @@ namespace diffCheck::segmentation
270269

271270
double clusterNormalToJunctionLineAngle = std::abs(std::acos(clusterNormal.dot((clusterCenter - faceCenter).normalized())));
272271

273-
double currentDistance = (clusterCenter - faceCenter).norm() * std::pow(std::cos(clusterNormalToJunctionLineAngle), 2) / std::pow(clusterNormal.dot(faceNormal), 2);
274-
if (std::abs(faceNormal.dot(clusterNormal)) > angleThreshold && currentDistance < distance)
272+
double currentDistance = (clusterCenter - faceCenter).norm() * std::pow(std::cos(clusterNormalToJunctionLineAngle), 2) / std::pow(clusterNormal.dot(faceNormal), 2);
273+
if (std::abs(sin(acos(faceNormal.dot(clusterNormal)))) < angleThreshold && currentDistance < distance)
275274
{
276275
distance = currentDistance;
277276
meshIndex = std::distance(meshes.begin(), std::find(meshes.begin(), meshes.end(), piece));
278277
faceIndex = std::distance(piece.begin(), std::find(piece.begin(), piece.end(), meshFace));
279-
testMesh = meshFace;
280278
}
281279
}
282280
}
283-
281+
if (meshIndex >= meshes.size() || faceIndex >= meshes[meshIndex].size())
282+
{
283+
// this one generates a lot of warnings
284+
DIFFCHECK_WARN("No mesh face found for the cluster. Skipping the cluster.");
285+
continue;
286+
}
284287
std::shared_ptr<geometry::DFPointCloud> completed_segment = existingPointCloudSegments[meshIndex];
285288
for (Eigen::Vector3d point : cluster->Points)
286289
{

src/diffCheck/segmentation/DFSegmentation.hh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,28 @@ namespace diffCheck::segmentation
2929
/** @brief Associates point cloud segments to mesh faces and merges them. It uses the center of mass of the segments and the mesh faces to find correspondances. For each mesh face it then iteratively associate the points of the segment that are actually on the mesh face.
3030
* @param referenceMesh the vector of mesh faces to associate with the segments
3131
* @param clusters the vector of clusters from cilantro to associate with the mesh faces of the reference mesh
32-
* @param angleThreshold the threshold to consider the a cluster as potential candidate for association. the value passed is the minimum cosine of the angles. A value of 0.99 requires perfect alignment, while a value of 0.8 is more permissive. A value of 0 allows any angle between the normal of the cluster and the normal of the mesh face.
32+
* @param angleThreshold the threshold to consider the a cluster as potential candidate for association. the value passed is the minimum sine of the angles. A value of 0 requires perfect alignment (angle = 0), while a value of 0.1 allows an angle of 5.7 degrees.
3333
* @param associationThreshold the threshold to consider the points of a segment and a mesh face as associable. It is the ratio between the surface of the closest mesh triangle and the sum of the areas of the three triangles that form the rest of the pyramid described by the mesh triangle and the point we want to associate or not. The lower the number, the more strict the association will be and some poinnts on the mesh face might be wrongfully excluded.
3434
* @return std::shared_ptr<geometry::DFPointCloud> The unified segments
3535
*/
3636
static std::shared_ptr<geometry::DFPointCloud> DFSegmentation::AssociateClustersToMeshes(
3737
std::vector<std::shared_ptr<geometry::DFMesh>> referenceMesh,
3838
std::vector<std::shared_ptr<geometry::DFPointCloud>> &clusters,
39-
double angleThreshold = 0.95,
39+
double angleThreshold = 0.1,
4040
double associationThreshold = 0.1);
4141

4242
/** @brief Iterated through clusters and finds the corresponding mesh face. It then associates the points of the cluster that are on the mesh face to the segment already associated with the mesh face.
4343
* @param unassociatedClusters the clusters from the normal-based segmentatinon that haven't been associated yet.
4444
* @param existingPointCloudSegments the already associated segments
4545
* @param Meshes the mesh faces for all the model. This is used to associate the clusters to the mesh faces.
46-
* * @param angleThreshold the threshold to consider the a cluster as potential candidate for association. the value passed is the minimum cosine of the angles. A value of 0.99 requires perfect alignment, while a value of 0.8 is more permissive. A value of 0 allows any angle between the normal of the cluster and the normal of the mesh face.
46+
* * @param angleThreshold the threshold to consider the a cluster as potential candidate for association. the value passed is the minimum sine of the angles. A value of 0 requires perfect alignment (angle = 0), while a value of 0.1 allows an angle of 5.7 degrees.
4747
* @param associationThreshold the threshold to consider the points of a segment and a mesh face as associable. It is the ratio between the surface of the closest mesh triangle and the sum of the areas of the three triangles that form the rest of the pyramid described by the mesh triangle and the point we want to associate or not. The lower the number, the more strict the association will be and some poinnts on the mesh face might be wrongfully excluded.
4848
*/
4949
static void DFSegmentation::CleanUnassociatedClusters(
5050
std::vector<std::shared_ptr<geometry::DFPointCloud>> &unassociatedClusters,
5151
std::vector<std::shared_ptr<geometry::DFPointCloud>> &existingPointCloudSegments,
5252
std::vector<std::vector<std::shared_ptr<geometry::DFMesh>>> Meshes,
53-
double angleThreshold = 0.95,
53+
double angleThreshold = 0.1,
5454
double associationThreshold = 0.1);
5555

5656
private: ///< helper methods

src/diffCheckApp.cc

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,47 @@ int main()
1616
std::vector<std::shared_ptr<diffCheck::geometry::DFPointCloud>> segments;
1717
std::vector<std::string> meshPaths;
1818

19-
std::string meshesFolderPath = R"(C:\Users\localuser\Desktop\again_other_meshes_for_diffCheck\6\)";
19+
std::string meshesFolderPath = R"(C:\Users\localuser\Desktop\meshes_for_diffCheck\9\)";
2020

21-
for (int i = 1; i <= 4; i++)
21+
for (int i = 1; i <= 7; i++)
2222
{
2323
std::string meshPath = meshesFolderPath + std::to_string(i) + ".ply";
2424
std::shared_ptr<diffCheck::geometry::DFMesh> mesh = std::make_shared<diffCheck::geometry::DFMesh>();
2525
mesh->LoadFromPLY(meshPath);
2626
meshSrc.push_back(mesh);
2727
}
2828

29-
std::string pathPcdSrc = R"(C:\Users\localuser\Desktop\again_other_meshes_for_diffCheck\source_pc.ply)";
29+
std::string pathPcdSrc = R"(C:\Users\localuser\Desktop\meshes_for_diffCheck\source_pc_2.ply)";
3030

3131
pcdSrc->LoadFromPLY(pathPcdSrc);
3232

33-
pcdSrc->EstimateNormals(false, 40);
33+
pcdSrc->EstimateNormals(false, 100);
34+
pcdSrc->VoxelDownsample(0.01);
3435
auto intermediateTime = std::chrono::high_resolution_clock::now();
3536
segments = diffCheck::segmentation::DFSegmentation::NormalBasedSegmentation(
3637
pcdSrc,
37-
2.0f,
38-
200,
38+
6.0f,
39+
25,
3940
true,
40-
100,
41+
20,
4142
0.5f,
4243
false);
4344
std::cout << "number of segments:" << segments.size()<< std::endl;
4445

4546
std::shared_ptr<diffCheck::geometry::DFPointCloud> unifiedSegments =
46-
diffCheck::segmentation::DFSegmentation::AssociateClustersToMeshes(meshSrc, segments, .15);
47+
diffCheck::segmentation::DFSegmentation::AssociateClustersToMeshes(
48+
meshSrc,
49+
segments,
50+
.1,
51+
.9);
4752

48-
diffCheck::segmentation::DFSegmentation::CleanUnassociatedClusters(segments, std::vector<std::shared_ptr<diffCheck::geometry::DFPointCloud>>{unifiedSegments}, std::vector<std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>>>{meshSrc}, .15);
53+
std::cout << "Association done. refinement in progress" << std::endl;
54+
55+
diffCheck::segmentation::DFSegmentation::CleanUnassociatedClusters(segments,
56+
std::vector<std::shared_ptr<diffCheck::geometry::DFPointCloud>>{unifiedSegments},
57+
std::vector<std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>>>{meshSrc},
58+
.1,
59+
.9);
4960

5061
std::cout << "number of points in unified segments:" << unifiedSegments->Points.size() << std::endl;
5162

@@ -67,7 +78,7 @@ int main()
6778
}
6879
for(auto mesh : meshSrc)
6980
{
70-
vis.AddMesh(mesh);
81+
//vis.AddMesh(mesh);
7182
}
7283

7384
for (int i = 0; i < unifiedSegments->Points.size(); i++)

src/diffCheckBindings.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,12 @@ PYBIND11_MODULE(diffcheck_bindings, m) {
182182
.def_static("associate_clusters", &diffCheck::segmentation::DFSegmentation::AssociateClustersToMeshes,
183183
py::arg("reference_mesh"),
184184
py::arg("clusters"),
185+
py::arg("angle_threshold") = 0.95,
185186
py::arg("association_threshold") = 0.1)
186187
.def_static("clean_unassociated_clusters", &diffCheck::segmentation::DFSegmentation::CleanUnassociatedClusters,
187188
py::arg("unassociated_clusters"),
188189
py::arg("existing_point_cloud_segments"),
189190
py::arg("meshes"),
191+
py::arg("angle_threshold") = 0.95,
190192
py::arg("association_threshold") = 0.1);
191193
}

0 commit comments

Comments
 (0)