Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

speeding things up

Hi all! I've developed an algorithm, but it seems to be too slow to keep up with 60 FPS. It is a background subtraction with computation of average color of around 100 moving objects.

What's already been done to increase speed: 1. no unnecesary imshow(); 2. cv::waitKey(1) every 5th or 10th time; 3. back subtractor is CNT, which known to be faster than MOG and MOG2. 4. no std::cout; 5. compiling with -O3 flag.

Still, with the 1280*720 video @ 60 FPS i got around 40, and maximum of 45. Hardware is Core i3 3.3 GHz loaded about 20%.

Please note that now i use video source, but alter i'll switch to camera, which able of 60fps capturing.

Here is simplified code, just so you get the idea:

int main(int argc, char *argv[])
{
cv::VideoCapture capture("test_video.avi");


cv::Ptr<cv::BackgroundSubtractor> BackgroundSub;
BackgroundSub = cv::bgsegm::createBackgroundSubtractorCNT(500, true,500*50, 0);

int morph_size = 3;
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size( morph_size + 1, morph_size+1 ), cv::Point( morph_size, morph_size ) );

while (1)
{
    capture >> img_in;
    img_output =  img_in.clone();
    img_wholemask = Mat::zeros(img_in.size(), CV_8UC3);

    cvtColor(img_in, img_gray, COLOR_BGR2GRAY);
    blur(img_gray, img_gray, Size(3,3) );
    BackgroundSub->apply(img_gray, img_mog_output, 0.05);
    Canny(img_mog_output, img_canny_output, 200.0, 200.0*2);
    cv::morphologyEx(img_canny_output, img_morph_out, cv::MORPH_CLOSE, element);
    cv::findContours(img_morph_out, contours, hierarchy,cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    for( int i = 0; i < contours.size(); i++ )
    {
        cv::drawContours(img_wholemask, contours, i, cv::Scalar(255,255,255), cv::FILLED);
        vector<Point2f> mc(contours.size());
        vector<Moments> mu(contours.size());
        vector<Point2f> centers( contours.size() );
        mu[i] = moments(contours[i], false);    //contour moments 
        mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );   //contour centers
        Rect roi = boundingRect(contours[i]);   //take single contour
        img_in(roi).copyTo(img_roi, img_wholemask(roi));    //copy to mat with mask
        Scalar avg_color = Scalar(mean(img_roi)) / PartOfColor; //average color in contour
        cv::drawContours(cv::FILLED ...); //fill contour
        cv::drawContours(...);  //draw contour
        rectangle(...); //contour bounding box
        drawMarker(...); //contour center
    }

    sprintf(str,"%2.1f FPS", info_fps);
    putText(img_output, str, Point(10,30), FONT_HERSHEY_SIMPLEX   , 1.0, Scalar(0,0,255), 1);
    sprintf(str,"%u contours", contours.size());
    putText(img_output, str, Point(10,50), FONT_HERSHEY_SIMPLEX   , 0.6, Scalar(0,0,255), 1);

    if (!img_output.empty()) imshow("img_output", img_output);

}

    counter++;
    if (counter==5){
        int key = cv::waitKey(1);
        counter = 0;
    }
}

So is there a way to spped things up a bit? Algo optimistions or something else? I've been thinking about multithreaded capture and processing, which is not much recommended here at forum, AFAIK. Is it applicable in this situation? What to read on muultithreaded C++ opencv applictions? PS: CUDA is not an option since i can't get it to compile, and it's poorly compatible with minGW and CodeBlocks.

Thanks in advance!