title: Detect card MinArea Quadrilateral from contour OpenCV
body: <p>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.</p>
  
  <p>For the context/constraint, objective:</p>
  
  <ul>
  <li>Detect a card in a picture</li>
  <li>Plain-ish background (see example)</li>
  <li>Type of card fixed ahead (meaning: we have the width/height ratio)</li>
  <li>One object per picture (for now at least)</li>
  </ul>
  
  <p>Approach I used:</p>
  
  <ol>
  <li>Downscale</li>
  <li>Gray-scale</li>
  <li>Light Blur</li>
  <li>Canny</li>
  <li>Find contours</li>
  <li>Remove all contours in list with less than 120 points (try/error value)</li>
  <li>Case 1: I have 1 contour: perfect contour of my card: step 9</li>
  <li>Case 2: I have multiple contour
  
  <ul>
  <li>Convex hull</li>
  <li>Approximate polygon ?</li>
  </ul></li>
  <li>???</li>
  </ol>
  
  <p>Step 1, 3 and 6 are mainly to remove noise and small artifacts.</p>
  
  <p>So I'm pretty much stuck at step 9.
  I've tried on a sample picture:</p>
  
  <p><a href="https://i.stack.imgur.com/vVekS.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vVekS.jpg" alt="Sample"></a></p>
  
  <p>On the debug picture:</p>
  
  <ul>
  <li>Green: contours</li>
  <li>Red: convex hull</li>
  <li>Purple/Pink-ish: used approxPolyDp</li>
  <li>Yellow: minAreaRect</li>
  </ul>
  
  <p>(the result image is extracted from the minAreaRect)</p>
  
  <p>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.</p>
  
  <p>Any clue how I can approach this?
  I tried playing with the epsilon value when using approxPolyDp (I used <code>arcLength*0.1</code>), but nothing.</p>
  
  <p>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).</p>
  
  <p><a href="https://i.stack.imgur.com/gkVRV.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gkVRV.jpg" alt="enter image description here"></a></p>
  
  <p>Not asking for code here, just ideas how to approach this,</p>
  
  <p>thanks!</p>
  
  <p><strong>Edit</strong>: Yves Daoust's solutions:</p>
  
  <ul>
  <li>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)</li>
  <li>From this octagon, take 4 longest sides, get the intersection points</li>
  </ul>
  
  <p>Result:</p>
  
  <p><a href="https://i.stack.imgur.com/b7g2f.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/b7g2f.jpg" alt="result"></a></p>
  
  <p><strong>Edit 2:</strong> 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)</p>