# Assignment 04: RanSaC line fit
## Summary
Copyright By PowCoder代写 加微信 powcoder
This assignment continues, and builds from, the work in the previous assignment.
In `Assignment 03 – Problem 1` you have implemented the classes `Point`, `Line`,
and `LineLsq`. In this assignment, you have to reuse those implementations and
add the code for `LineRansac`, a class similar to `LineLsq` in the sense that
it also estimates a 2-dimensional line from a set of 2-dimensional points.
The [RanSaC](https://en.wikipedia.org/wiki/Random_sample_consensus)
(Random Sample Consensus) algorithm differs from a least squares line fit
in that the former is “robust” to outliers and the latter is not. That means,
the input set of points may include points which belong to the line, and points
which are not part of this line. For example, points from some other line,
or maybe just random noise. The RanSaC algorithm, given the correct parameters,
will succeed on identifying which points actually belong to the line
(i.e. “inlier points”) and which ones do not belong to this line
(i.e. “outlier points”). Once the inliers have been identified,
a least squares line fit is used on the inlier points.
In the last assignment, we used C-style arrays to collect our points and
pass them to functions. In this assignment, we will implement our own `Vector`
class using C++ templates, and use it for storing the points and point indices.
As usual, the goal of the assignment is to practice implementing in C++ the
requested functionality and classes, in order to practice the topics covered
in the lectures. In this assignment, we want to implement our own `Vector`
class from scratch. Please be cautious on using functions, classes, and other
concepts not covered in the lectures and lecture’s materials. When in doubt ask,
or just implement what you need with simple C++ concepts (e.g. conditionals,
loops, and basic math).
In this assignment we will:
– Practice writing class templates
– Implement a `Vector` class similar to `std::vector`
– Use our `Vector` class for holding points and passing them to functions
– Use the standard library random number generator and distributions
– Implement a robust line fit algorithm
## Grading
The assignment grade is based on automatic testing results, adherence to
the assignment rules, and specific details of the implemented solution.
A file named `NOTES.txt` is included in this repository. Students may use
this file to write any comment about the assignment and its solution.
In this particular case, 50% of the grade corresponds to the implementation
of the `Vector` class, 45% corresponds to the implementation of `LineRansac`
class, and 5% to the implementation of the `linefit_ransac` program.
## General Instructions
1. Download the starter code using `git clone
2. Open a command line shell and execute `./build.sh` or `build.bat` to
generate the project files using `CMake` and to compile the provided code.
3. Open any file you want edit with a text editor or C++ development
environment (e.g. Visual Studio, Xcode) and add your code to them.
4. Compile your code again with `./build.sh` or `build.bat`, or using the
development environment.
5. Execute the programs and verify they work as expected based on the
specific instructions for each problem.
6. Repeat steps 3-5 as many times as desired.
7. Once you are satisfied with the result, save your changes using a
`git commit` command. For example `git commit -a -m “Complete assignment”`.
8. Upload your assignment using `git push`.
You can use `git commit` and/or `git push` as many times as desired. For
instance, to save work in progress.
## Before you start
This assignment continues the work from `Assignment 03 – Problem 1`. In order
to solve this assignment you need working versions of the `Point`, `Line`, and
`LineLsq` classes. You need to take those from your own Assignment 03 solution.
Before you start, go ahead and copy the files:
– prob1/Point.hpp
– prob1/Point.cpp
– prob1/Line.hpp
– prob1/Line.cpp
– prob1/LineLsq.hpp
– prob1/LineLsq.cpp
and overwrite the versions provided here.
Please be careful about not copying `CMakeLists.txt`.
## Problem 1 Part 1: Vector class
Implement a Vector class capable of holding elements of arbitrary types using
C++ templates. A skeleton header file is provided. Specific instructions about
which features this class must support are included in such file.
Once implemented, code like the following must work as expected:
course::Vector
v1.push_back(1);
v1.push_back(2);
int sum{ 0 };
for (int i = 0; i < v1.size(); ++i)
sum += v1[i];
std::cout "sum = " << sum << std::endl; //displays "sum = 3"
course::Vector
v1.push_back({1, 2});
v1.push_back({3, 4});
course::Point centroid;
for (int i = 0; i < v1.size(); ++i)
centroid = centroid + v1[i];
centroid = centroid / static_cast
std::cout “centroid = (” << centroid.x() << ", " << centroid.y() << ")"
<< std::endl; //displays "centroid = (2, 3)"
The complete implementation must be written in the file `prob1/Vector.hpp`.
Remember that template classes must be completely contained in header files,
as opposed to regular classes that we split in header and source files.
Refer to the slides and material covered in lecture for additional details
about C++ templates and the vector data structure.
## Problem 1 Part 2: RanSaC line fit
`linefit_ransac` is a command-line application which takes a list of points,
and estimates the line that best fits them with the RanSaC algorithm. A plot
showing the input points and fitted line is also created. The first two
arguments to this program are the number of iterations and the inliers distance
threshold. The following arguments are point coordinates.
### Example
$ ./build/prob1/Release/linefit_ransac.exe 30 0.2 -5 5.1 -3.6 4.98 -3.4 4.95 -1.9 5 -0.6 5 0.4 0.06 0.5 4.94 1.5 0.05 1.8 0.04 2.6 0.05
NumIter: 30
DistThreshold: 0.2
0 Point{x=-5,y=5.1}
1 Point{x=-3.6,y=4.98}
2 Point{x=-3.4,y=4.95}
3 Point{x=-1.9,y=5}
4 Point{x=-0.6,y=5}
5 Point{x=0.4,y=0.06}
6 Point{x=0.5,y=4.94}
7 Point{x=1.5,y=0.05}
8 Point{x=1.8,y=0.04}
9 Point{x=2.6,y=0.05}
Line{a=0.0169941,b=0.999856,c=-4.95463}
RMSE 0.0413627
Saved: lineplot_ransac.svg
![Example linefit_ransac plot](example-lineplot_ransac.svg "Example linefit_ransac plot")
In the plot, outlier points are shown in red.
### RanSaC algorithm
RanSaC was discussed in lecture, please review that material and make sure you
understand how the algorithm works prior to starting writing your code.
Implement RanSaC in two parts:
1. Identify inlier points.
2. Fit a line to the inlier points with the least squares method.
#### Identify inlier points
Inlier points are those we determine belong to the line. On the contrary,
outlier points are those we determine do not belong to the line. The first
part of the algorithm consists of splitting the input points into inliers
and outliers.
This part of the algorithm is iterative. We repeat the same process as many
times as specified by the `numIter` argument in the `solve` member function.
At each iteration we do the following:
1. Pick two points randomly: `p1` and `p2`
2. Construct a line passing through `p1` and `p2`: `Line line{p1,p2}`
3. Determine which points are inliers to this candidate line.
For each point `p` in `points` do:
a. Compute distance to current candidate line: `dist(line,p)`
b. If the distance is less than `distThreshold` then this point is an
inlier. The value of `distThreshold` is an input argument of `solve`.
4. If this candidate line has more inliers than previous candidate lines,
then keep this set of inliers as the current "best" set. Otherwise,
abandon this candidate and continue to the next iteration.
After executing all iterations, we have one set of inlier points corresponding
to the best candidate line produced by the random sampling algorithm. The set
of inliers is the result of this step.
#### Least squares line fit
Take the inlier points produced in the last step and fit a line to them using
the implementation of `LineLsq` from previous assignment. The result line and
corresponding RMSE value are the results of the RanSaC line fit.
#### Random sampling
In order to pick points randomly use a uniform distribution. You can use code
similar to the following:
std::mt19937 gen{ 12345 };
std::uniform_int_distribution distrib(0, numPts - 1);
where the number `12345` is the seed of the random number generator and can
replaced by any other number of choice, and `numPts` is the number of input
Then, each time you need to pick a point at random, you can do this:
int index{ distrib(gen) }; //generates a number in [0, numPts-1]
const Point& p{ points[index] };
Make sure of selecting two different points each time you need to make a new
line candidate. You can do that in several ways. For instance, generate two
indices, check if they are different, and discard them and generate new ones
when they are not.
### Program linefit_ransac
`linefit_ransac` is a command-line program that fits a line using RanSaC and
makes a plot of the line and points. The application takes several arguments
being the first two the parameters `numIter` and `distThreshold` corresponding
to the number of iterations and inlier distance threshold required by RanSaC.
The following arguments are the coordinates of the input points.
linefit_ransac numIter distThreshold x1 y1 x2 y2 x3 y3 ...
Consider the following:
- `numIter` is a positive number
- `distThreshold` is a non-negative floating point number
- each `(x, y)` pair corresponds to one point
- at least two different points are required to successfully fit a line
- the program must display `ERROR` and some error message on error situations.
The program must place the input points in a `Vector` object and call your
own implementation of `LineRansac` to fit a line. On success, display the
line, RMSE, number of inliers and call the function `makePlot` to create
a plot. On failure, display an error message.
The program must always return 0.
Refer to the example execution above for reference of how to call this program
and possible result.
## Assignment requirements
Complete the requested implementations by following both the instructions in
this page and in the source code files.
In this assignment the same conventions as previous ones were used for naming
files and classes. For instance, the class `LineRansac` is given in the files
`LineRansac.hpp` and `lineRansac.cpp`.
Use your code to write the implementations and only use standard library
functions for things that are usually allowed such as math operations.
For random number generation the standard library should be used.
## References
- [uniform_int_distribution](https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution)
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com