title: opencv deskewing a contour
body: <p>InputImage</p>
  
  <p><a href="https://i.stack.imgur.com/MSHd6.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MSHd6.jpg" alt="enter image description here"></a></p>
  
  <p>ResultImage</p>
  
  <p><a href="https://i.stack.imgur.com/av4IG.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/av4IG.jpg" alt="enter image description here"></a></p>
  
  <p>I have been able to filter the largest contour in the image to detect the token. </p>
  
  <p>I have applied warp perception but it is only cropping the image at the edges of the contour, nothing else.</p>
  
  <p>I want the detected token to be cropped out of the rest of the image entireley, de-skew it while keeping proportions so the result image should be upright, straight. Then I will move forward with finding the blobs in the token to detect the dates marked inside it.</p>
  
  <pre><code>    private Mat processMat(Mat srcMat) {
      Mat processedMat = new Mat();
      Imgproc.cvtColor(srcMat, processedMat, Imgproc.COLOR_BGR2GRAY);
      Imgproc.GaussianBlur(processedMat, processedMat, new Size(5, 5), 5);
      Imgproc.threshold(processedMat, processedMat, 127, 255, Imgproc.THRESH_BINARY);
      List&lt;MatOfPoint&gt; contours = new ArrayList&lt;&gt;();
      Mat hierarchy = new Mat();
      Imgproc.findContours(processedMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
  
      double maxVal = 0;
      int maxValIdx = 0;
      for (int contourIdx = 0; contourIdx &lt; contours.size(); contourIdx++) {
          double contourArea = Imgproc.contourArea(contours.get(contourIdx));
          if (maxVal &lt; contourArea) {
              maxVal = contourArea;
              maxValIdx = contourIdx;
          }
      }
      if (!contours.isEmpty()) {
          Imgproc.drawContours(srcMat, contours, maxValIdx, new Scalar(0,255,0),  3);
          Rect rect = Imgproc.boundingRect(contours.get(maxValIdx));
          Log.e("rect", "" + rect);
          int top = srcMat.height();
          int left = srcMat.width();
          int right = 0;
          int bottom = 0;
  
          if(rect.x &lt; left) {
              left = rect.x;
          }
          if(rect.x+rect.width &gt; right){
              right = rect.x+rect.width;
          }
          if(rect.y &lt; top){
              top = rect.y;
          }
          if(rect.y+rect.height &gt; bottom){
              bottom = rect.y+rect.height;
          }
  
          Point topLeft = new Point(left, top);
          Point topRight = new Point(right, top);
          Point bottomRight = new Point(right, bottom);
          Point bottomLeft = new Point(left, bottom);
  
          return warp(srcMat, topLeft, topRight, bottomLeft, bottomRight);
      }
      return null;
  }
  
  Mat warp(Mat inputMat, Point topLeft, Point topRight, Point bottomLeft, Point bottomRight) {
      int resultWidth = (int)(topRight.x - topLeft.x);
      int bottomWidth = (int)(bottomRight.x - bottomLeft.x);
      if(bottomWidth &gt; resultWidth)
          resultWidth = bottomWidth;
  
      int resultHeight = (int)(bottomLeft.y - topLeft.y);
      int bottomHeight = (int)(bottomRight.y - topRight.y);
      if (bottomHeight &gt; resultHeight) {
          resultHeight = bottomHeight;
      }
  
      Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC1);
  
      List&lt;Point&gt; source = new ArrayList&lt;&gt;();
      source.add(topLeft);
      source.add(topRight);
      source.add(bottomLeft);
      source.add(bottomRight);
      Mat startM = Converters.vector_Point2f_to_Mat(source);
  
      Point ocvPOut1 = new Point(0, 0);
      Point ocvPOut2 = new Point(resultWidth, 0);
      Point ocvPOut3 = new Point(0, resultHeight);
      Point ocvPOut4 = new Point(resultWidth, resultHeight);
      List&lt;Point&gt; dest = new ArrayList&lt;&gt;();
      dest.add(ocvPOut1);
      dest.add(ocvPOut2);
      dest.add(ocvPOut3);
      dest.add(ocvPOut4);
      Mat endM = Converters.vector_Point2f_to_Mat(dest);
  
      Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM);
  
      Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight));
      return outputMat;
  }
  </code></pre>
  
  <p><strong>UPDATE 1</strong></p>
  
  <p>Replaced This:</p>
  
  <pre><code>        return warp(srcMat, topLeft, topRight, bottomLeft, bottomRight);
  </code></pre>
  
  <p>With This:</p>
  
  <pre><code>        return warp(srcMat, topLeft, topRight, bottomRight, bottomLeft);
  </code></pre>
  
  <p>Result Update 1:</p>
  
  <p><a href="https://i.stack.imgur.com/hXebA.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hXebA.png" alt="Result Now"></a></p>
  
  <p><strong>UPDATE 2</strong></p>
  
  <pre><code>    public Mat warp(Mat inputMat, MatOfPoint selectedContour) {
      MatOfPoint2f new_mat = new MatOfPoint2f(selectedContour.toArray());
      MatOfPoint2f approxCurve_temp = new MatOfPoint2f();
      int contourSize = (int) selectedContour.total();
      Imgproc.approxPolyDP(new_mat, approxCurve_temp, contourSize * 0.05, true);
  
      double[] temp_double;
      temp_double = approxCurve_temp.get(0,0);
      Point p1 = new Point(temp_double[0], temp_double[1]);
      temp_double = approxCurve_temp.get(1,0);
      Point p2 = new Point(temp_double[0], temp_double[1]);
      temp_double = approxCurve_temp.get(2,0);
      Point p3 = new Point(temp_double[0], temp_double[1]);
      temp_double = approxCurve_temp.get(3,0);
      Point p4 = new Point(temp_double[0], temp_double[1]);
      List&lt;Point&gt; source = new ArrayList&lt;Point&gt;();
      source.add(p1);
      source.add(p2);
      source.add(p3);
      source.add(p4);
      Mat startM = Converters.vector_Point2f_to_Mat(source);
  
      int resultWidth = 846;
      int resultHeight = 2048;
  
      Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4);
  
      Point ocvPOut1 = new Point(0, 0);
      Point ocvPOut2 = new Point(0, resultHeight);
      Point ocvPOut3 = new Point(resultWidth, resultHeight);
      Point ocvPOut4 = new Point(resultWidth, 0);
      List&lt;Point&gt; dest = new ArrayList&lt;Point&gt;();
      dest.add(ocvPOut1);
      dest.add(ocvPOut2);
      dest.add(ocvPOut3);
      dest.add(ocvPOut4);
      Mat endM = Converters.vector_Point2f_to_Mat(dest);
  
      Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM);
  
      Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight),
              Imgproc.INTER_CUBIC);
      return outputMat;
  }
  </code></pre>
  
  <p>Result Update 2:</p>
  
  <p>I have changed my warp function a bit and the code is attached.
  However the resultant image is rotated somehow in the wrong direction. Can you guide me which is the correct way to do this.</p>
  
  <p>Android device orientation is set to: portrait and the input image is in portrait as well.</p>
  
  <p><a href="https://i.stack.imgur.com/hkGgD.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hkGgD.png" alt="result_update_2"></a></p>
  
  <p><strong>UPDATE 3</strong></p>
  
  <p>I have managed to straighten the token by sorting the corners like so:</p>
  
  <pre><code>    List&lt;Point&gt; source = new ArrayList&lt;Point&gt;();
      source.add(p2);
      source.add(p3);
      source.add(p4);
      source.add(p1);
      Mat startM = Converters.vector_Point2f_to_Mat(source);
  </code></pre>
  
  <p>Result Update 3:</p>
  
  <p><a href="https://i.stack.imgur.com/GAS83.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/GAS83.png" alt="Result Update 3"></a></p>
  
  <p>However the resultant image is cropped from the left side which I have no idea how to tackle that.
  I have managed to straighten the input image if the token is tilted to the right or left and the output image is straight nonetheless. However if the input image already has the token centred and straight up. it rotates the token like so, using the same code: </p>
  
  <p>Issue Update 3:</p>
  
  <p><a href="https://i.stack.imgur.com/ddL8h.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ddL8h.png" alt="Issue Update 3"></a></p>