2

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.

Community
  • 1
  • 1
layer19
  • 33
  • 4
  • 1
    maybe try [convexHull](http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#convexhull) after what's described in the question you linked to – slawekwin Feb 09 '17 at 10:59
  • @slawekwin we do not know in advance what type of contour we have. It may contain convexity defects or may not and the same about concave defects – layer19 Feb 09 '17 at 11:12

2 Answers2

0

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.

Tamás Zahola
  • 9,271
  • 4
  • 34
  • 46
  • That's interesting. Can you please explain a little more. Do I understand correctly that we need to store the contours (returned by 'cv::findContours') to a *cv::Mat* and then perform 'cv::HoughLinesP' on it? – layer19 Feb 09 '17 at 11:05
  • The input of the hough transform is a grayscale image, where pixel intensities signify the "strength" of the edges. In your case, the contour is already binarized, so it will be a binary (black/white) image. The HoughLines or HoughLinesP will then give you a list of found lines in decreasing order of "strength". In your case this means that the longer colinear segments would be in the beginning of the list, therefore the first 4 lines would be your rectangle as long as defect edges are not longer than the rectangle edges. – Tamás Zahola Feb 09 '17 at 11:25
  • As the contour you have from `findContours` is a vector of points, you would need to draw the contour as a grayscale image before passing it to the Hough transform. You can use `drawContours` for this. – Tamás Zahola Feb 09 '17 at 11:30
  • @TamásZahola You can mention your comments in the answer :D – Jeru Luke Feb 09 '17 at 11:37
  • @TamásZahola I've tried it but it doesn't work. What am I doing wrong? **results:** https://postimg.org/image/emei07jjx/ https://postimg.org/image/4qdf0kdrx/ https://postimg.org/image/jauhve8ql/ https://postimg.org/image/tm6uo20fx/ https://postimg.org/image/hllenbt19/ https://postimg.org/image/x8co0p6t9/ – layer19 Feb 09 '17 at 12:24
  • @TamásZahola the results I get from HoughLinesP are always different and I have no idea how to set threshold parameter. – layer19 Feb 09 '17 at 12:32
  • `HoughLinesP` is the probabilistic Hough transform, that's why you're getting different results each time. You should try `HoughLines` instead, see example here: http://docs.opencv.org/2.4.10/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html – Tamás Zahola Feb 09 '17 at 12:46
  • @TamásZahola thank you for your time and explanations, I've corrected my code. The results are better now, but still not fitting the problem. Top 4 lines not always produces a desired rect. [code](https://ideone.com/l4e2xM) [results](https://postimg.org/gallery/lrc3jw6w/) – layer19 Feb 09 '17 at 13:17
  • Yeah, the problems seems to be that the rectangle's height is comparable to the size of the defects, therefore the Hough transform can confuse the defects' edges for the vertical edges. – Tamás Zahola Feb 09 '17 at 13:22
0

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.
Peter Wishart
  • 11,600
  • 1
  • 26
  • 45