-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathransac2d.cpp
176 lines (136 loc) · 4.49 KB
/
ransac2d.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
169
170
171
172
173
174
175
176
/* \author Aaron Brown */
// Quiz on implementing simple RANSAC line fitting
#include "/home/workspace/SFND_Lidar_Obstacle_Detection/src/render.h"
#include "/home/workspace/SFND_Lidar_Obstacle_Detection/src/render/box.h"
#include <unordered_set>
#include ".../.../processPointClouds.h"
// using templates for processPointClouds so also include .cpp to help linker
#include "/home/workspace/SFND_Lidar_Obstacle_Detection/src/processPointClouds.cpp"
pcl::PointCloud<pcl::PointXYZ>::Ptr CreateData()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
// Add inliers
float scatter = 0.6;
for(int i = -5; i < 5; i++)
{
double rx = 2*(((double) rand() / (RAND_MAX))-0.5);
double ry = 2*(((double) rand() / (RAND_MAX))-0.5);
pcl::PointXYZ point;
point.x = i+scatter*rx;
point.y = i+scatter*ry;
point.z = 0;
cloud->points.push_back(point);
}
// Add outliers
int numOutliers = 10;
while(numOutliers--)
{
double rx = 2*(((double) rand() / (RAND_MAX))-0.5);
double ry = 2*(((double) rand() / (RAND_MAX))-0.5);
pcl::PointXYZ point;
point.x = 5*rx;
point.y = 5*ry;
point.z = 0;
cloud->points.push_back(point);
}
cloud->width = cloud->points.size();
cloud->height = 1;
return cloud;
}
pcl::PointCloud<pcl::PointXYZ>::Ptr CreateData3D()
{
ProcessPointClouds<pcl::PointXYZ> pointProcessor;
return pointProcessor.loadPcd("../../../sensors/data/pcd/simpleHighway.pcd");
}
pcl::visualization::PCLVisualizer::Ptr initScene()
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer ("2D Viewer"));
viewer->setBackgroundColor (0, 0, 0);
viewer->initCameraParameters();
viewer->setCameraPosition(0, 0, 15, 0, 1, 0);
viewer->addCoordinateSystem (1.0);
return viewer;
}
std::unordered_set<int> Ransac(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, int maxIterations, float distanceTol)
{
auto startTime = std::chrono::steady_clock::now();
std::unordered_set<int> inliersResult;
srand(time(NULL));
// TODO: Fill in this function
// For max iterations
// Randomly sample subset and fit line
// Measure distance between every point and fitted line
// If distance is smaller than threshold count it as inlier
// Return indicies of inliers from fitted line with most inliers
while(maxIterations--)
{
//Randomly pick two points
std::unordered_set<int> inliers;
while (inliers.size() < 2)
inliers.insert(rand()%(cloud->points.size()));
float x1 , y1 , x2 , y2;
auto itr = inliers.begin();
x1 = cloud->points[*itr].x;
y1 = cloud->points[*itr].y;
itr++;
x2 = cloud->points[*itr].x;
y2 = cloud->points[*itr].y;
float a = (y1-y2);
float b = (x2-x1);
float c = (x1*y2-x2*y1);
for (int index = 0; index < cloud->points.size(); index ++)
{
if(inliers.count(index) > 0)
continue;
pcl::PointXYZ point = cloud->points[index];
float x3 = point.x;
float y3 = point.y;
float d = fabs(a*x3+b*y3+c)/sqrt(a*a+b*b);
if (d <= distanceTol)
inliers.insert(index);
}
if(inliers.size()>inliersResult.size())
{
inliersResult = inliers;
}
}
auto endTime = std::chrono::steady_clock::now();
auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
std::cout << "RANSAC TOOK " << elapsedTime.count() << "milliseconds" << std::endl;
return inliersResult;
}
int main ()
{
// Create viewer
pcl::visualization::PCLVisualizer::Ptr viewer = initScene();
// Create data
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = CreateData();
// Create data
// pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = CreateData3D();
// TODO: Change the max iteration and distance tolerance arguments for Ransac function
std::unordered_set<int> inliers = Ransac(cloud, 10, 1.0);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudInliers(new pcl::PointCloud<pcl::PointXYZ>());
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOutliers(new pcl::PointCloud<pcl::PointXYZ>());
for(int index = 0; index < cloud->points.size(); index++)
{
pcl::PointXYZ point = cloud->points[index];
if(inliers.count(index))
cloudInliers->points.push_back(point);
else
cloudOutliers->points.push_back(point);
}
// Render 2D point cloud with inliers and outliers
if(inliers.size())
{
renderPointCloud(viewer,cloudInliers,"inliers",Color(0,1,0));
renderPointCloud(viewer,cloudOutliers,"outliers",Color(1,0,0));
}
else
{
renderPointCloud(viewer,cloud,"data");
}
while (!viewer->wasStopped ())
{
viewer->spinOnce ();
}
}