0

I am able to detect all the squares/rectangles (any contour consists of 4 points) in a given WEBCAM frame. But i am facing a problem that it detects a single square/rectangle as 3-4 squares/rectangles which covers more or less the same portion of the image (Not exactly the same).

Problem: I want to remove those CvSeq which give me the similar "square" which has already been processed/drawn.

overlapping square

Example: Lets say one rectangle is {(3,3), (3, 50), (20,4), (25,56)} and another rectangle as {(2,2), (4, 52), (21,6), (23,58)} and so on....so if you see then these two rectangle are covering the similar portion of image..so i just want to keep any one of them

The part of my code where i am trying to draw the squares after receiving the information about all the squares contained in CvSeq is following:

// the function draws all the squares in the image
void drawSquares( IplImage* img, CvSeq* squares ) // CvSeq* squares--> "square" contains all the points for all the squares.
{

    CvSeqReader reader;
    IplImage* cpy = cvCloneImage( img );
    int i;    


    // initialize reader of the sequence
    cvStartReadSeq( squares, &reader, 0 );

    // read 4 sequence elements at a time (all vertices of a square)
    for( i = 0; i < squares->total; i += 4 ) // increaing i by 4 because one square consists of 4 points
    {
        CvPoint pt[4], *rect = pt;
        int count = 4;

        // read 4 vertices
        CV_READ_SEQ_ELEM( pt[0], reader );
        CV_READ_SEQ_ELEM( pt[1], reader );
        CV_READ_SEQ_ELEM( pt[2], reader );
        CV_READ_SEQ_ELEM( pt[3], reader );

        // draw the square as a closed polyline
        cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );

    }

    // show the resultant image
    cvShowImage( wndname, cpy );
    cvReleaseImage( &cpy );
}
skm
  • 5,015
  • 8
  • 43
  • 104
  • How are you doing your square detection - it sounds like there are features in the image that are causing the smaller rectangles to be picked up; if so, you can try and remove these first - eg. applying a threshold. Anyway, to solve the immediate problem you can order your rectangles by volume (largest first) and then test whether any of the smaller rectangle points are contained in any of the larger rectangles and if so discard it. – timegalore Jan 27 '14 at 21:37
  • Smaller rectangle are not my problem.....My problem is i am detecting the same rectangle more than one time in the same frame...lets say one rectangle is {(3,3), (3, 50), (20,4), (25,56)} and another rectangle as {(2,2), (4, 52), (21,6), (23,58)} and so on....so if you see then these two rectangle are covering the similar portion of image..so i just want to keep any one of them – skm Jan 27 '14 at 21:52
  • My idea might still work - point (3,3) is contained in the other rectangle so you could discard that one. Alternatively, and maybe not very elegant, but you could test each point to see if it is "near" the 4 points of the previous square, ie. x and y is +/- a threshold of say 4. I've done similar trying to find corners from Hough line detection. – timegalore Jan 27 '14 at 22:04
  • ok, lets say my code has detected a total of 9 squares in a given webcam frame....the corners of all of these 9 squares are stored in CVSeq...out of these 9 , 4 are overlapping...but how do i keep a record about previous and next square...i mean some efficient algo...i can do it in several steps but i don't have the flexibility to take a lot of computational time – skm Jan 28 '14 at 09:21
  • How do you get your points - do you do contour detection first? I think you could use pointPolygonTest to check whether any subsequent point is in the previously displayed square. You would need to keep track of the previously displayed squares though and test with each. – timegalore Jan 28 '14 at 11:52
  • yes..i am getting the information about squares by detecting contours and applying some checks on those contours to declare those contour points as squares/rectangles e.g. the number of points should be =4, angle between subsequent lines should be >30 and <110 etc. – skm Jan 28 '14 at 20:35
  • Do you use the CV_RETR_EXTERNAL in the FindContours call - that retrieves only the outer contour but I suspect you do. Maybe post up an example frame from the web cam and I can try it out - I'm working on similar type of rect detection too. – timegalore Jan 28 '14 at 22:25
  • No, i am not using CV_RETR_EXTERNAL. As i said, i am just detecting contours, approximating contours and it the number of points in a contour sequence is 4, then i take it as a square/rectangle. My code is based upon the sample code of opencv squares.c – skm Jan 29 '14 at 16:37
  • Just looking at squares.c, there seems to be a couple of nested loops - one to go through each channels and one to try different threshold values - if that's still in your code then I suspect that will give you duplicate looking squares. – timegalore Jan 29 '14 at 20:54
  • @timegalore: I am using there "findSquares4()" and "angle()" with couple of extra checks related to my application e.g. i am eliminating all the squares which are quite big or having large difference between the lenghts of subsequent edges etc. – skm Jan 30 '14 at 16:02
  • @timegalore: So can you tell which parts should be removed to get rid of duplicate looking squares? – skm Jan 30 '14 at 16:03

2 Answers2

0

Have a look at this bit of the code from squares.c

for( c = 0; c < 3; c++ )
{
    // extract the c-th color plane
    cvSetImageCOI( timg, c+1 );
    cvCopy( timg, tgray, 0 );

    // try several threshold levels
    for( l = 0; l < N; l++ )
    {

I would recommend simplifying this for the time being so that you remove these two loops. Convert your original image to greyscale using CvColor and then apply a single CvCanny and single CvThreshold operation to begin with. You can experiment with the parameters and then do more sophisticated things when you get the basic detection working.

timegalore
  • 731
  • 7
  • 9
0

Find overlapping rectangles and apply cv::groupRectangles()

More here.

LovaBill
  • 5,107
  • 1
  • 24
  • 32
  • cv::groupRectangles() works in C++ but i have information about rectangles in terms of CvPoint pt[4]; ...so here pt[4] is an array which contains four points of a rectangle – skm Feb 07 '14 at 15:26
  • Create the appropriate C++ input. – LovaBill Feb 07 '14 at 15:32
  • I am planning to create a "rect" from each "CvPoint pt[4]"..but i am unable to find the way, how can i do so. – skm Feb 07 '14 at 15:35
  • may be you can have a look here ..i have a similar problem – skm Feb 07 '14 at 16:14
  • I have defined two "Rect" myself i.e. `Rect rect1(10,10,20,20)` and `Rect rect2(20,20,50,50)`..and then i tried to merge them using `groupRectangles(rectList, 4, 0.1);` but then whem i am trying to print the size of "rectList" after merging its zero...why – skm Feb 07 '14 at 16:27
  • Also groupRectangles() does not work with the RotatedRectangles shown in the picture! – br1 Sep 11 '15 at 10:56