Hi,
I'm trying to write down a code to count objects that will be moving from left to right in the FoV, so I guess I don't need to track them and I'm just going for a check when the center point of an object gets into a ROI (for example the middle of the image).
I've used background subtraction to easily highlights objects to count, then with findcontours and the center of the bounding rect I get the point that will be used to count every object.
The code seems to work "quite well" if i'm working with very low resolution videos: in this first example ( Video 1 ) I'm counting some pens, but I need to define a pixel range where the rect center could be located to get it counted or the pen will be missed. Also the 6th pen is not being counted.
When I run the code the video is playing slower than it's normal speed. Is it my PC working bad or is it the code bad written? When trying to work with higher resolution video (like this one Video 2 the code isn't giving any result at all, cannot identify almost any rect.
Any suggestion? What am I doing wrong?
Thanks for helping
Here's the source code:
#include < stdio.h>
#include < stdlib.h>
#include < opencv2\opencv.hpp>
#include < opencv2/core/core.hpp>
#include < opencv2/highgui/highgui.hpp>
#include < opencv2/video/background_segm.hpp>
using namespace std;
using namespace cv;
// Global variables
Mat img, frame, fgMaskMOG;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Ptr< BackgroundSubtractor> pMOG; //MOG Background subtractor
static Rect pointSetBoundingRect(const Mat& points, Mat m)
{
int npoints = points.checkVector(2);
int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i;
Point ptxmin, ptymin, ptxmax, ptymax;
if (npoints == 0)
return Rect();
const Point* pts = points.ptr<Point>();
Point pt = pts[0];
ptxmin = ptymin = ptxmax = ptymax = pt;
xmin = xmax = pt.x;
ymin = ymax = pt.y;
for (i = 1; i < npoints; i++)
{
pt = pts[i];
if (xmin > pt.x)
{
xmin = pt.x;
ptxmin = pt;
}
if (xmax < pt.x)
{
xmax = pt.x;
ptxmax = pt;
}
if (ymin > pt.y)
{
ymin = pt.y;
ptymin = pt;
}
if (ymax < pt.y)
{
ymax = pt.y;
ptymax = pt;
}
}
return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
}
int main()
{
pMOG = new BackgroundSubtractorMOG();
int Count = 0;
VideoCapture cap("../4.avi");
while (true)
{
cap >> frame;
pMOG->operator()(frame, fgMaskMOG);
findContours(fgMaskMOG, contours, hierarchy, CV_RETR_CCOMP, CHAIN_APPROX_SIMPLE);
Mat dst = Mat::zeros(frame.rows, frame.cols, CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
Rect minRect = pointSetBoundingRect(Mat(contours[i]), dst);
if (minRect.area() > 2000)
{
rectangle(dst, minRect, Scalar(0, 0, 255), 3, 8);
Point center = Point((minRect.x + (minRect.width) / 2), (minRect.y + (minRect.height) / 2));
circle(dst, center, 2, Scalar(255, 0, 0), 2, 8, 0);
if (center.x > 300 & center.x < 308)
{
Count++;
}
}
char text[30];
sprintf_s(text, "Bars: %d", Count);
IplImage iplimg = dst;
CvFont font;
double hScale = 1.5;
double vScale = 1.5;
int lineWidth = 2;
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC, hScale, vScale, 0, lineWidth);
cvPutText(&iplimg, text, cvPoint(30, 50), &font, cvScalar(255, 255, 0));
cvShowImage("Contours", &iplimg);
}
imshow("Origin", frame);
imshow("MOG", fgMaskMOG);
if (waitKey(30) >= 0)
break;
}
}