Ask Your Question
1

How to remove overlapping contours

asked 2017-08-12 18:36:21 -0600

thatc0der gravatar image

updated 2020-09-15 11:24:35 -0600

I am working on a program where I am trying to extract the colored squares from a puzzle. I take a frame from a video capture then find the all contours. I then remove contours that aren't in the shape of a square (This works alright but looking for a better method). The main problem I am facing is that there are overlapping contours. I use RETR_TREE to get all contours but when using RETR_EXTERNAL The contours become harder to detect. Is there a way I can improve the detection of squares? Or a way that I can remove the overlapping contours in the image.

Here is an image of where there are overlapping contours: There were 11 contours found in this image but I want only 9.(I draw the rects to see the overlapping a little easier) Overlapping image

. How can I remove the inner contours? Here is my code:

public Mat captureFrame(Mat capturedFrame){

    Mat newFrame = new Mat();
    capturedFrame.copyTo(newFrame); 

    //Gray
    Mat gray = new Mat();
    Imgproc.cvtColor(capturedFrame, gray, Imgproc.COLOR_RGB2GRAY);

    //Blur
    Mat blur = new Mat();
    Imgproc.blur(gray, blur, new Size(3,3));
    //Canny image
    Mat canny = new Mat();
    Imgproc.Canny(blur, canny, 20, 40, 3, true);

    //Dilate image to increase size of lines
    Mat kernel = Imgproc.getStructuringElement(1, new Size(3,3));
    Mat dilated = new Mat();
    Imgproc.dilate(canny,dilated, kernel);


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

    //find contours
    Imgproc.findContours(dilated, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE);


    //Remove contours that aren't close to a square shape.
    //Wondering if there is a way I can improve this?
    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);

        //add contour to new List if it has a square shape.
        if(squareness >= 0.7 && squareness <= 0.9 && area >= 3000){
           squareContours.add(contours.get(i));
        }
    }

    MatOfPoint2f approxCurve = new MatOfPoint2f();
    for(int n = 0; n < squareContours.size(); n++){

        //Convert contours(n) from MatOfPoint to MatOfPoint2f
        MatOfPoint2f contour2f = new MatOfPoint2f( squareContours.get(n).toArray());
        //Processing on mMOP2f1 which is in type MatOfPoint2f
        double approxDistance = Imgproc.arcLength(contour2f, true)*0.02;
        Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);

        //Convert back to MatOfPoint
        MatOfPoint points = new MatOfPoint( approxCurve.toArray());

        // Get bounding rect of contour
        Rect rect = Imgproc.boundingRect(points);
        //length and width should be about the same
        if(rect.height - rect.width < Math.abs(10)){
            System.out.printf("%s , %s \n", rect.height, rect.width);
        }

         // draw enclosing rectangle (all same color, but you could use variable i to make them unique)
        Imgproc.rectangle(newFrame, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar (255, 0, 0, 255), 3); 

        }  

    return newFrame;
}
edit retag flag offensive close merge delete

Comments

1

You simply need to apply the concept of non maxima suppression on your data. That means that for every contour, find other contours that at least overlap 50%. Replace both by their intersection over union for example. Its standard in any detection algorithm.

StevenPuttemans gravatar imageStevenPuttemans ( 2017-08-14 03:51:51 -0600 )edit

what would that be like? How would I be able to check to see if one contour is being overlapped by the rest of the other contours? @StevenPuttenmans

thatc0der gravatar imagethatc0der ( 2017-08-14 07:33:06 -0600 )edit
StevenPuttemans gravatar imageStevenPuttemans ( 2017-08-14 09:05:36 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2017-08-12 19:04:19 -0600

updated 2017-08-13 21:24:47 -0600

groupRectangles() or SimilarRects will help you

for more information see this and take a look at similar question on stackoverflow.com


in addition,

there is a similar question maybe interesting

end finally here you can find an explanation in detail how to do it.

for simple solution, you can try using erosion before your process

//Gray
Mat gray = new Mat();

//like the line below 
Imgproc.erode(capturedFrame, gray, new Mat(),Point(-1,-1),10);

Imgproc.cvtColor(gray, gray, Imgproc.COLOR_RGB2GRAY);
edit flag offensive delete link more

Comments

thanks but it isn't so much about the rectangles, it is able the overlapping contours. I use the rectangles for debugging, I mean I could use them in the main program but is there a way i can distinctly remove the overlapping contours? It is just that I use the rectangles to show were these overlapping contours are because its much easier to see.

thatc0der gravatar imagethatc0der ( 2017-08-12 20:26:26 -0600 )edit

what it your final aim from this program?

sturkmen gravatar imagesturkmen ( 2017-08-12 20:52:30 -0600 )edit

I want to be able to detect the squares, grab their rgb values take that and represent it in a form my solver understands and it gets me the solution for it.

thatc0der gravatar imagethatc0der ( 2017-08-12 20:59:41 -0600 )edit

as i know there is many programs already do it

sturkmen gravatar imagesturkmen ( 2017-08-12 21:01:28 -0600 )edit

I know that however I am writing my own, just for the experience and fun of it.

thatc0der gravatar imagethatc0der ( 2017-08-12 21:02:39 -0600 )edit

I am pretty close its just this annoying overlapping thing that is giving me problems.

thatc0der gravatar imagethatc0der ( 2017-08-12 21:34:30 -0600 )edit

Lol your last link has me in that blog post I contributed to that :). I think I have an idea of how to use the groupRectangles, I will let you know if figure it out. Thanks for all the help.

thatc0der gravatar imagethatc0der ( 2017-08-12 21:45:45 -0600 )edit

Question, why erode the image if I dilate it already to make the contours easier to find?

thatc0der gravatar imagethatc0der ( 2017-08-12 22:36:36 -0600 )edit

try and see the result :)

sturkmen gravatar imagesturkmen ( 2017-08-12 22:52:24 -0600 )edit

Good news, this helps with detection but the problem is still there, I am currently trying to check if one Rect is in another rectangle and not draw those rects that are inside.

thatc0der gravatar imagethatc0der ( 2017-08-13 13:56:44 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-08-12 18:36:21 -0600

Seen: 8,027 times

Last updated: Aug 13 '17