Reputation: 103
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?
//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
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
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