0

The code is about finding the largest rectangle in an Android device's camera using OpenCV. The app always force close but I can't find the trouble.

The input of the method is a Mat obtained by CvCameraViewFrame.rgba().

private Mat findLargestRectangle(Mat original_image)
{
    Mat imgSource = original_image;

    // convert the image to black and white
    Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY);

    // convert the image to black and white does (8 bit)
    Imgproc.Canny(imgSource, imgSource, 50, 50);

    // apply gaussian blur to smoothen lines of dots
    Imgproc.GaussianBlur(imgSource, imgSource, new Size(5, 5), 5);

    // find the contours
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

    double maxArea = -1;
    int maxAreaIdx = -1;
    MatOfPoint temp_contour = contours.get(0); // the largest is at the
                                                // index 0 for starting
                                                // point
    MatOfPoint2f approxCurve = new MatOfPoint2f();
    Mat largest_contour = contours.get(0);
    List<MatOfPoint> largest_contours = new ArrayList<MatOfPoint>();
    for (int idx = 0; idx < contours.size(); idx++)
    {
        temp_contour = contours.get(idx);
        double contourarea = Imgproc.contourArea(temp_contour);
        // compare this contour to the previous largest contour found
        if (contourarea > maxArea)
        {
            // check if this contour is a square
            MatOfPoint2f new_mat = new MatOfPoint2f(temp_contour.toArray());
            int contourSize = (int) temp_contour.total();
            Imgproc.approxPolyDP(new_mat, approxCurve, contourSize * 0.05, true);
            if (approxCurve.total() == 4)
            {
                maxArea = contourarea;
                maxAreaIdx = idx;
                largest_contours.add(temp_contour);
                largest_contour = temp_contour;
            }
        }
    }
    MatOfPoint temp_largest = largest_contours.get(largest_contours.size() - 1);
    largest_contours = new ArrayList<MatOfPoint>();
    largest_contours.add(temp_largest);

    Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BayerBG2RGB);
    Imgproc.drawContours(imgSource, largest_contours, -1, new Scalar(0, 255, 0), 1);

    // create the new image here using the largest detected square

    Toast.makeText(getApplicationContext(), "Largest Contour: ", Toast.LENGTH_LONG).show();

    return imgSource;
}

Here are the error information in LogCat:

error opening trace file: No such file or directory (2)
Tegra Version detected: 0
FATAL EXCEPTION: Thread-14346
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
at org.opencv.samples.tutorial2.Tutorial2Activity.findLargestRectangle(Tutorial2Activity.java:221)
at org.opencv.samples.tutorial2.Tutorial2Activity.onCameraFrame(Tutorial2Activity.java:169)
at org.opencv.android.CameraBridgeViewBase.deliverAndDrawFrame(CameraBridgeViewBase.java:387)
at org.opencv.android.JavaCameraView$CameraWorker.run(JavaCameraView.java:328)
at java.lang.Thread.run(Thread.java:856)

And the 221st line of the Tutorial2Avctivity is:

MatOfPoint temp_contour = contours.get(0);

Please tell me what the errors are. Thanks a lot!

2 Answers 2

1

This simply means that the size of the ArrayList of contours is empty.

I would suggest adding a conditional block to allow your application cope with the scenario that no contours could be found in the input image.

If you're consistently getting no contours, regardless of the input image, you may want to review the documentation (or Javadoc):

image – Source, an 8-bit single-channel image. Non-zero pixels are treated as 1’s. Zero pixels remain 0’s, so the image is treated as binary . You can use compare() , inRange() , threshold() , adaptiveThreshold() , Canny() , and others to create a binary image out of a grayscale or color one.

Perhaps the threshold values in your Canny() function is not yielding any edges.

If you're still having no luck, perhaps you could test with the input image and values from this blog post.

Sign up to request clarification or add additional context in comments.

Comments

0

Try with this,

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

You have to add some value into counter before below line

MatOfPoint temp_contour = contours.get(0);

2 Comments

findContours() is a void function. (See also this Javadoc.)
Thanks, I forgot this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.