Connecting the dots on the given diagram - c++

What is the best or easiest way to connect the dots on the given diagram. I would like to connect the dots to form a rectangle. The dots are initially blue color.

If you want to create tetragon (shape with 4 vertixes) instead of rectangle (shape with 4 vertixes and all angles equal to 90 degrees) - i. e. connect points that human can simply classify as lines, the simplest way is creating array with points coordinates, and then applying cv::approxPolyDP or cv::convexHull.

You did not specified what kind of shapes you want to get, convex or concave.
Miki mentioned convex hull algorithm.
You can also search for Concave Hull algorithm.
Here is one of possible sources in C++:
https://bitbucket.org/vostreltsov/concave-hull/src
Here is also some theory: http://www.it.uu.se/edu/course/homepage/projektTDB/ht13/project10/Project-10-report.pdf
Or if you search for rectangles only then take a look at cv::minAreaRect method from OpenCV.

Related

Remove contour defects [OpenCV]

I want to generalize this question: How to crop away convexity defects.
Situation described there is clear to me but I have more complex situation: I have a contour which can have not only convex, but a concave defects:
Blue is the contour I have and red is a rectangle I want - it can be rotated rectangle in general, so I need 4-point rectangular contour with area is as close as possible to the given contour. I'm looking for algorithm on how this transformation function could be implemented and it would be nice if it will be illustrated with code.
My idea would be to perform a Hough transform on the contour and choose the top 4 most prominent lines as the edges of the rectangle.
You should draw the contour as a b&w image and pass that to HoughLines. It will return a vector of (r, theta) pairs, which encode the detected lines in polar coordinates. See this example for how to convert them back to cartesian coordinates.
The lines will be ordered by decreasing number of "votes" (i.e. the sum of pixel intensities along the line).
Note that HoughLinesP is less suitable for the problem at hand, because it returns line segments, not lines.
The approach from the linked answer can only handle convexity defects based on deviation from the convex hull, I don't think you can use the opposite approach to remove 'concavity defects' (which grow the convex hull and make other features the defects).
You could try the following:
Run the solution from the linked answer to remove convex defects
On the resulting feature, iteratively call cv::ApproxPoly with varying accuracy parameter (e.g. 0.0, 0.5, 1.0...) until it approximates to a 4 sided shape.

OpenCV 'Almost' Closed contours

I'm trying to extract the cube from the image (looks like a square...). I've used canny and dilate to get the edges and remove the noise.
I'm not even sure if it is possible to get the square out in a robust way.
Advice appreciated!
Thanks.
It's not excessively hard.
Sort all edges by direction. Look for a pair of edges in one direction with another pair 90 degrees rotated. Check for rough proximity. If so, they probably form a rectangle. Check the edge distances to pick the squares from the rectangles, and to discard small squares. Check if you have sufficiently large parts of the edge to be convinced the entire edge must exist. An edge might even be broken in 2. Check if the 4 edges now found delimit an area that is sufficiently uniform.
The last bit is a bit tricky. That's domain knowlegde. Could there be other objects inside the square, and could they touch or overlap the edges of the square?
You can utilize color information and kmeans clustering as explained in the link.
As long as target object color differs from the background, the pixels of the square object can be detected accurately.

linear separability of points in a plane

I am creating an algorithm using c++.
I have a plane of 320*240 pixels and a line (y=ax + b) that separates the plane in 2 polygons.
Given these information I would like to ask, if it is possible to know, in which of the 2 polygons, a new pixel(x,y) belongs to.
you can separate according to if
y<ax+b or y>ax+b

Find points of angles in a rectangle in 3D coordinate system

I have points in 3D which make 2 or 3 side of rectangle. How I can calculate the coordinates of the cube's corners? Is it possible?
Updated: https://github.com/CPIGroup/3d-Camera-scanDimensions
This is just an idea, not a proven method.
First, find the planes. Randomly select 3 points, find a plane that passes through them, normalize the 4 parameters. Repeat 1000 or so times. You will end up with 1000 4-tuples of numbers. Use one of the clustering analysis methods to find 2 or 3 groups of 4-tuples that are very close together. Average each of the groups. These will be, approximately, planes of your box's sides.
Now make them more precise. For each plane, find all points that are close to it but not close to other planes (for some value of "close", perhaps to be found using a clustering method too). For each such group of points, find a best fit plane using least squares.
If you have three planes, great; intersect them and you have a vertex and three edges. For two planes, you only have one edge. Either way, you can now try to find other edges. For simplicity, consider your plane to be an XY plane and your known edge an X axis. You now need to find the leftmost (rightmost) vertical line such that most of the points are to the left (resp. right) of it. Project all the points to the X axis. You now have a 1-dimensional case of your original problem: there is a lot of random points on some interval, find the interval. Use a clustering method again.
I'm not super experienced with this, but possibly you could use RANSAC ?
There seem to be many papers on the plane detection from pointclouds using RANSAC
Also you might want to have a look at the Point Clouds Library(PCL).It's a pretty impressive project with many useful features including also planar segmentation
As soon as the planes are detected, it should be a matter of finding the edges/corners which should be a lot simpler.

How to form a Concave shape out of Convex shapes?

i'm trying to get around the rule of only being able to form convex shapes in the SFML c++ library.
To do this I'm planning on testing given vertices, and if concave,
splitting the vertices into groups, testing each groups' concaveness,
and repeating until a full set of concave shapes results that look
just like the original shape when put together
What I would like to know is...
What the equation for testing a shapes concaveness is: What is it and how does it work?
How would i split up the vertices of the concave shape so in the end the shape is formed out of as few convex shapes as possible?
Whats the best practice for achieving my goal?
Thanks!
You can test for a shape being a convex hull by going round all the edges and checking the next edge is always moving in the same direction (left/right handed). This is a quick and cheap algorithm. There is an implementation of this here: en.wikipedia.org/wiki/Graham_scan
If you don't have a convex hull, perform a package wrapping algorithm to get a convex hull that encompasses all your points (again quite fast). en.wikipedia.org/wiki/Gift_wrapping_algorithm
Now, look for points that are on your shape, but aren't on the convex hull. For each run of these points, create a new shape from these points (plus the 2 either side on the convex hull).
Recursion is now your friend: do the exact same process on each of the sub-shapes you have just made.
I have used this techniques to test for a point being contained inside an arbitrary shape: i.e. the point must be inside the convex hull (easy to test), but not any of the sub-shapes, or their sub-shapes, or their sub-shapes....
The Boost Geometry library that was published yesterday, has an implementation of Convex Hull algorithm. A picture says more than a thousand words:
Although this constructs a 'new' shape that is non-concave (i.e. convex); This may or may not be precisely what you want. However, in the process the algorithm is bound to be able to classify shape a concave/convex, so you'd likely be interested in the library nonetheless.
General information on convex hull algorithm:
http://en.wikipedia.org/wiki/Convex_hull
http://en.wikipedia.org/wiki/Convex_hull_algorithms
Since Adrian Japon more or less suggested that 'hit testing' (containment test) is of a usual reason to care about convex/concave geometries, without further ado, I'll highlight the corresponding Boost Geometry algorithm for that: within.
Again, really because the picture is so pretty. Note that though the picture suggests querying for a point against a polygon, the algorithms are fully generic and can be used to test complete containment on n-dimensional polygons in another
Alright, just to mash all the info together:
To test polygon Concaveness, look at this page given by Adrian
Taylor
One way to accomplish my goal is to use Monotone Decomposition and Triangulation
You can learn about Monotone Decomposition at this lovely site: (summary of it below)
Finally, triangulate the now Monotone shapes using the information in this Powerpoint:
Push u1 and u2 on the stack.
j = 3 /* j is index of current vertex */
u = uj
Case (i): u is adjacent to v1 but not vi.
add diagonals uv2, uv3, …, uvi.
pop vi, vi-1, …, v1 from stack.
push vi, u on stack.
Case (ii): u is adjacent to vi but not v1.
while i > 1 and angle uvivi-1 < 
add diagonal uvi-1
pop vi from stack
endwhile
push u
Case (iii): u adjacent to both v1 and vi.
add diagonals uv2, uv3, …, uvi-1.
exit
j = j + 1
Go to step 3.
**Note:**
By “adjacent” we mean connected by an edge in P.
Recall that v1 is the bottom of the stack, vi is the top.
By “Push” we mean push the item(s) to the back of the list
Hope this helps someone... but I'm still looking for any better/faster solutions.
Some things to think about:
Left-handed and right-handed corners (the sign of the cross-product is an easy way to distinguish). All corners in a convex shape are the same handed-ness.
Extending an edge and adding a new vertex may give you better results than adding edges between existing vertices.
I assume you have your polygon as a list of point, a very simple way would be to go around your polygon and consider the sequence of triplet of consecutive points (A,B,C).
Then you just check that at one point det(AB,BC) changes its sign, where
det(AB,AC) = (x_a-x_b)(yc-yb) - (x_c-x_b)(y_a-y_b)