2

I am building an OpenCV application which captures a video from camera and overlays it on another video after removing the background.

I am not able to achieve a reasonable speed as it is playing the output at about 1 fps, whereas my background removal is working at 3fps.

Is there a way to display the background video at its normal speed and overlay the processed video at 3fps ?

I tried commenting out my code and I realized that the problem lies majorly with the Rendering part itself. I tried displaying the video along with my web cam feed and I noticed that there is a drop in the actual fps and the fps of video when displayed with openCV.

here is the sample code:

 void main()
{
    CvCapture* capture, *Vcap;
    capture = cvCaptureFromCAM(0);
    if(!capture)
    {
        printf("Video Load Error");
    }

    Vcap = cvCaptureFromAVI("bgDemo.mp4");
    //printf("\nEntered BGR");
    if(!Vcap)
    {
        printf("Video Load Error");
    }

    while(1)
    {

        IplImage* src = cvQueryFrame(Vcap);
        if(!src)
        {
            Vcap = cvCaptureFromAVI("bgDemo.mp4");
            continue;
        }
        IplImage* bck1 = cvCreateImage(cvGetSize(src),8,3);
        cvResize(src,bck1,CV_INTER_LINEAR);

        cvShowImage("BCK",bck1);
        cvWaitKey(1);
    }
}
user1606191
  • 551
  • 2
  • 6
  • 14
  • Post source. Without it, it's impossible to answer questions about the source's efficiency. – mpenkov Nov 05 '12 at 11:10
  • 1
    @user1606191 Review the answers and up vote the ones that helped you. It's also important to select the official answer to your question (if there is one): you can do so by clicking on the checkbox near it. By doing this you will be helping future visitors like yourself. – karlphillip Feb 13 '13 at 15:37
  • @karlphillip Thanks I am a new bee and hence doesn't know much about using stackoverflow, Thanks and I also upvoted your answer. Thnx for ur help :) – user1606191 Feb 14 '13 at 06:35

1 Answers1

7

The main problem is that you are allocating a new image at every iteration of the loop without releasing it at the end of the loop. In other words, you have a beautiful memory leak.

A better approach is to simply grab a frame of the video before the loop starts. This will let you create bck1 with the right size just once.

There are other problems with your code, I'm sharing a fixed version below, make sure you pay attention to every line of code to see what changed. I haven't had time to test it, but I'm sure you'll figure it out:

int main()
{
    // I know what you are doing, just one capture interface is enough
    CvCapture* capture = NULL; 

    capture = cvCaptureFromCAM(0);
    if(!capture)
    {
        printf("Ooops! Camera Error");            
    }

    capture = cvCaptureFromAVI("bgDemo.mp4");
    if(!capture)
    {
        printf("Ooops! Video Error");
        // if it failed here, it means both methods for loading a video stream failed.
        // It makes no sense to let the application continue, so we return.
        return -1; 
    }

    // Retrieve a single frame from the camera
    IplImage* src = cvQueryFrame(capture);
    if(!src)
    {
        printf("Ooops! #1 cvQueryFrame Error");
        return -1; 
    }

    // Now we can create our backup image with the right dimensions.
    IplImage* bck1 = cvCreateImage(cvGetSize(src),src->depth, src->nChannels);
    if(!bck1)
    {
        printf("Ooops! cvCreateImage Error");
        return -1; 
    }

    while(1)
    {
        src = cvQueryFrame(capture);
        if(!src)
        {
             printf("Ooops! #2 cvQueryFrame Error");  
             break; 
        }

        cvResize(src, bck1, CV_INTER_LINEAR);

        cvShowImage("BCK",bck1);
        cvWaitKey(10);
    }

    cvReleaseImage( &bck1 ); // free manually allocated resource

    return 0;
}

These fixes should speed up your application considerably.

karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • You can also get the frame dimensions without grabbing any frames by querying the capture with cvGetCapturePrperty. This allows you to avoid that first frame grab outside of the loop. – mpenkov Nov 07 '12 at 07:49
  • True! But since I had some problems doing this in the past I am a little bit suspicious. Maybe this is more robust in opencv nowadays. Thanks! – karlphillip Nov 07 '12 at 11:55
  • I also want the my camera feed to be displayed along with the video. I can't display both the camera feed and video through the same capture Interface. and this is why my application is slow, do you suggest me how can I solve this problem. – user1606191 Nov 09 '12 at 04:45
  • Go back and place 2 capture interfaces. Then, you need to make the frame grabbing procedure independent of each other to improve performance. This means that after you successfully open those 2 capture interfaces you will start 2 threads, and each thread will create it's own OpenCV window and grab frames from the correspondent interface. By doing this you will isolate the processing of each interface, which has the potential to improve the performance of your application. – karlphillip Nov 09 '12 at 16:09
  • 1
    Consider up voting my answer if it helped you, or click the checkbox near it to select it as the official answer to your problem. – karlphillip Nov 09 '12 at 16:10
  • Thanx karl, I'll definitely try using threads and see if this helps me. Thanx :) – user1606191 Nov 19 '12 at 08:43
  • I am facing this error while running the program `"Ooops! #2 cvQueryFrame Error"` – Rocket May 04 '13 at 10:25