Ask Your Question

Revision history [back]

I am not well versed with the implementation of Java's Collections but I doubt contours.remove(i) is doing exactly what you are thinking its doing.

You are removing an element from a container whilst iterating over it. If this even works, then i will have an offset of sorts because the container might be changing lengths after each iteration. I would recommend looping over your container with an iterator then using it to remove elements or creating another list to hold the found squares as shown below

List<MatOfPoint> squareContours = new ArrayList<>();

    //Remove contours that aren't close to a square shape.
    for(int i = 0; i < contours.size(); ++i)
    {

        double area = Imgproc.contourArea( contours.get(i)); 
        MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
        double perimeter = Imgproc.arcLength(contour2f, true);

        //Found squareness equation on wiki... 
        // https://en.wikipedia.org/wiki/Shape_factor_(image_analysis_and_microscopy)
        double squareness = 4 * Math.PI * area / Math.pow(perimeter, 2);

        System.out.println("Squareness: " + squareness);


        if(squareness <= 0.7 && squareness >=  0.8)
        {
            squareContours.add(contours[i]);
        }
    }

Then use squareContours from this point onwards

I am not well versed with the implementation of Java's Collections but I doubt contours.remove(i) is doing exactly what you are thinking its doing.

You are removing an element from a container whilst iterating over it. If this even works, then i will have an offset of sorts because the container might be changing lengths after each iteration. I would recommend looping the following methods:

Method 1: Creating another list to hold the found squares as shown below

List<MatOfPoint> squareContours = new ArrayList<>();

    //Remove contours that aren't close to a square shape.
    for(int i = 0; i < contours.size(); ++i)
    {
        double area = Imgproc.contourArea(contours.get(i)); 
        MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
        double perimeter = Imgproc.arcLength(contour2f, true);

        //Found squareness equation on wiki... 
        // https://en.wikipedia.org/wiki/Shape_factor_(image_analysis_and_microscopy)
        double squareness = 4 * Math.PI * area / Math.pow(perimeter, 2);

        System.out.println("Squareness: " + squareness);

        if(squareness <= 0.7 && squareness >=  0.8)
        {
            squareContours.add(contours[i]); // similar to squareContours.add(contours.get(i))
        }
    }

Then use squareContours from this point onwards

Method 2: Looping over your container with an iterator then using it to remove elements or creating another list to hold the found squares as shown below elements

List<MatOfPoint> squareContours = new ArrayList<>();

    //Remove contours that aren't close to a square shape.
    for(int i = 0; i < contours.size(); ++i)
    ListIterator <MatOfPoint> iter = contours.listIterator();

while(iter.hasNext())
{
     MatOfPoint contour = iter.next(); // this gets the actual element the iterator is pointing @
    // then you can go ahead and perform other tasks.
    double area = Imgproc.contourArea( contours.get(i)); 
        MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
        double perimeter = Imgproc.arcLength(contour2f, true);

        //Found squareness equation on wiki... 
        // https://en.wikipedia.org/wiki/Shape_factor_(image_analysis_and_microscopy)
        double squareness = 4 * Math.PI * area / Math.pow(perimeter, 2);

        System.out.println("Squareness: " + squareness);


    Imgproc.contourArea(contour);
    ..................
    if(squareness <= 0.7 && squareness >=  0.8)
     {
            squareContours.add(contours[i]);
    iter.remove(); // this removes that particular element the iterator is pointing @
    }
 }

Then use squareContours from this point onwards

This and this might be helpful in understanding iterators in Java

I am not well versed with the implementation of Java's Collections but I doubt contours.remove(i) is doing exactly what you are thinking its doing.

You are removing an element from a container whilst iterating over it. If this even works, then i will have an offset of sorts because the container might be changing lengths after each iteration. I would recommend the following methods:

Method 1: Creating another list to hold the found squares as shown below

List<MatOfPoint> squareContours = new ArrayList<>();

    //Remove contours that aren't close to a square shape.
    for(int i = 0; i < contours.size(); ++i)
    {
        double area = Imgproc.contourArea(contours.get(i)); 
        MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
        double perimeter = Imgproc.arcLength(contour2f, true);

        //Found squareness equation on wiki... 
        // https://en.wikipedia.org/wiki/Shape_factor_(image_analysis_and_microscopy)
        double squareness = 4 * Math.PI * area / Math.pow(perimeter, 2);

        System.out.println("Squareness: " + squareness);

        if(squareness <= >= 0.7 && squareness >= <=  0.8)
        {
            squareContours.add(contours[i]); // similar to squareContours.add(contours.get(i))
        }
    }

Then use squareContours from this point onwards

Method 2: Looping over your container with an iterator then using it to remove elements

ListIterator <MatOfPoint> iter = contours.listIterator();

while(iter.hasNext())
{
    MatOfPoint contour = iter.next(); // this gets the actual element the iterator is pointing @
    // then you can go ahead and perform other tasks.
    double area = Imgproc.contourArea(contour);
    ..................
    if(squareness <= >= 0.7 && squareness >= <=  0.8)
    {
        iter.remove(); // this removes that particular element the iterator is pointing @
    }
}

This and this might be helpful in understanding iterators in Java