1

I am doing a project for video monitoring.
I can't see the conversion from RGB to gray; I get a black window for the gray.
Could you please help me with the problem? (code attached)
Also, how can I get the difference between current frame and previous frame?
Thanks a lot. Ilan

#include "stdafx.h"
#include <stdio.h>  // For printf
#include <cv.h>  
#include <cxcore.h>  
#include <highgui.h>      

int main()  
{  


    int key = 0; 



    CvCapture* capture = cvCaptureFromAVI( "macroblock.mpg" );  
    IplImage* frame = cvQueryFrame( capture );
    IplImage* gray = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
    cvCvtColor(frame, gray, CV_RGB2GRAY);

        if ( !capture ) 

    {  
        fprintf( stderr, "Cannot open AVI!\n" );  
        return 1;  
        }
          int fps = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );

           cvNamedWindow( "video", CV_WINDOW_AUTOSIZE ); 
         cvNamedWindow( "grayvideo", CV_WINDOW_AUTOSIZE ); 

        while( key != 'x' )  
    {  
        frame = cvQueryFrame( capture );




    if(key==27 )break;
     cvShowImage( "video",frame );
     cvShowImage( "grayvideo",gray );


           key = cvWaitKey( 1000 / fps );  
    }  
           cvDestroyWindow( "video" );  
    cvReleaseCapture( &capture );  

    return 0;  
}  
john_science
  • 6,325
  • 6
  • 43
  • 60
Ilan Reuven
  • 61
  • 2
  • 3
  • 6
  • You should learn the c++ opencv api. Using cv::Mat object for images, which have its own destructor (and a ref counter) you dont need to release the IplImage* manually, what you forgot in your code. – Eric Apr 02 '12 at 11:48
  • If this question has been successfully answered, consider selecting the official answer by clicking on the checkbox near it. If not, consider adding your own answer. – karlphillip Jun 05 '12 at 23:32

3 Answers3

3

You need to convert each frame from color to gray scale. It does not get converted automatically if you do it once in the beginning. So you need to add

cvCvtColor(frame, gray, CV_BGR2GRAY);

into your while-loop after your call to cvQueryFrame.

sietschie
  • 7,425
  • 3
  • 33
  • 54
  • can i do difference between current frame to previous frame in this code? how i reduce previous from current frame and show the result on window? – Ilan Reuven Apr 02 '12 at 19:23
  • I'm pretty sure that BGR is the default pixel format in OpenCV. I see that most examples use CV_RGB2GRAY, but imho (unless I'm very much mistaken), it would be better to use CV_BGR2GRAY – mehfoos yacoob Aug 19 '13 at 11:22
  • That's true. Although the only difference is, that less red and more blue is used for computing the result. – sietschie Aug 22 '13 at 12:27
1

There were a few problems with your code.

  • It was a mess and poorly idented;
  • When you need to check the return of a function, you should do it right after you call them. Ex: cvCaptureFromAVI();
  • As cvQueryFrame() might fail, you need to check it's return as well;
  • You forgot to execute the RGB -> GRAY conversion: cvCvtColor(frame, gray, CV_RGB2GRAY); before displaying the gray frame;
  • You also forgot to release the resources for the grayvideo window;

Isn't it easier to read/understand a code when it looks like this?

int main()  
{      
    CvCapture* capture = cvCaptureFromAVI( "macroblock.mpg" );  
    if ( !capture ) 
    {  
        fprintf( stderr, "Cannot open AVI!\n" );  
        return 1;  
    }

    int fps = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );
    printf("FPS: %d\n", fps);

    cvNamedWindow( "video", CV_WINDOW_AUTOSIZE ); 
    cvNamedWindow( "grayvideo", CV_WINDOW_AUTOSIZE ); 

    int key = 0; 
    IplImage* gray = NULL;
    IplImage* prev_frame = NULL;

    while( key != 'x' )  
    {  
        frame = cvQueryFrame( capture );
        if (!frame) 
        {
            // print error and abort the loop
            break;
        }

        cvShowImage( "video", frame );

        if (!gray) // allocate space for the GRAY frame only once
        {
            gray = cvCreateImage(cvGetSize(frame), frame->depth,1);
        }
        cvCvtColor(frame, gray, CV_RGB2GRAY); // convert RGB frame to GRAY
        cvShowImage( "grayvideo", gray );

        if (!prev_frame) // allocate space for the GRAY frame only once
        {
            prev_frame = cvCreateImage(cvGetSize(frame), frame->depth,1);
            cvCopy( frame, prev_frame, 0 );
        }

        // perform process to compute the "difference" of the current 
        // and previous frames:
        // <add your code here>

        // then, update prev_frame now so in the next iteration it holds the previous frame
        cvCopy( frame, prev_frame, 0 );

        key = cvWaitKey( 1000 / fps );  
        if ( key==27 ) // ESC was pressed
            break;
    }  

    cvDestroyWindow( "video" );  
    cvDestroyWindow( "grayvideo" );  

    cvReleaseCapture( &capture );  

    if (gray)
        cvReleaseImage( &gray );

    if (prev_frame)
        cvReleaseImage( &prev_frame );

    return 0;  
}  
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • do you have an idea how to do difference between 2 frames for example current frame to previous frame? thank you – Ilan Reuven Apr 02 '12 at 19:41
  • I just updated the code to store the previous frame. The computation of the *difference between 2 frames*, whatever that means to you, needs to be written. There's a bunch of questions on how to detect the difference between frames in this forum. You can use the search box to help you and find the appropriate technique. Good luck. – karlphillip Apr 02 '12 at 20:07
0

use one of below opencv functions based on you need:

subtract(img_current,img_prev, img_diff);
absdiff(img_current, img_prev, img_diff);
furins
  • 4,979
  • 1
  • 39
  • 57
Dawit
  • 1