C – OpenCV: Handling Each Frame

I want to write a cross-platform application that uses OpenCV for video capture. In all the examples, I found using the grab function to process the frames from the camera and wait for a while. I want to process Each frame in the sequence. I want to define my own callback function, which will be executed when the new frame is ready to be processed (just like in the directshow of Windows, when you define and put in the graphics for this purpose, you Own filter).

So the question is: how can I do this?

According to the code below, all callbacks must follow the following definition:

IplImage* custom_callback(IplImage* frame);

This signature indicates that the callback will be executed on each frame retrieved by the system. In my case, make_it_gray() Assign a new image to save the result of the grayscale conversion and return it. This means that you must release this frame in the code later. I added a comment about the code for it.

Please note that if Your callback requires a lot of processing, and the system may skip a few frames in the camera. Consider the suggestions of Paul R and diverscuba23.

#include 
#include "cv.h"
#include "highgui.h"


typedef IplImage* (*callback_prototype)(IplImage*);


/*
* make_it_gray: our custom callback to convert a colored frame to its grayscale version.
* Remember that you must deallocate the returned IplImage* yourself after calling this function.
*/
IplImage* make_it_gray(IplImage* frame)
{
// Allocate space for a new image
IplImage* gray_frame = 0;
gray_frame = cvCreateImage( cvSize(frame->width, frame->height), frame->depth, 1);
if (!gray_frame)
{
fprintf(stderr, " !!! cvCreateImage failed!\n" );
return NULL;
}

cvCvtColor(frame, gray_frame, CV_RGB2GRAY);
return gray_frame;
}

/*
* process_video: retrieves frames from camera and executes a callback to do individual frame processing.
* Keep in mind that if your callback takes too much time to execute, you might loose a few frames from
* the camera.
*/
void process_video(callback_prototype custom_cb)
{
// Initialize camera
CvCapture *capture = 0;
capture = cvCaptureFromCAM(-1);
if (!capture)
{
fprintf(stderr, "!!! Cannot open initialize webcam!\ n" );
return;
}

// Create a window for the video
cvNamedWindow("result", CV_WINDOW_AUTOSIZE);

IplImage* frame = 0;
char key = 0;
while (key != 27) // ESC
{
frame = cvQueryFrame(capture);
if(!frame)
{
fprintf( stderr, "!!! cvQueryFrame failed!\n" );
break;
}

/ / Execute callback on each frame
IplImage* processed_frame = (*custom_cb)(frame);

// Display processed frame
cvShowImage("result", processed_frame);

// Release resources
cvReleaseImage(&processed_frame);

// Exit when user press ESC
key = cvWaitKey(10);
}

// Free memory
cvDestroyWindow("result");
cvReleaseCapture(&capture);
}

int main( int argc , char **argv )
{
process_video(make_it_gray);

return 0;
}

Edit:

< p>I changed the code above so it prints the current frame rate and performs manual grayscale conversion. They are small adjustments to the code, I did it for educational purposes, so we know how to perform operations at the pixel level.

#include 
#include

#include "cv.h"
#include "highgui.h"


typedef IplImage* (*callback_prototype)(Ipl Image*);


/*
* make_it_gray: our custom callback to convert a colored frame to its grayscale version.
* Remember that you must deallocate the returned IplImage* yourself after calling this function.
*/
IplImage* make_it_gray(IplImage* frame)
{
// New IplImage* to store the processed image
IplImage * gray_frame = 0;

// Manual grayscale conversion: ugly, but shows how to access each channel of the pixels individually
gray_frame = cvCreateImage(cvSize(frame->width, frame-> height), frame->depth, frame->nChannels);
if (!gray_frame)
{
fprintf(stderr, "!!! cvCreateImage failed!\n" );
return NULL;
}

for (int i = 0; i width * frame->height * frame->nChannels; i += frame->nChannels)
{
gray_frame->imageData[i] = (frame->imageData[i] + frame->imageData[i+1] + frame->imageData[i+2])/3; / /B
gray_frame->ima geData[i+1] = (frame->imageData[i] + frame->imageData[i+1] + frame->imageData[i+2])/3; //G
gray_frame->imageData [i+2] = (frame->imageData[i] + frame->imageData[i+1] + frame->imageData[i+2])/3; //R
}

return gray_frame;
}

/*
* process_video: retrieves frames from camera and executes a callback to do individual frame processing.
* Keep in mind that if your callback takes too much time to execute, you might loose a few frames from
* the camera.
*/
void process_video(callback_prototype custom_cb)
{
// Initialize camera
CvCapture *capture = 0;
capture = cvCaptureFromCAM(-1);
if (!capture)
{
fprintf(stderr, "!!! Cannot open initialize webcam!\n" );
return;
}

// Create a window for the video
cvNamedWindow("result" , CV_WINDOW_AUTOSIZE);

double elapsed = 0;
int last_tim e = 0;
int num_frames = 0;

IplImage* frame = 0;
char key = 0;
while (key != 27) // ESC
{
frame = cvQueryFrame(capture);
if(!frame)
{
fprintf( stderr, "!!! cvQueryFrame failed!\n" );
break;
}

// Calculating framerate
num_frames++;
elapsed = clock()-last_time;
int fps = 0;
if (elapsed> 1)
{
fps = floor(num_frames / (float)(1 + (float)elapsed / (float)CLOCKS_PER_SEC));
num_frames = 0 ;
last_time = clock() + 1 * CLOCKS_PER_SEC;
printf("FPS: %d\n", fps);
}

// Execute callback on each frame
IplImage* processed_frame = (*custom_cb)(frame);

// Display processed frame
cvShowImage("result", processed_frame);
< br /> // Release resources
cvReleaseIma ge(&processed_frame);

// Exit when user press ESC
key = cvWaitKey(10);
}

// Free memory
cvDestroyWindow("result");
cvReleaseCapture(&capture);
}

int main( int argc, char **argv )
{
process_video(make_it_gray);

return 0;
}

I want to write a cross-platform application that uses OpenCV for video capture Program. In all the examples, I found using the grab function to process the frames from the camera and wait for a while. I want to process each frame in the sequence. I want to define my own callback function when the new frame is ready to be processed , It will be executed (just like in the directshow of Windows, when you define and put your own filter for this purpose).

So the question is: how can I do this Do?

According to the code below, all callbacks must follow the following definitions:

IplImage* custom_callback(IplImage* frame);

This signature indicates that the callback will be executed on each frame retrieved by the system. In my example, make_it_gray() allocates a new image to save the result of grayscale conversion and Return it. This means you have to release this frame in your code later. I added a comment about its code.

Please note that if your callback requires a lot of processing, the system may skip A few frames in the camera. Consider the suggestions of Paul R and diverscuba23.

#include 
#include "cv.h"
#include "highgui.h"


typedef IplImage* (*callback_prototype)(IplImage*);


/*
* make_it_gray: our custom callback to convert a colored frame to its grayscale version.
* Remember that you must deallocate the returned IplImage* yourself after calling this function.
*/
IplImage* make_it_gray(IplImage * frame)
{
// Allocate space for a new image
IplImage* gray_frame = 0;
gray_frame = cvCreateImage(cvSize(frame->width, frame->height) , frame->depth, 1);
if (!gray_frame)
{
fprintf(stderr, "!!! cvCreateImage failed!\n" );
return NULL; }

cvCvtColor(frame, gray_frame, CV_RGB2GRAY);
return gray_frame;
}

/*
* process_video: retrieves frames from camera and executes a callback to do individual frame processing.
* Keep in mind that if your callback takes too much time to execute, you might loose a few frames from
* the camera.
*/
void process_video(callback_prototype custom_cb)
{
// Initialize camera
CvCapture *capture = 0;
capture = cvCaptureFromCAM(-1);< br /> if (!capture)
{
fprintf(stderr, "!!! Cannot open initialize webcam!\n" );
return;
}

// Create a window for the video
cvNamedWindow("result", CV_WINDOW_AUTOSIZE);

IplImage* frame = 0;
char key = 0;
while (key != 27) // ESC
{
frame = cvQueryFrame(capture);
if(!frame)
{
fprintf( stderr,"!!! cvQueryFrame failed!\n" );
break;
}

// Execute callback on each frame
IplImage* processed_frame = (*custom_cb) (frame);

// Display processed frame
cvShowImage("result", processed_frame);

// Release resources
cvReleaseImage(&processed_frame) ;

// Exit when user press ESC
key = cvWaitKey(10);
}

// Free memory
cvDestroyWindow( "result");
cvReleaseCapture(&capture);
}

int main( int argc, char **argv )
{
process_video(make_it_gray );

return 0;
}

Edit:

I changed the above code, so it prints the current frame rate and performs manual Grayscale conversion. They are small adjustments to the code, I did it for educational purposes, so we know how to perform operations at the pixel level.

#include 
#include

#include "cv.h"
#include "highgui.h"


typedef IplImage* (*callback_prototype)(IplImage*);


/*
* make_it_gray: our custo m callback to convert a colored frame to its grayscale version.
* Remember that you must deallocate the returned IplImage* yourself after calling this function.
*/
IplImage* make_it_gray(IplImage* frame)
{
// New IplImage* to store the processed image
IplImage* gray_frame = 0;

// Manual grayscale conversion: ugly, but shows how to access each channel of the pixels individually
gray_frame = cvCreateImage(cvSize(frame->width, frame->height), frame->depth, frame->nChannels);
if (!gray_frame)
{
fprintf(stderr, "!!! cvCreateImage failed!\n" );
return NULL;
}

for (int i = 0; i width * frame->height * frame->nChannels; i += frame->nChannels)
{
gray_frame->imageData[i] = (frame->imageData[i] + frame->imageData[i+1] + frame->imageData[i+2])/3; //B
gray_frame->imageData[i+1] = (frame->imageData[i] + frame ->imageData[i+1] + frame->imageData[i+2])/3; //G
gray_frame->imageData[i+2] = (frame->imageData[i] + frame->imageData[i+1] + frame ->imageData[i+2])/3; //R
}

return gray_frame;
}

/*
* process_video: retrieves frames from camera and executes a callback to do individual frame processing.
* Keep in mind that if your callback takes too much time to execute, you might loose a few frames from
* the camera .
*/
void process_video(callback_prototype custom_cb)
{
// Initialize camera
CvCapture *capture = 0;
capture = cvCaptureFromCAM(-1 );
if (!capture)
{
fprintf(stderr, "!!! Cannot open initialize webcam!\n" );
return;
}< br />
// Create a window for the video
cvNamedWindow("result", CV_WINDOW_AUTOSIZE);

double elapsed = 0;
int last_time = 0;
int num_frames = 0;

IplImage* frame = 0;
char key = 0;
while (key != 27) // ESC
{
frame = cvQueryFrame(capture);
if(! frame)
{
fprintf( stderr, "!!! cvQueryFrame failed!\n" );
break;
}

// Calculating framerate
num_frames++;
elapsed = clock()-last_time;
int fps = 0;
if (elapsed> 1)
{
fps = floor( num_frames / (float)(1 + (float)elapsed / (float)CLOCKS_PER_SEC));
num_frames = 0;
last_time = clock() + 1 * CLOCKS_PER_SEC;
printf("FPS : %d\n", fps);
}

// Execute callback on each frame
IplImage* processed_frame = (*custom_cb)(frame);

// Display processed frame
cvShowImage("result", processed_frame);

// Release resources
cvReleaseImage(&processed_frame);

// Exit when user pres s ESC
key = cvWaitKey(10);
}

// Free memory
cvDestroyWindow("result");
cvReleaseCapture(&capture);
}

int main( int argc, char **argv )
{
process_video(make_it_gray);

return 0;< br />}

Leave a Comment

Your email address will not be published.