Bhavin Chowksi
Bhavin Chowksi

Reputation: 103

Bounding a foreground object

I want to bound the foreground object by a rectangle, how shall I go about doing it?

I tried bounding the rectangle by collecting the white pixels , but it bounds the whole screen...

How shall I solve this problem?

enter image description here

//defined later
vector<Point> points;
RNG rng(12345);

int main(int argc, char* argv[])
{
    //create GUI windows
    namedWindow("Frame");
    namedWindow("FG Mask MOG 2");
    pMOG2 = createBackgroundSubtractorMOG2();

    VideoCapture capture(0);
        //update the background model
        pMOG2->apply(frame, fgMaskMOG2);
        frame_check = fgMaskMOG2.clone();
        erode(frame_check, frame_check, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
        dilate(frame_check, frame_check, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));

        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;

        /// Detect edges using Threshold
        //threshold(frame_check, frame_check, 100, 255, THRESH_BINARY);
        //find contours
        findContours(frame_check, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

        //points
        for (size_t i = 0; i < contours.size(); i++) {
            for (size_t j = 0; j < contours[i].size(); j++) {
                if (contours[i].size() > 2000)
                {
                    cv::Point p = contours[i][j];
                    points.push_back(p);
                }
            }
        }



            if (points.size() > 0){
                Rect brect = cv::boundingRect(cv::Mat(points).reshape(2));
                rectangle(frame, brect.tl(), brect.br(), CV_RGB(0, 255, 0), 2, CV_AA);
                cout << points.size() << endl;

            }
            imshow("Frame", frame);
            imshow("FG Mask MOG 2", fgMaskMOG2);
            //get the input from the keyboard
            keyboard = waitKey(1000);
        }
    }

Upvotes: 2

Views: 1339

Answers (2)

Miki
Miki

Reputation: 41765

This is a small example on how to draw a bounding box around the foreground objects using the points of the contour. It's with OpenCV 2.9, so you probably need to change the initialization of the BackgroundSubtractorMOG2 if you're using OpenCV 3.0.

#include <opencv2\opencv.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
   BackgroundSubtractorMOG2 bg = BackgroundSubtractorMOG2(30, 16.0, false);
   VideoCapture cap(0);
   Mat3b frame;
   Mat1b fmask;

   for (;;)
   {
       cap >> frame;
       bg(frame, fmask, -1);

       vector<vector<Point>> contours;
       findContours(fmask.clone(), contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

       for(int i=0; i<contours.size(); ++i)
       {
           if(contours[i].size() > 200)
           {
               Rect roi = boundingRect(contours[i]);
               drawContours(frame, contours, i, Scalar(0,0,255));
               rectangle(frame, roi, Scalar(0,255,0));  
           }
       }

       imshow("frame", frame);
       imshow("mask", fmask);
       if (cv::waitKey(30) >= 0) break;
   }
   return 0;
}

Upvotes: 1

Shepard
Shepard

Reputation: 811

Try this, it's from a project I am working on. To isolate objects I use color masks, which produce binary images, but in your case with a proper threshold on the foreground image (after filtering) you can achieve the same result.

// Morphological opening
erode(binary, binary, getStructuringElement(MORPH_ELLIPSE, filterSize));
dilate(binary, binary, getStructuringElement(MORPH_ELLIPSE, filterSize));

// Morphological closing
dilate(binary, binary, getStructuringElement(MORPH_ELLIPSE, filterSize));
erode(binary, binary, getStructuringElement(MORPH_ELLIPSE, filterSize));

// Find contours
vector<vector<Point>> contours;
findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

vector<Rect> rectangles;
for(auto& contour : contours)
{
    // Produce a closed polygon with object's contours
    vector<Point> polygon;
    approxPolyDP(contour, polygon, 3, true);

    // Get polygon's bounding rectangles
    Rect rect = boundingRect(polygon);
    rectangles.push_back(rect);
}

Upvotes: 1

Related Questions