What is the output vector of the convexHull function in OpenCV? - c++

C++:
void
convexHull(InputArray points,
OutputArray hull,
bool clockwise=false,
bool returnPoints=true);
The description given on OutputArray hull is as follows:
hull – Output convex hull. It is either an integer vector of indices or vector of points. In the first case, the hull elements are 0-based indices of the convex hull points in the original array (since the set of convex hull points is a subset of the original point set). In the second case, hull elements are the convex hull points themselves.
So what is integer vector of indices ?
If I use the output array as a vector<vector<int>>, what do I get in it?
Can I print the results?

Answering to your specific questions:
Integer vector of indices (where index starts from 0) are the indices that indicates which points from InputArray points are in the set of convex hull points.
You can use either a vector of integer or vector of points. In the first case, you get the indices that allow to access to the actual point given the input array of points. In the second case, you can read directly the coordinates of the points from the output array.
This question is not entirely clear as you don't mention where you want to print the results. Assuming that you want to show it in an image, you can draw the convex hull with polylines. Specifically (look at cv::polylines for more information):
void cv::polylines (
InputOutputArray img,
InputArrayOfArrays pts,
bool isClosed,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
)
To print the coordinates of the points in the console, assuming that the output vector is a vector of integers, thus indices:
size_t hull_size = hull.size();
for (size_t i = 0; i < hull_size; i++)
{
std::cout << points[hull[i]] << std::endl;
}

Related

Calculating edge lengths of triangles obtained from Delaunay's triangulation

I have a set of discrete points and using them, I performed Delaunay's triangulation.
I want to calculate all the edge lengths from a vertex to the neighboring vertices.
How can I do/code this in c++?
I haven't tested the code that you posted, but the problem seems trivial.
In your main function after you draw all the triangles/points, get the list of all the triangles from subdiv with:
vector<Vec6f> triangleList;
subdiv.getTriangleList(triangleList);
(just like in the draw_delaunay(...) function)
Now you just iterate the triangles and compare each point of each triangle to your vertex.
If it's the same point as yours, then you calculate the lengths of edges with two other points of the triangle.
Length here = L2 norm of the vector v = point - your_vertex = Sqrt(v.x^2 + v.y^2).
There may be duplicates of some edges, so if you want to avoid it, just create a set and add all the point there and calculate the norms later.

8-neighboorhood in vector from nonZeroCoordinates

From an edge image 8UC1 obtained from Canny operator, I want to go through all white pixels and find their 8-neighboorhood.
As a first step, I apply
findNonZero(edgesFromCanny, nonZeroCoordinates);
to obtain just all white pixels to increase computational time.
The coordinates of those pixels in nonZeroCoordinates are then ordered in a row-wise manner, so that p(x=100, y =1) can be far away from p(x=100, y=2) in the nonZeroCoordinates Mat (column-wise), while p(x=100, y =1) and p(x=101, y =1) are subsequent in nonZeroCoordinates (if they are edges).
How can I (fast) retrieve the 8-neighboorhood of p(x=100, y=1) taking into account, it is an edge, too?
I found a solution using kNN, but I am not sure if this solution does not take too much computation or there can be a simpler one:
vector<Point2f> edgesVec; //Insert all 2D points to this vector
flann::KDTreeIndexParams indexParams;
flann::Index kdtree(Mat(edgesVec).reshape(1), indexParams);
vector<float> query;
query.push_back(i); //Insert the 2D point we need to find neighbours to the query
query.push_back(j); //Insert the 2D point we need to find neighbours to the query
vector<int> indices;
vector<float> dists;
kdtree.radiusSearch(query, indices, dists, 1.5, 8);

Detect extreme points of a convex polygon

How can i get the extreme points of a convex polygon looking from a determined point? I'm trying to make this by points angle, the smaller and bigger angles is the extreme points, but when observer is closer to points, this is not valid.
This is my code:
Vec2* bigger = &points[0]; // pointer to point with bigger angle
Vec2* smaller = &points[0]; // pointer to point with smaller angle
Vec2 observer = rayCenter;
// iterate through all points of polygon
for(unsigned u = 0 ; u < points.size() ; u++)
{
Vec2 distance = observer - points[u];
if(distance.angle() < (observer - *smaller).angle())
smaller = &points[u];
if(distance.angle() > (observer - *bigger).angle())
bigger = &points[u];
}
The result:
Where blue lines is the excluded points and yellow desirable points.
Is there a best way to resolve this?
Sorry for my english.
Polygon vertex A is extreme for the given location of the observer, iff all other points of the polygon lie on the same side of the observer-to-A line (or, possibly, lie on that line).
If the polygon is known to be convex, then the criterion is greatly simplified. There's no need to analyze all other points of the polygon. The extreme point can be easily recognized by analyzing the locations of its two immediate neighbors.
If A is our candidate point and P and N are its adjacent points in the polygon (previous and next), then A is an extreme point iff both P and N lie on the same side of observer-to-A line.
vec_of_A = A - observer; // observer-to-A vector
vec_of_P = P - observer;
vec_of_N = N - observer;
productP = vec_of_A.x * vec_of_P.y - vec_of_A.y * vec_of_P.x;
productN = vec_of_A.x * vec_of_N.y - vec_of_A.y * vec_of_N.x;
if (sign(productP) == sign(productN))
// A is an extreme point
else
// A is not an extreme point
Some extra decision making will be necessary if P and/or N lie exactly on the observer-to-A line (depends on what point you consider extreme in such cases).
Compute a new convex hull using the points from the existing convex hull plus the observer point. In the new convex hull, the points that are adjacent to the observer point are your "extreme" points.
Here is a matlab implementation. Below is a sample output where the blue point is the observer point and the green polygon is the convex hull of the red points. The implementation returns the points (0,0) and (2,0).
You shouldn't compare angles directly as there is a 360° wraparound.
Prefer to test "this point is more to the left" or "to the right" by computing the signed area of the triangle formed by the observer and two points.

Get coordinate values of defect's object

I found contours and hull using OpenCV methods(C++) on image. And I want to draw defects points. I found defects points by calling
vector<Vec4i> defects;
convexityDefects(contours, hull, defects);
There are 4 integer number each defect. Which one is x coordinate? I want to get defects points's coordinates. I will draw starter points of black lines which are on hand.
You'll want something like: Point p = contours[defects[d][2]]
I'll quote just the meaningful part of the documentation:
[...] 4-element integer vector: (start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices in the original contour of the convexity defect [...]
So the returned values represent indexes in the original contour.
defects[d] represents the d-th contour. Then you take its 3rd member, farthest_pt_index, which is at defects[d][2]. This integer is the index of a point in the original contour that is the farthest from the hull, i.e. the lower arrow head on the drawing. Its coordinates:
Point p = contours[defects[d][2]]
int x = p.x
int y = p.y
And if you want to know how far this point is from the hull, you'll have to divide the 4-th element by 256: float p_distance = defects[d][3] / 256.0
The doc on convexityDefects():
convexityDefects – The output vector of convexity defects. In C++ and the new Python/Java interface each convexity defect is represented as 4-element integer vector (a.k.a. cv::Vec4i): (start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices in the original contour of the convexity defect beginning, end and the farthest point, and fixpt_depth is fixed-point approximation (with 8 fractional bits) of the distance between the farthest contour point and the hull. That is, to get the floating-point value of the depth will be fixpt_depth/256.0.
So each convexity defect consists of several points, from start_index to end_index in the countour parameter of convexityDefects().

Opencv contour 1D discrete Fourier transform

A problem happened about Fourier descriptor: if a contour has K point,then let
s(k)= x(k)+i y(k),k = 0,1,...,K-1.
the s(k) discrete Fourier transform is
a(u)=∑s(k)*e^(-i2πuk/K), k = 0,1,...,K-1.
I want to inverse the contour with a(p) ,p=0,1...,P,the P is less than K.
But when use dft function in Opencv:
dft(inputarray,outputarray,DFT_INVERSE,0);
the output array has the same size with input array, how can I get a K points contour with P parameters a(p)? Thanks!!
actually the output array size should be equal to the input array size, revise the mathematical model of the DFT https://ccrma.stanford.edu/~jos/mdft/Mathematics_DFT.html