Skip to content

Commit bcd6802

Browse files
authored
Merge pull request #40 from diffCheckOrg/substractive_refinement
Substractive registration refinement
2 parents 03924e4 + c575579 commit bcd6802

File tree

9 files changed

+319
-35
lines changed

9 files changed

+319
-35
lines changed

src/diffCheck/geometry/DFMesh.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ namespace diffCheck::geometry
125125
double res = (area1 + area2 + area3 - referenceTriangleArea) / referenceTriangleArea;
126126

127127
// arbitrary value to avoid false positives (points that, when projected on the triangle, are in it, but that are actually located too far from the mesh to actually belong to it)
128-
double maxProjectionDistance = std::min({(v1 - v0).norm(), (v2 - v1).norm(), (v0 - v2).norm()});
128+
double maxProjectionDistance = std::min({(v1 - v0).norm(), (v2 - v1).norm(), (v0 - v2).norm()}) / 2;
129129

130130
if (std::abs(res) < associationThreshold && (projectedPoint - point).norm() < maxProjectionDistance)
131131
{

src/diffCheck/geometry/DFPointCloud.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ namespace diffCheck::geometry
273273
this->Normals = cloud->Normals;
274274
}
275275

276+
void DFPointCloud::AddPoints(const DFPointCloud &pointCloud)
277+
{
278+
this->Points.insert(this->Points.end(), pointCloud.Points.begin(), pointCloud.Points.end());
279+
this->Colors.insert(this->Colors.end(), pointCloud.Colors.begin(), pointCloud.Colors.end());
280+
this->Normals.insert(this->Normals.end(), pointCloud.Normals.begin(), pointCloud.Normals.end());
281+
}
282+
276283
Eigen::Vector3d DFPointCloud::GetCenterPoint()
277284
{
278285
if (this->Points.size() == 0)

src/diffCheck/geometry/DFPointCloud.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ namespace diffCheck::geometry
156156
*/
157157
void LoadFromPLY(const std::string &path);
158158

159+
/**
160+
* @brief adds the points, colors and normals from another point cloud
161+
*
162+
* @param pointCloud the other point cloud
163+
*/
164+
void AddPoints(const DFPointCloud &pointCloud);
165+
159166
public: ///< Getters
160167
/// @brief Number of points in the point cloud
161168
int GetNumPoints() const { return this->Points.size(); }

src/diffCheckApp.cc

Lines changed: 79 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,94 @@ int main()
1212
auto initTime = std::chrono::high_resolution_clock::now();
1313

1414
std::shared_ptr<diffCheck::geometry::DFPointCloud> pcdSrc = std::make_shared<diffCheck::geometry::DFPointCloud>();
15-
std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>> meshSrc = std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>>();
15+
std::vector<std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>>> meshSrc = std::vector<std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>>>();
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\meshes_for_diffCheck\9\)";
19+
std::string meshesFolderPath = R"(C:\Users\localuser\Desktop\meshes_for_diffCheck\joints\)";
2020

21-
for (int i = 1; i <= 7; i++)
21+
for (int i = 1; i <= 3; i++)
2222
{
23-
std::string meshPath = meshesFolderPath + std::to_string(i) + ".ply";
24-
std::shared_ptr<diffCheck::geometry::DFMesh> mesh = std::make_shared<diffCheck::geometry::DFMesh>();
25-
mesh->LoadFromPLY(meshPath);
26-
meshSrc.push_back(mesh);
23+
std::vector<std::shared_ptr<diffCheck::geometry::DFMesh>> fullJoint;
24+
for (int j = 1; j <= 3; j++)
25+
{
26+
std::string meshPath = meshesFolderPath + std::to_string(i) + "/" + std::to_string(j) + ".ply";
27+
std::shared_ptr<diffCheck::geometry::DFMesh> mesh = std::make_shared<diffCheck::geometry::DFMesh>();
28+
mesh->LoadFromPLY(meshPath);
29+
fullJoint.push_back(mesh);
30+
}
31+
meshSrc.push_back(fullJoint);
2732
}
2833

29-
std::string pathPcdSrc = R"(C:\Users\localuser\Desktop\meshes_for_diffCheck\source_pc_2.ply)";
34+
std::string pathPcdSrc = R"(C:\Users\localuser\Desktop\meshes_for_diffCheck\joints\full_beam.ply)";
3035

3136
pcdSrc->LoadFromPLY(pathPcdSrc);
3237

3338
pcdSrc->EstimateNormals(false, 100);
34-
pcdSrc->VoxelDownsample(0.01);
39+
pcdSrc->VoxelDownsample(0.007);
3540
auto intermediateTime = std::chrono::high_resolution_clock::now();
3641
segments = diffCheck::segmentation::DFSegmentation::NormalBasedSegmentation(
3742
pcdSrc,
38-
6.0f,
39-
25,
43+
15.0f,
44+
15,
4045
true,
41-
20,
46+
50,
4247
0.5f,
4348
false);
4449
std::cout << "number of segments:" << segments.size()<< std::endl;
4550

46-
std::shared_ptr<diffCheck::geometry::DFPointCloud> unifiedSegments =
47-
diffCheck::segmentation::DFSegmentation::AssociateClustersToMeshes(
48-
meshSrc,
51+
std::vector<std::shared_ptr<diffCheck::geometry::DFPointCloud>> unifiedSegments;
52+
for (int i = 0; i < meshSrc.size(); i++)
53+
{
54+
std::shared_ptr<diffCheck::geometry::DFPointCloud> unifiedSegment = std::make_shared<diffCheck::geometry::DFPointCloud>();
55+
unifiedSegment = diffCheck::segmentation::DFSegmentation::AssociateClustersToMeshes(
56+
meshSrc[i],
4957
segments,
50-
.1,
51-
.9);
52-
53-
std::cout << "Association done. refinement in progress" << std::endl;
58+
.2,
59+
.05);
60+
unifiedSegments.push_back(unifiedSegment);
61+
}
5462

5563
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);
60-
61-
std::cout << "number of points in unified segments:" << unifiedSegments->Points.size() << std::endl;
62-
64+
unifiedSegments,
65+
meshSrc,
66+
.2,
67+
.05);
68+
69+
// Perform a registration per joint
70+
for (int i = 0; i < meshSrc.size(); i++)
71+
{
72+
std::shared_ptr<diffCheck::geometry::DFPointCloud> referencePointCloud = std::make_shared<diffCheck::geometry::DFPointCloud>();
73+
for (auto jointFace : meshSrc[i])
74+
{
75+
std::shared_ptr<diffCheck::geometry::DFPointCloud> facePointCloud = jointFace->SampleCloudUniform(1000);
76+
referencePointCloud->Points.insert(referencePointCloud->Points.end(), facePointCloud->Points.begin(), facePointCloud->Points.end());
77+
}
78+
referencePointCloud->EstimateNormals(false, 100);
79+
80+
diffCheck::transformation::DFTransformation transformation = diffCheck::registrations::DFRefinedRegistration::O3DICP(
81+
unifiedSegments[i],
82+
referencePointCloud);
83+
84+
std::cout << "Transformation matrix:" << std::endl;
85+
std::cout << transformation.TransformationMatrix << std::endl;
86+
87+
diffCheck::visualizer::Visualizer deVisu = diffCheck::visualizer::Visualizer("DiffCheckApp", 1000, 800, 50, 50, false, true, false);
88+
for (int i = 0; i < segments.size(); i++)
89+
{
90+
segments[i]->ApplyTransformation(transformation);
91+
deVisu.AddPointCloud(segments[i]);
92+
}
93+
for (auto joint : meshSrc)
94+
{
95+
for (auto face : joint)
96+
{
97+
deVisu.AddMesh(face);
98+
}
99+
}
100+
deVisu.Run();
101+
}
102+
63103
diffCheck::visualizer::Visualizer vis(std::string("DiffCheckApp"), 1000, 800, 50, 50, false, true, false);
64104
for (auto segment : segments)
65105
{
@@ -74,18 +114,25 @@ int main()
74114
segment->Colors.push_back(Eigen::Vector3d(0, 0, 0));
75115
}
76116
vis.AddPointCloud(segment);
77-
78117
}
79-
for(auto mesh : meshSrc)
118+
for(auto joint : meshSrc)
80119
{
81-
//vis.AddMesh(mesh);
120+
for(auto mesh : joint){vis.AddMesh(mesh);}
82121
}
83122

84-
for (int i = 0; i < unifiedSegments->Points.size(); i++)
123+
int numSegments = unifiedSegments.size();
124+
125+
for (int i = 0; i < numSegments; i++)
85126
{
86-
unifiedSegments->Colors.push_back(Eigen::Vector3d(0, 0, 1));
127+
for (int j = 0; j < unifiedSegments[i]->Points.size(); j++)
128+
{
129+
unifiedSegments[i]->Colors.push_back(Eigen::Vector3d((double(numSegments) - double(i))/double(numSegments), 1, double(i) / double(numSegments)));
130+
}
131+
}
132+
for (auto seg : unifiedSegments)
133+
{
134+
vis.AddPointCloud(seg);
87135
}
88-
vis.AddPointCloud(unifiedSegments);
89136

90137
auto endTime = std::chrono::high_resolution_clock::now();
91138
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - initTime);
@@ -95,6 +142,5 @@ int main()
95142

96143
vis.Run();
97144

98-
99145
return 0;
100146
}

src/diffCheckBindings.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ PYBIND11_MODULE(diffcheck_bindings, m) {
4848
py::arg("r"), py::arg("g"), py::arg("b"))
4949

5050
.def("load_from_PLY", &diffCheck::geometry::DFPointCloud::LoadFromPLY)
51+
.def("add_points", &diffCheck::geometry::DFPointCloud::AddPoints)
5152

5253
.def("get_tight_bounding_box", &diffCheck::geometry::DFPointCloud::GetTightBoundingBox)
5354

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#! python3
2+
3+
import Rhino
4+
5+
import diffCheck
6+
from diffCheck import diffcheck_bindings
7+
from diffCheck import df_cvt_bindings as df_cvt
8+
import diffCheck.df_util
9+
10+
from ghpythonlib.componentbase import executingcomponent as component
11+
12+
ABSTOL = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance
13+
14+
class DFJointSegmentator(component):
15+
def RunScript(self,
16+
i_clusters: Rhino.Geometry.PointCloud,
17+
i_joints: Rhino.Geometry.Mesh,
18+
i_joint_ids: int,
19+
i_angle_threshold: float,
20+
i_distance_threshold: float):
21+
"""
22+
Amongst clusters, associates the clusters to the individual joints,
23+
creates a reference point cloud for each joint,
24+
and returns the joint segments, the reference point clouds, and the ICP transformations from the first to the second.
25+
26+
:param i_clusters: The clusters to be associated to the joints.
27+
:param i_joints: The joints to which the clusters will be associated. These are meshes.
28+
:param i_joint_ids: The joint ids of the joints.
29+
:param i_angle_threshold: The angle threshold for the association of the clusters to the joints.
30+
:param i_distance_threshold: The distance threshold for the association of the clusters to the joints.
31+
"""
32+
if i_angle_threshold is None : i_angle_threshold = 0.1
33+
if i_distance_threshold is None : i_distance_threshold = 0.1
34+
35+
if len(i_joints) != len(i_joint_ids):
36+
raise ValueError("The number of joints and joint ids must be the same.")
37+
38+
if len(i_clusters) == 0:
39+
raise ValueError("No clusters given.")
40+
41+
if not isinstance(i_clusters[0], Rhino.Geometry.PointCloud):
42+
raise ValueError("The input clusters must be PointClouds.")
43+
44+
if not isinstance(i_joints[0], Rhino.Geometry.Mesh):
45+
raise ValueError("The input joints must be convertible to Meshes.")
46+
47+
48+
# prepping the reference meshes
49+
n_joints = max(i_joint_ids) + 1
50+
joints = [ [] for i in range(n_joints) ]
51+
for face, id in zip(i_joints, i_joint_ids):
52+
face.Subdivide()
53+
face.Faces.ConvertQuadsToTriangles()
54+
joints[id].append(df_cvt.cvt_rhmesh_2_dfmesh(face))
55+
56+
joint_clouds = []
57+
registrations = []
58+
joint_segments = []
59+
df_clouds = [df_cvt.cvt_rhcloud_2_dfcloud(cluster) for cluster in i_clusters]
60+
61+
# for each joint, find the corresponding clusters and merge them, generate a reference point cloud, and register the merged clusters to the reference point cloud
62+
for joint in joints:
63+
64+
# create the reference point cloud
65+
joint_cloud = diffcheck_bindings.dfb_geometry.DFPointCloud()
66+
67+
for face in joint:
68+
face_cloud = face.sample_points_uniformly(1000)
69+
joint_cloud.add_points(face_cloud)
70+
71+
joint_clouds.append(df_cvt.cvt_dfcloud_2_rhcloud(joint_cloud))
72+
73+
# find the corresponding clusters and merge them
74+
segment = diffcheck_bindings.dfb_segmentation.DFSegmentation.associate_clusters(joint, df_clouds, i_angle_threshold, i_distance_threshold)
75+
diffcheck_bindings.dfb_segmentation.DFSegmentation.clean_unassociated_clusters(df_clouds, [segment], [joint], i_angle_threshold ,i_distance_threshold)
76+
77+
# register the merged clusters to the reference point cloud
78+
registration = diffcheck_bindings.dfb_registrations.DFRefinedRegistration.O3DICP(segment, joint_cloud)
79+
res = registration.transformation_matrix
80+
81+
registrations.append(df_cvt.cvt_ndarray_2_rh_transform(res))
82+
joint_segments.append(df_cvt.cvt_dfcloud_2_rhcloud(segment))
83+
84+
return joint_segments, registrations, joint_clouds
85+
86+
# if __name__ == "__main__":
87+
# o_joint_segments, o_reference_point_clouds, o_transforms = main(i_clusters, i_joints, i_joint_ids)
88+
89+
# for i in range(len(o_joint_segments)):
90+
# o_joint_segments[i].Transform(o_transforms[i])
731 Bytes
Loading

0 commit comments

Comments
 (0)