Background subtraction and object counting - slow performance

asked 2015-09-10 14:57:53 -0600

David_86 gravatar image

updated 2015-09-11 03:30:04 -0600


I'm trying to write down a code to count objects that will be moving from left to right in the FoV, so I think 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 of 8 pixels 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)

            char text[30];
            sprintf_s(text, "Bars: %d", Count);
            IplImage iplimg = dst;
            CvFont font;
            double hScale = 1.5;
            double vScale ...
edit retag flag offensive close merge delete



Try to time the different parts of your code to know which one slow down your program.

I think that your function pointSetBoundingRect could be replace by cv::boundingRect.

You can also directly use cv::Mat, C++ functions for the different drawings and display.

Eduardo gravatar imageEduardo ( 2015-09-11 06:51:05 -0600 )edit

@Eduardo: tested both boundingRect and this code, this one seems to work a little faster. What is slowing down the code is the background subtractor: i've tryed a different strategy to highlight moving objects working on consecutive frames subtraction, but this is not giving good result since i'm losing the overlapping area of the objects plus in the difference image coming from absdiff function every object is cloned.

I'm back to MOG2 background subtractor, but this is getting harder than expected..

David_86 gravatar imageDavid_86 ( 2015-09-17 05:40:54 -0600 )edit