what are best features to detect a contour by comparison to a saved one?
for now i have the following on the table and will use ratios between some of them (preliminary results are good):
-enclosing area circle
-bounding rectangle area
-bounding rectangle height over width
-perimeter (arc length)
-convex hull polygon area (using the polygon area formula)
which ones will be most distinct between different shapes and will be most accurate when compared (ratioA - ratioB < threshold) so i dont waste computing power on all together?
ps: should also work with scale and rotation
There is a module shape in OpenCV that contains two shape comparators: ShapeContextDistanceExtractor and HausdorffDistanceExtractor. Both require only two contours as arguments and return single number (a distance between these contours in some space) that you can treat as a measure of dissimilarity.
Easier way is to try cv::matchShapes(): this function calculates two vectors of invariant Hu moments for each contour and then calculates their dissimilarity based on these vectors as well.
Related
Good day.
I have the task of finding the set of points in 2D space for which the sum of the distances to the rectangles is minimal. For example, for two rectangles, the result will be the next area (picture). Any point in this area has the minimum sum of lengths to A and B rectangles.
Which algorithm is suitable for finding a region, all points of which have the minimum sum of lengths? The number of rectangles can be different, they are randomly located. They can even overlap each other. The sides of the rectangles are parallel to the coordinate axes and cannot be rotated. The region must be either a rectangle or a line or a point.
Hint:
The distance map of a rectangle (function that maps any point (x,y) to the closest distance to the rectangle) is made of four slanted planes (slope 45°), four quarter of cones and the rectangle itself, which is at ground level, forming a continuous surface.
To obtain the global distance map, it "suffices" to sum the distance maps of the individual rectangles. A pretty complex surface will result. Depending on the geometries, the minimum might be achieved on a single vertex, a whole edge or a whole face.
The construction of the global map seems more difficult than that of a line arrangement, due to the conic patches. A very difficult problem in the general case, though the axis-aligned constraint might ease it.
Add on Yves's answer.
As Yves described, each rectangle 'divide' plane into 9 parts and adds different distance method in to the sum. Middle part (rectangle) add distance 0, side parts add coordinate distance to that side, corner parts add point distance to that corner. With that approach plan has to be divided into 9^n parts, and distance sum is calculated by adding appropriate rectangle distance functions. That is feasible if number of rectangles is not too large.
Probably it is not needed to calculate all parts since it is easy to calculate some bound on part min value and check is it needed to calculate part at all.
I am not sure, but it seems to me that global distance map is convex function. If that is the case than it can be solved iteratively by similar idea as in linear programming.
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.
I am tryng to detect traffic signs by their colour and shape, i have the binary image from de colour segmentation and i try to detect triangles in it, by unless all the sides of the triangle are complete y doesnt work,
in this image for example it does not detect any triangle
the code i am using is this:
vector<Point> approx;
findContours(copia,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
vector<Rect_ <int> > boundRect( contours.size() );
vector<Rect_ <int> > boundRect_( contours.size() );
for(size_t i=0; i<contours.size();i++)
{
approxPolyDP(Mat(contours[i]), approx,arcLength(Mat(contours[i]), true)*0.02, true);
if (approx.size() == 3 &&fabs(contourArea(Mat(approx))) > 300 && isContourConvex(Mat(approx)))
drawContours(capture->image,contours,i,Scalar(0,255,0));
It is not a problem of the cotourArea, i have no problem detecting complete triangles. I do not know if i could do something to detect that kind of "not complete triangles" or i would have to do something to complete the triangle so that i could detect them. In either case i am a bit lost
Thank you for your help
EDIT: i forgot to upload the image
Actually, opencv side of a triangle maybe difficult in terms of vision but I would suggest some method that may help you achieve.
1) Use Corner detector
(OpenCV Canny) to detector all corner in the binary image. I would say use Morphological Operations (Dilate and Errode) as a means to reduce noise instead of blurring or non-max suppression. Next Use the extreme points, and connect it to form Triangles. Because there will be perhaps many corners you can try fitting all the points and select the maximum Fit. You may also use delaunay triangulation to find the triangle to the points.
2) Using Curvature Info.
Since one edge of the triangle is missing, you can use the 2 edges to compute the curvature of the circumscribing contour. Again here Morphological Operations (Dilate and Errode) can be useful. Than you can select points where curvature (Computing the Curvature of Binary Image Contour) change drastically as extreme point as vertex and fit lines to get approximation to the traiangle. If you image is less noisely you can use Convex Hull to get the approximation.
3) RANSAC Fitting
You may also use Fitting method to approximate the triangle by using variants of triangles and fit it to the 2 estimated edges on the binary image.
Topic is old - but might help others.
I had same issue but I dealt with it using dilate() function on input image (it might require 2-3 iterations if triangle has big gap). It is not the best solution but at the moment seems to be the easiest one.
I have some 3D Points that roughly, but clearly form a segment of a circle. I now have to determine the circle that fits best all the points. I think there has to be some sort of least squares best fit but I cant figure out how to start.
The points are sorted the way they would be situated on the circle. I also have an estimated curvature at each point.
I need the radius and the plane of the circle.
I have to work in c/c++ or use an extern script.
You could use a Principal Component Analysis (PCA) to map your coordinates from three dimensions down to two dimensions.
Compute the PCA and project your data onto the first to principal components. You can then use any 2D algorithm to find the centre of the circle and its radius. Once these have been found/fitted, you can project the centre back into 3D coordinates.
Since your data is noisy, there will still be some data in the third dimension you squeezed out, but bear in mind that the PCA chooses this dimension such as to minimize the amount of data lost, i.e. by maximizing the amount of data that is represented in the first two components, so you should be safe.
A good algorithm for such data fitting is RANSAC (Random sample consensus). You can find a good description in the link so this is just a short outline of the important parts:
In your special case the model would be the 3D circle. To build this up pick three random non-colinear points from your set, compute the hyperplane they are embedded in (cross product), project the random points to the plane and then apply the usual 2D circle fitting. With this you get the circle center, radius and the hyperplane equation. Now it's easy to check the support by each of the remaining points. The support may be expressed as the distance from the circle that consists of two parts: The orthogonal distance from the plane and the distance from the circle boundary inside the plane.
Edit:
The reason because i would prefer RANSAC over ordinary Least-Squares(LS) is its superior stability in the case of heavy outliers. The following image is showing an example comparision of LS vs. RANSAC. While the ideal model line is created by RANSAC the dashed line is created by LS.
The arguably easiest algorithm is called Least-Square Curve Fitting.
You may want to check the math,
or look at similar questions, such as polynomial least squares for image curve fitting
However I'd rather use a library for doing it.
I have got the following image:
There are curves on the picture.
i would like to find center of the circles containing curves.
i tried opencv and hough circle transform but had no results.
The natural candidate would be cvHoughCircles. Each part of each curve adds a "vote" for an X/Y/R triplet which identifies the centrepoint. Now, you only have part of the circles, so the number of votes is limited and the accuracy reduced, but you probably suspected as much.
Here's what I would try first:
Observe that if you draw rays from the true center of the circles, the local maxima of the image intensity along them occur at intervals that are independent of the ray orientation. These intervals are the differences between the lengths of the radii of consecutive circles.
So fix a number or ray directions, say 16 equally spaced in [0, pi], and define a cost function parametrized on the (xc, yc) coordinates of the center, and the ri radii of the circles, with cost equal to, for example, the variance of the maxima locations along the radii
among different radii.
Threshold the image
erode it until there is little or no noise (small blobs)
dilate it back
find the big blob. If there are still some small blobs, select the max area.
use cv::moments to find its centroid