-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathcluster.cpp
168 lines (137 loc) · 5.42 KB
/
cluster.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* \author Aaron Brown */
// Quiz on implementing simple RANSAC line fitting
#include "../../render/render.h"
#include "../../render/box.h"
#include <chrono>
#include <string>
#include "kdtree.h"
// Arguments:
// window is the region to draw box around
// increase zoom to see more of the area
pcl::visualization::PCLVisualizer::Ptr initScene(Box window, int zoom)
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("2D Viewer"));
viewer->setBackgroundColor(0, 1, 1);
viewer->initCameraParameters();
viewer->setCameraPosition(0, 0, zoom, 0, 1, 0);
viewer->addCoordinateSystem(1.0);
viewer->addCube(window.x_min, window.x_max, window.y_min, window.y_max, 0, 0, 1, 1, 1, "window");
return viewer;
}
pcl::PointCloud<pcl::PointXYZ>::Ptr CreateData(std::vector<std::vector<float>> points)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
for(int i = 0; i < points.size(); i++)
{
pcl::PointXYZ point;
point.x = points[i][0];
point.y = points[i][1];
point.z = 0;
cloud->points.push_back(point);
}
cloud->width = cloud->points.size();
cloud->height = 1;
return cloud;
}
void render2DTree(Node* node, pcl::visualization::PCLVisualizer::Ptr& viewer, Box window, int& iteration, uint depth=0)
{
if (node!=NULL)
{
Box upperWindow = window;
Box lowerWindow = window;
// split on x axis
if (depth%2==0)
{
viewer->addLine(pcl::PointXYZ(node->point[0], window.y_min, 0),pcl::PointXYZ(node->point[0], window.y_max, 0),0,0,1,"line"+std::to_string(iteration));
lowerWindow.x_max = node->point[0];
upperWindow.x_min = node->point[0];
}
// split on y axis
else
{
viewer->addLine(pcl::PointXYZ(window.x_min, node->point[1], 0),pcl::PointXYZ(window.x_max, node->point[1], 0),1,0,0,"line"+std::to_string(iteration));
lowerWindow.y_max = node->point[1];
upperWindow.y_min = node->point[1];
}
iteration++;
render2DTree(node->left,viewer, lowerWindow, iteration, depth+1);
render2DTree(node->right,viewer, upperWindow, iteration, depth+1);
}
}
// find nearby points for a given target point, add them to the same cluster
void clusterHelper(const std::vector<std::vector<float>>& points, std::vector<bool>& processedPoints, int index, std::vector<int>& cluster, KdTree* tree, float distanceTol)
{
processedPoints[index] = true;
cluster.push_back(index);
std::vector<int> proximity = tree->search(points[index], distanceTol);
for (int id : proximity)
{
if (!processedPoints[id])
{
clusterHelper(points, processedPoints, id, cluster, tree, distanceTol);
}
}
}
std::vector<std::vector<int>> euclideanCluster(const std::vector<std::vector<float>>& points, KdTree* tree, float distanceTol)
{
std::vector<std::vector<int>> clusters;
std::vector<bool> processedPoints(points.size(), false); // map the processed points
for (int i = 0; i < points.size(); ++i)
{
if (processedPoints[i])
continue;
std::vector<int> cluster;
clusterHelper(points, processedPoints, i, cluster, tree, distanceTol);
clusters.push_back(cluster);
}
return clusters;
}
int main()
{
// Create viewer
Box window;
window.x_min = -10;
window.x_max = 10;
window.y_min = -10;
window.y_max = 10;
window.z_min = 0;
window.z_max = 0;
pcl::visualization::PCLVisualizer::Ptr viewer = initScene(window, 25);
// Create data
std::vector<std::vector<float>> points = { {-6.2,7}, {-6.3,8.4}, {-5.2,7.1}, {-5.7,6.3}, {7.2,6.1}, {8.0,5.3}, {7.2,7.1}, {0.2,-7.1}, {1.7,-6.9}, {-1.2,-7.2}, {2.2,-8.9} };
//std::vector<std::vector<float>> points = { {-6.2,7}, {-6.3,8.4}, {-5.2,7.1}, {-5.7,6.3} };
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = CreateData(points);
KdTree* tree = new KdTree;
for (int i=0; i<points.size(); i++)
tree->insert(points[i],i);
int it = 0;
render2DTree(tree->root,viewer,window, it);
std::cout << "Test Search" << std::endl;
std::vector<int> nearby = tree->search({-6,7},3.0);
for (int index : nearby)
std::cout << index << ",";
std::cout << std::endl;
// Time segmentation process
auto startTime = std::chrono::steady_clock::now();
std::vector<std::vector<int>> clusters = euclideanCluster(points, tree, 3.0);
auto endTime = std::chrono::steady_clock::now();
auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
std::cout << "clustering found " << clusters.size() << " and took " << elapsedTime.count() << " milliseconds" << std::endl;
// Render clusters
int clusterId = 0;
std::vector<Color> colors = {Color(1,0,0), Color(0,1,0), Color(0,0,1)};
for (std::vector<int> cluster : clusters)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr clusterCloud(new pcl::PointCloud<pcl::PointXYZ>());
for(int indice: cluster)
clusterCloud->points.push_back(pcl::PointXYZ(points[indice][0],points[indice][1],0));
renderPointCloud(viewer, clusterCloud,"cluster"+std::to_string(clusterId),colors[clusterId%3]);
++clusterId;
}
if (clusters.size()==0)
renderPointCloud(viewer,cloud,"data");
while (!viewer->wasStopped())
{
viewer->spinOnce();
}
}