Detect card MinArea Quadrilateral from contour OpenCV

Viewed 7227

Yet another about detecting card in a picture. I've managed to pretty much isolate the card in the picture, I have a convex hull that is close and from here I'm stuck.

For the context/constraint, objective:

  • Detect a card in a picture
  • Plain-ish background (see example)
  • Type of card fixed ahead (meaning: we have the width/height ratio)
  • One object per picture (for now at least)

Approach I used:

  1. Downscale
  2. Gray-scale
  3. Light Blur
  4. Canny
  5. Find contours
  6. Remove all contours in list with less than 120 points (try/error value)
  7. Case 1: I have 1 contour: perfect contour of my card: step 9
  8. Case 2: I have multiple contour
    • Convex hull
    • Approximate polygon ?
  9. ???

Step 1, 3 and 6 are mainly to remove noise and small artifacts.

So I'm pretty much stuck at step 9. I've tried on a sample picture:

Sample

On the debug picture:

  • Green: contours
  • Red: convex hull
  • Purple/Pink-ish: used approxPolyDp
  • Yellow: minAreaRect

(the result image is extracted from the minAreaRect)

So the contour is acceptable, I can probably do a little better by tweaking the parameters from canny or the first blur. But for now this is acceptable, the issue now is, how can I get the the 4 points that will form the "minarea quadrilateral". As you can see, minAreaRect gives a rectangle which is not perfect, and the approxPolyDp is losing too much of the card.

Any clue how I can approach this? I tried playing with the epsilon value when using approxPolyDp (I used arcLength*0.1), but nothing.

Another issue with this approach is that is a corner is lost during canny (see example) it'll not work (unless when using minAreaRect). But this can probably be resolved before (with a better pre-processing) or after (since we know the width/height ratio).

enter image description here

Not asking for code here, just ideas how to approach this,

thanks!

Edit: Yves Daoust's solutions:

  • Get the 8 points from the convex hull that match the predicate: (maximize x, x+y, y, -x+y, -x, -x-y, -y, x-y)
  • From this octagon, take 4 longest sides, get the intersection points

Result:

result

Edit 2: Using Hough transform (instead of 8 extreme points) gives me better result for all cases where the 4 sides are found. If more than 4 lines are found, probably we have duplicates, so use some maths to try to filter and keep 4 lines. I coded a draft working by using the determinant (close to 0 if parallel) and the point-line distance formula)

2 Answers
Related