Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Please visit the following link :

https://www.pastiebin.com/5d0da17bccc9a

I have snippet of code which can help you to find the largest contour area of rectangle.

Please visit the following link :

https://www.pastiebin.com/5d0da17bccc9a

I have snippet of code which can help you to find the largest contour area of rectangle.

protected Bitmap findEdges(Bitmap rotatedBitmap) {

 Mat rgba = new Mat();
 Utils.bitmapToMat(rotatedBitmap, rgba);

 Mat edges = new Mat(rgba.size(), CV_8UC1);
 Imgproc.cvtColor(rgba, edges, Imgproc.COLOR_RGB2GRAY, 4);
 Canny(edges, edges, 80, 100);

 Bitmap resultBitmap = Bitmap.createBitmap(edges.cols(), edges.rows(), Bitmap.Config.ARGB_8888);
 Utils.matToBitmap(edges, resultBitmap);

 // https://github.com/daisygao/ScannerLites
 Mat rgbMat = new Mat();
 Mat grayMat = new Mat();
 Mat cannyMat;
 Mat linesMat = new Mat();
 BitmapFactory.Options o = new BitmapFactory.Options();


 // define the destination image size: A4 - 200 PPI
 int w_a4 = 1654, h_a4 = 2339;

 // TODO: 29/08/2016  May need to check sample size https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
 o.inSampleSize = 4;
 o.inDither = false;


 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
 byte[] b = baos.toByteArray();

 try {
     // resize
     rotatedBitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
 } catch (OutOfMemoryError error) {
     error.printStackTrace();
 }


 int w = rotatedBitmap.getWidth();

 int h = rotatedBitmap.getHeight();
 int min_w = 800;
 double scale = Math.min(10.0, w * 1.0 / min_w);
 int w_proc = (int)(w * 1.0 / scale);
 int h_proc = (int)(h * 1.0 / scale);
 Bitmap srcBitmap = Bitmap.createScaledBitmap(rotatedBitmap, w_proc, h_proc, false);

 Utils.bitmapToMat(srcBitmap, rgbMat); //convert original bitmap to Mat, R G B.

 // grayscale
 Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY); //rgbMat to gray grayMat

 // canny
 cannyMat = getCanny(grayMat);

 // HoughLinesP

 Imgproc.HoughLinesP(cannyMat, linesMat, 1, Math.PI / 280, w_proc / 12, w_proc / 12, 20);

 // Calculate horizontal lines and vertical lines
 Log.e("opencv", "lines.cols " + linesMat.cols() + " w_proc/3: " + w_proc / 3);
 List < Line > horizontals = new ArrayList < > ();
 List < Line > verticals = new ArrayList < > ();
 for (int x = 0; x < linesMat.rows(); x++) {
     double[] vec = linesMat.get(x, 0);
     double x1 = vec[0],
         y1 = vec[1],
         x2 = vec[2],
         y2 = vec[3];
     Point start = new Point(x1, y1);
     Point end = new Point(x2, y2);
     Line line = new Line(start, end);
     if (Math.abs(x1 - x2) > Math.abs(y1 - y2)) {
         horizontals.add(line);
     } else {
         verticals.add(line);
     }

     // for visualization in debug mode
     if (BuildConfig.DEBUG) {}
 }

 Log.e("HoughLines", "completed HoughLines");
 Log.e("HoughLines", "linesMat size: " + linesMat.size());
 Log.e("Lines Detected", Integer.toString(linesMat.rows()));


 // if we don't have at least 2 horizontal lines or vertical lines
 if (horizontals.size() < 2) {
     if (horizontals.size() == 0 || horizontals.get(0)._center.y > h_proc / 2) {
         horizontals.add(new Line(new Point(0, 0), new Point(w_proc - 1, 0)));
     }
     if (horizontals.size() == 0 || horizontals.get(0)._center.y <= h_proc / 2) {
         horizontals.add(new Line(new Point(0, h_proc - 1), new Point(w_proc - 1, h_proc - 1)));
     }
 }
 if (verticals.size() < 2) {
     if (verticals.size() == 0 || verticals.get(0)._center.x > w_proc / 2) {
         verticals.add(new Line(new Point(0, 0), new Point(h_proc - 1, 0)));
     }
     if (verticals.size() == 0 || verticals.get(0)._center.x <= w_proc / 2) {
         verticals.add(new Line(new Point(w_proc - 1, 0), new Point(w_proc - 1, h_proc - 1)));
     }
 }

 Collections.sort(horizontals, new Comparator < Line > () {
     @Override
     public int compare(Line lhs, Line rhs) {
         return (int)(lhs._center.y - rhs._center.y);
     }
 });

 Collections.sort(verticals, new Comparator < Line > () {
     @Override
     public int compare(Line lhs, Line rhs) {
         return (int)(lhs._center.x - rhs._center.x);
     }
 });


 // for visualization in debug mode
 if (BuildConfig.DEBUG) {}

 // compute intersections
 List < Point > intersections = new ArrayList < > ();
 intersections.add(computeIntersection(horizontals.get(0), verticals.get(0)));
 intersections.add(computeIntersection(horizontals.get(0), verticals.get(verticals.size() - 1)));
 intersections.add(computeIntersection(horizontals.get(horizontals.size() - 1), verticals.get(0)));
 intersections.add(computeIntersection(horizontals.get(horizontals.size() - 1), verticals.get(verticals.size() - 1)));

 Log.e("Intersections", Double.toString(intersections.get(0).x));

 for (Point point: intersections) {
     // for visualization in debug mode
     if (BuildConfig.DEBUG) {}
 }

 Log.e("Intersections", Double.toString(intersections.get(0).x));

 // perspective transform

 // Calculate max width and height
 double w1 = Math.sqrt(Math.pow(intersections.get(3).x - intersections.get(2).x, 2) + Math.pow(intersections.get(3).x - intersections.get(2).x, 2));
 double w2 = Math.sqrt(Math.pow(intersections.get(1).x - intersections.get(0).x, 2) + Math.pow(intersections.get(1).x - intersections.get(0).x, 2));
 double h1 = Math.sqrt(Math.pow(intersections.get(1).y - intersections.get(3).y, 2) + Math.pow(intersections.get(1).y - intersections.get(3).y, 2));
 double h2 = Math.sqrt(Math.pow(intersections.get(0).y - intersections.get(2).y, 2) + Math.pow(intersections.get(0).y - intersections.get(2).y, 2));

 double maxWidth = (w1 < w2) ? w1 : w2;
 double maxHeight = (h1 < h2) ? h1 : h2;

 // source Mat from earlier intersection calculations
 Mat srcMat = new Mat(4, 1, CvType.CV_32FC2);
 srcMat.put(0, 0, intersections.get(0).x, intersections.get(0).y, intersections.get(1).x, intersections.get(1).y, intersections.get(2).x, intersections.get(2).y, intersections.get(3).x, intersections.get(3).y);

 Mat dstMat = new Mat(4, 1, CvType.CV_32FC2);
 dstMat.put(0, 0, 0.0, 0.0, maxWidth - 1, 0.0, 0.0, maxHeight - 1, maxWidth - 1, maxHeight - 1);

 Log.e("FinalDisplay", "srcMat: " + srcMat.size());
 Log.e("FinalDisplay", "dstMat: " + dstMat.size());

 // transformation matrix
 Mat transformMatrix = Imgproc.getPerspectiveTransform(srcMat, dstMat);

 Mat finalMat = Mat.zeros((int) maxHeight, (int) maxWidth, CV_8UC1);
 Imgproc.warpPerspective(rgbMat, finalMat, transformMatrix, finalMat.size());
 Log.e("FinalDisplay", "finalMat: " + finalMat.size());

 // display final results
 Bitmap dstBitmap = Bitmap.createBitmap(finalMat.width(), finalMat.height(), Bitmap.Config.RGB_565);
 Log.e("FinalDisplay", "dstBitmap: " + dstBitmap.getWidth() + " x " + dstBitmap.getHeight());
 Utils.matToBitmap(finalMat, dstBitmap); //convert mat to bitmap

 return dstBitmap;

}

public double calculateDistanceBetweenPoints(
        double x1,
        double y1,
        double x2,
        double y2) {
    return Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
}

protected Mat getCanny(Mat gray) {
    Mat canny = new Mat();
    // last paramter 8 is using OTSU algorithm
    double high_threshold = 255; //threshold(gray, threshold,240, 200, 8);
    double low_threshold = high_threshold * 0.5;
    Canny(gray, canny, low_threshold - 20, high_threshold * 2.5);

    // display final results

    Bitmap dstBitmap = Bitmap.createBitmap(canny.width(), canny.height(), Bitmap.Config.RGB_565);
    Utils.matToBitmap(canny, dstBitmap);  //convert mat to bitmap

    return canny;
}


protected Point computeIntersection(Line l1, Line l2) {
    double x1 = l1._p1.x, x2 = l1._p2.x, y1 = l1._p1.y, y2 = l1._p2.y;
    double x3 = l2._p1.x, x4 = l2._p2.x, y3 = l2._p1.y, y4 = l2._p2.y;
    double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
    Point pt = new Point();

    pt.x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
    pt.y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
    return pt;
}

class Line {
    Point _p1;
    Point _p2;
    Point _center;

    Line(Point p1, Point p2) {
        _p1 = p1;
        _p2 = p2;
        _center = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
    }
}

Please visit the following link :

I have snippet of code which can help you to find the largest contour area of rectangle.

protected Bitmap findEdges(Bitmap rotatedBitmap) {

 Mat rgba = new Mat();
 Utils.bitmapToMat(rotatedBitmap, rgba);

 Mat edges = new Mat(rgba.size(), CV_8UC1);
 Imgproc.cvtColor(rgba, edges, Imgproc.COLOR_RGB2GRAY, 4);
 Canny(edges, edges, 80, 100);

 Bitmap resultBitmap = Bitmap.createBitmap(edges.cols(), edges.rows(), Bitmap.Config.ARGB_8888);
 Utils.matToBitmap(edges, resultBitmap);

 // https://github.com/daisygao/ScannerLites
 Mat rgbMat = new Mat();
 Mat grayMat = new Mat();
 Mat cannyMat;
 Mat linesMat = new Mat();
 BitmapFactory.Options o = new BitmapFactory.Options();


 // define the destination image size: A4 - 200 PPI
 int w_a4 = 1654, h_a4 = 2339;

 // TODO: 29/08/2016  May need to check sample size https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
 o.inSampleSize = 4;
 o.inDither = false;


 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
 byte[] b = baos.toByteArray();

 try {
     // resize
     rotatedBitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
 } catch (OutOfMemoryError error) {
     error.printStackTrace();
 }


 int w = rotatedBitmap.getWidth();

 int h = rotatedBitmap.getHeight();
 int min_w = 800;
 double scale = Math.min(10.0, w * 1.0 / min_w);
 int w_proc = (int)(w * 1.0 / scale);
 int h_proc = (int)(h * 1.0 / scale);
 Bitmap srcBitmap = Bitmap.createScaledBitmap(rotatedBitmap, w_proc, h_proc, false);

 Utils.bitmapToMat(srcBitmap, rgbMat); //convert original bitmap to Mat, R G B.

 // grayscale
 Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY); //rgbMat to gray grayMat

 // canny
 cannyMat = getCanny(grayMat);

 // HoughLinesP

 Imgproc.HoughLinesP(cannyMat, linesMat, 1, Math.PI / 280, w_proc / 12, w_proc / 12, 20);

 // Calculate horizontal lines and vertical lines
 Log.e("opencv", "lines.cols " + linesMat.cols() + " w_proc/3: " + w_proc / 3);
 List < Line > horizontals = new ArrayList < > ();
 List < Line > verticals = new ArrayList < > ();
 for (int x = 0; x < linesMat.rows(); x++) {
     double[] vec = linesMat.get(x, 0);
     double x1 = vec[0],
         y1 = vec[1],
         x2 = vec[2],
         y2 = vec[3];
     Point start = new Point(x1, y1);
     Point end = new Point(x2, y2);
     Line line = new Line(start, end);
     if (Math.abs(x1 - x2) > Math.abs(y1 - y2)) {
         horizontals.add(line);
     } else {
         verticals.add(line);
     }

     // for visualization in debug mode
     if (BuildConfig.DEBUG) {}
 }

 Log.e("HoughLines", "completed HoughLines");
 Log.e("HoughLines", "linesMat size: " + linesMat.size());
 Log.e("Lines Detected", Integer.toString(linesMat.rows()));


 // if we don't have at least 2 horizontal lines or vertical lines
 if (horizontals.size() < 2) {
     if (horizontals.size() == 0 || horizontals.get(0)._center.y > h_proc / 2) {
         horizontals.add(new Line(new Point(0, 0), new Point(w_proc - 1, 0)));
     }
     if (horizontals.size() == 0 || horizontals.get(0)._center.y <= h_proc / 2) {
         horizontals.add(new Line(new Point(0, h_proc - 1), new Point(w_proc - 1, h_proc - 1)));
     }
 }
 if (verticals.size() < 2) {
     if (verticals.size() == 0 || verticals.get(0)._center.x > w_proc / 2) {
         verticals.add(new Line(new Point(0, 0), new Point(h_proc - 1, 0)));
     }
     if (verticals.size() == 0 || verticals.get(0)._center.x <= w_proc / 2) {
         verticals.add(new Line(new Point(w_proc - 1, 0), new Point(w_proc - 1, h_proc - 1)));
     }
 }

 Collections.sort(horizontals, new Comparator < Line > () {
     @Override
     public int compare(Line lhs, Line rhs) {
         return (int)(lhs._center.y - rhs._center.y);
     }
 });

 Collections.sort(verticals, new Comparator < Line > () {
     @Override
     public int compare(Line lhs, Line rhs) {
         return (int)(lhs._center.x - rhs._center.x);
     }
 });


 // for visualization in debug mode
 if (BuildConfig.DEBUG) {}

 // compute intersections
 List < Point > intersections = new ArrayList < > ();
 intersections.add(computeIntersection(horizontals.get(0), verticals.get(0)));
 intersections.add(computeIntersection(horizontals.get(0), verticals.get(verticals.size() - 1)));
 intersections.add(computeIntersection(horizontals.get(horizontals.size() - 1), verticals.get(0)));
 intersections.add(computeIntersection(horizontals.get(horizontals.size() - 1), verticals.get(verticals.size() - 1)));

 Log.e("Intersections", Double.toString(intersections.get(0).x));

 for (Point point: intersections) {
     // for visualization in debug mode
     if (BuildConfig.DEBUG) {}
 }

 Log.e("Intersections", Double.toString(intersections.get(0).x));

 // perspective transform

 // Calculate max width and height
 double w1 = Math.sqrt(Math.pow(intersections.get(3).x - intersections.get(2).x, 2) + Math.pow(intersections.get(3).x - intersections.get(2).x, 2));
 double w2 = Math.sqrt(Math.pow(intersections.get(1).x - intersections.get(0).x, 2) + Math.pow(intersections.get(1).x - intersections.get(0).x, 2));
 double h1 = Math.sqrt(Math.pow(intersections.get(1).y - intersections.get(3).y, 2) + Math.pow(intersections.get(1).y - intersections.get(3).y, 2));
 double h2 = Math.sqrt(Math.pow(intersections.get(0).y - intersections.get(2).y, 2) + Math.pow(intersections.get(0).y - intersections.get(2).y, 2));

 double maxWidth = (w1 < w2) ? w1 : w2;
 double maxHeight = (h1 < h2) ? h1 : h2;

 // source Mat from earlier intersection calculations
 Mat srcMat = new Mat(4, 1, CvType.CV_32FC2);
 srcMat.put(0, 0, intersections.get(0).x, intersections.get(0).y, intersections.get(1).x, intersections.get(1).y, intersections.get(2).x, intersections.get(2).y, intersections.get(3).x, intersections.get(3).y);

 Mat dstMat = new Mat(4, 1, CvType.CV_32FC2);
 dstMat.put(0, 0, 0.0, 0.0, maxWidth - 1, 0.0, 0.0, maxHeight - 1, maxWidth - 1, maxHeight - 1);

 Log.e("FinalDisplay", "srcMat: " + srcMat.size());
 Log.e("FinalDisplay", "dstMat: " + dstMat.size());

 // transformation matrix
 Mat transformMatrix = Imgproc.getPerspectiveTransform(srcMat, dstMat);

 Mat finalMat = Mat.zeros((int) maxHeight, (int) maxWidth, CV_8UC1);
 Imgproc.warpPerspective(rgbMat, finalMat, transformMatrix, finalMat.size());
 Log.e("FinalDisplay", "finalMat: " + finalMat.size());

 // display final results
 Bitmap dstBitmap = Bitmap.createBitmap(finalMat.width(), finalMat.height(), Bitmap.Config.RGB_565);
 Log.e("FinalDisplay", "dstBitmap: " + dstBitmap.getWidth() + " x " + dstBitmap.getHeight());
 Utils.matToBitmap(finalMat, dstBitmap); //convert mat to bitmap

 return dstBitmap;

}

public double calculateDistanceBetweenPoints(
        double x1,
        double y1,
        double x2,
        double y2) {
    return Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
}

protected Mat getCanny(Mat gray) {
    Mat canny = new Mat();
    // last paramter 8 is using OTSU algorithm
    double high_threshold = 255; //threshold(gray, threshold,240, 200, 8);
    double low_threshold = high_threshold * 0.5;
1.5;
    Canny(gray, canny, low_threshold - 20, high_threshold * 2.5);

    // display final results

    Bitmap dstBitmap = Bitmap.createBitmap(canny.width(), canny.height(), Bitmap.Config.RGB_565);
    Utils.matToBitmap(canny, dstBitmap);  //convert mat to bitmap

    return canny;
}


protected Point computeIntersection(Line l1, Line l2) {
    double x1 = l1._p1.x, x2 = l1._p2.x, y1 = l1._p1.y, y2 = l1._p2.y;
    double x3 = l2._p1.x, x4 = l2._p2.x, y3 = l2._p1.y, y4 = l2._p2.y;
    double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
    Point pt = new Point();

    pt.x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
    pt.y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
    return pt;
}

class Line {
    Point _p1;
    Point _p2;
    Point _center;

    Line(Point p1, Point p2) {
        _p1 = p1;
        _p2 = p2;
        _center = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
    }
}