Opencv Capture Causes Memory Allocation Error - c

I have implemented a capture code runs on OpenCV libraries. Code captures from 2 cameras order by order. But the code causes memory allocation error after a while.
I have to release a capture stream of camera1 to open a capture stream of camera2. I could not able to get two capture simultanously so I have to capture it order by order.
Why it couses memory allocation error in this scenario?
My code is located below:
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
#include <stdio.h>
CvCapture* camera; // Use the default camera
IplImage* frame;
int main(int argc, char* argv[])
{
while(1)
{
camera = cvCreateCameraCapture(0); // Use the default camera
//camera2 = cvCreateCameraCapture(1); // Use the default camera
frame = 0;
//frame2 = 0;
cvSetCaptureProperty(camera,CV_CAP_PROP_FRAME_WIDTH,1024) ;
cvSetCaptureProperty(camera,CV_CAP_PROP_FRAME_HEIGHT,768);
frame = cvQueryFrame(camera); //need to capture at least one extra frame
if (frame != NULL) {
printf("Frame extracted from CAM1\n\r");
cvSaveImage("/dev/shm/webcam1.jpg", frame,0);
printf("Frame from CAM1 saved\n\r");
} else {
printf("Null frame 1\n\r");
}
cvReleaseImage(&frame);
cvReleaseCapture(&camera);
camera = cvCreateCameraCapture(1); // Use the default camera
cvSetCaptureProperty(camera,CV_CAP_PROP_FRAME_WIDTH,1024) ;
cvSetCaptureProperty(camera,CV_CAP_PROP_FRAME_HEIGHT,768);
frame = cvQueryFrame(camera); //need to capture at least one extra frame
if (frame != NULL) {
printf("Frame extracted from CAM2\n\r");
cvSaveImage("/dev/shm/webcam2.jpg", frame,0);
printf("Frame from CAM2 saved\n\r");
} else {
printf("Null frame 2\n\r");
}
cvReleaseImage(&frame);
cvReleaseCapture(&camera);
}

First of all, you can start declaring out of while() statement the cameraCapture:
camera0 = cvCreateCameraCapture(0);
camera1 = cvCreateCameraCapture(1);
frame0 = 0;
frame1 = 0;
cvSetCaptureProperty(camera0,CV_CAP_PROP_FRAME_WIDTH,1024) ;
cvSetCaptureProperty(camera0,CV_CAP_PROP_FRAME_HEIGHT,768);
cvSetCaptureProperty(camera1,CV_CAP_PROP_FRAME_WIDTH,1024) ;
cvSetCaptureProperty(camera1,CV_CAP_PROP_FRAME_HEIGHT,768);
while(1) {
/* your operation */
frame0 = cvQueryFrame(camera0);
frame1 = cvQueryFrame(camera1);
/* your operation */
}
cvReleaseImage(&frame0);
cvReleaseImage(&frame1);
cvReleaseCapture(&camera0);
cvReleaseCapture(&camera1);
Edit
If you want to take first stream from A-cam and then from B-cam, you'll have a code like the this. I don't understand exactly what do you want to do, so this code simply show your stream on a window.
Remember to use cvWaitKey(...) in order to give to highgui time to process the draw requests from cvShowImage().
Also, take a look at the documentation of cvSetCaptureProperty: here is written that currently the function supports only video files:
CV_CAP_PROP_POS_MSEC;
CV_CAP_PROP_POS_FRAMES;
CV_CAP_PROP_POS_AVI_RATIO.
By the way, this is my suggest:
const char* wndName = "window";
cvNamedWindow(wndName, CV_WINDOW_NORMAL);
IplImage* frame;
CvCapture* capture;
while(true) {
capture = cvCaptureFromCAM(0);
/* Showing for a while capture in window */
while(/* your condition */) {
frame = cvQueryFrame(capture);
/* operation with A cam */
cvShowImage(wndName, frame);
cvWaitKey(30);
}
cvReleaseCapture(&capture);
cvWaitKey(100);
/* switching source cam */
capture = cvCaptureFromCAM(1);
/* Showing for a while capture in the same window */
while(/* your condition */) {
frame = cvQueryFrame(capture);
/* operation with B cam */
cvShowImage(wndName, frame);
cvWaitKey(30);
}
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);
This works for me, give me any feedback.

Related

Getting volume value from pulseaudio

I've written this code by looking at various examples: Python pulseaudio monitor, Pavumeter source, async playback example, and Pacat source.
I have successfully connected to a sink and am able to record it, but my problem is, I'm stuck at getting the volume value out. If I try printing value from the read function, I just get a bunch of random numbers at a second's interval.
Now I'm not asking for someone to finish writing the code for me, I'd just like some tips, help so that I could head towards the right direction. How do I retrieve the volume value?
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <pulse/pulseaudio.h>
static int latency = 20000; // start latency in micro seconds
static int sampleoffs = 0;
static short sampledata[300000];
static pa_buffer_attr bufattr;
static int underflows = 0;
static pa_sample_spec ss;
// This callback gets called when our context changes state. We really only
// care about when it's ready or if it has failed
void pa_state_cb(pa_context *c, void *userdata) {
pa_context_state_t state;
int *pa_ready = userdata;
state = pa_context_get_state(c);
switch (state) {
// These are just here for reference
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
default:
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
*pa_ready = 2;
break;
case PA_CONTEXT_READY:
*pa_ready = 1;
break;
}
}
static void stream_read_cb(pa_stream *s, size_t length, void *userdata) {
const void *data;
pa_stream_peek(s, &data, &length);
data = (const unsigned char*) data;
printf("%u", data);
pa_stream_drop(s);
}
int main(int argc, char *argv[]) {
pa_mainloop *pa_ml;
pa_mainloop_api *pa_mlapi;
pa_context *pa_ctx;
pa_stream *recordstream;
int r;
int pa_ready = 0;
int retval = 0;
unsigned int a;
double amp;
int test = 0;
// Create a mainloop API and connection to the default server
pa_ml = pa_mainloop_new();
pa_mlapi = pa_mainloop_get_api(pa_ml);
pa_ctx = pa_context_new(pa_mlapi, "Simple PA test application");
pa_context_connect(pa_ctx, NULL, 0, NULL);
// This function defines a callback so the server will tell us it's state.
// Our callback will wait for the state to be ready. The callback will
// modify the variable to 1 so we know when we have a connection and it's
// ready.
// If there's an error, the callback will set pa_ready to 2
pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);
// We can't do anything until PA is ready, so just iterate the mainloop
// and continue
while (pa_ready == 0) {
pa_mainloop_iterate(pa_ml, 1, NULL);
}
if (pa_ready == 2) {
retval = -1;
goto exit;
}
ss.rate = 44100;
ss.channels = 2;
ss.format = PA_SAMPLE_U8;
recordstream = pa_stream_new(pa_ctx, "Record", &ss, NULL);
if (!recordstream) {
printf("pa_stream_new failed\n");
}
pa_stream_set_read_callback(recordstream, stream_read_cb, NULL);
r = pa_stream_connect_record(recordstream, NULL, NULL, PA_STREAM_PEAK_DETECT);
if (r < 0) {
printf("pa_stream_connect_playback failed\n");
retval = -1;
goto exit;
}
// Run the mainloop until pa_mainloop_quit() is called
// (this example never calls it, so the mainloop runs forever).
// printf("%s", "Running Loop");
pa_mainloop_run(pa_ml, NULL);
exit:
// clean up and disconnect
pa_context_disconnect(pa_ctx);
pa_context_unref(pa_ctx);
pa_mainloop_free(pa_ml);
return retval;
}
Looking at the original question from UNIX.StackExchange, it looks like you're trying to create a VU meter. It can be done using an envelope detector. You have to read the input values and then average their rectified value. A simple envelope detector can be done as an exponential moving average filter.
float level = 0; // Init time
const float alpha = COEFFICIENT; // See below
...
// Inside sample loop
float input_signal = fabsf(get_current_sample());
level = level + alpha * (input_signal - level);
Here, alpha is the filter coefficient, which can be calculated as:
const float alpha = 1.0 - expf( (-2.0 * M_PI) / (TC * SAMPLE_RATE) );
Where TC is known as the "time constant" parameter, measured in seconds, which defines how fast you want to "follow" the signal. Setting it too short makes the VU meter very "bumpy" and setting it too long will miss transients in the signal. 10 mS is a good value to start from.

Pixel manipulation using sdl

I am trying to manipulate pixel using sdl and manage to read them up now. Below is my sample code. When I print I this printf("\npixelvalue is is : %d",MyPixel); I get values like this
11275780
11275776
etc
I know these are not in hex form but how to manipulate say I want to filter just the blue colors out? Secondly after manipulation how to generate the new image?
#include "SDL.h"
int main( int argc, char* argv[] )
{
SDL_Surface *screen, *image;
SDL_Event event;
Uint8 *keys;
int done = 0;
if (SDL_Init(SDL_INIT_VIDEO) == -1)
{
printf("Can't init SDL: %s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
SDL_WM_SetCaption("sample1", "app.ico");
/* obtain the SDL surfance of the video card */
screen = SDL_SetVideoMode(640, 480, 24, SDL_HWSURFACE);
if (screen == NULL)
{
printf("Can't set video mode: %s\n", SDL_GetError());
exit(1);
}
printf("Loading here");
/* load BMP file */
image = SDL_LoadBMP("testa.bmp");
Uint32* pixels = (Uint32*)image->pixels;
int width = image->w;
int height = image->h;
printf("Widts is : %d",image->w);
for(int iH = 1; iH<=height; iH++)
for(int iW = 1; iW<=width; iW++)
{
printf("\nIh is : %d",iH);
printf("\nIw is : %d",iW);
Uint32* MyPixel = pixels + ( (iH-1) + image->w ) + iW;
printf("\npixelvalue is is : %d",MyPixel);
}
if (image == NULL) {
printf("Can't load image of tux: %s\n", SDL_GetError());
exit(1);
}
/* Blit image to the video surface */
SDL_BlitSurface(image, NULL, screen, NULL);
SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
/* free the image if it is no longer needed */
SDL_FreeSurface(image);
/* process the keyboard event */
while (!done)
{
// Poll input queue, run keyboard loop
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_QUIT )
{
done = 1;
break;
}
}
keys = SDL_GetKeyState(NULL);
if (keys[SDLK_q])
{
done = 1;
}
// Release CPU for others
SDL_Delay(100);
}
// Release memeory and Quit SDL
SDL_FreeSurface(screen);
SDL_Quit();
return 0;
}
Use SDL_MapRGB and SDL_MapRGBA to sort colors out. SDL will filter it out for you, based on surface format.
Just like this:
Uint32 rawpixel = getpixel(surface, x, y);
Uint8 red, green, blue;
SDL_GetRGB(rawpixel, surface->format, &red, &green, &blue);
You are printing the value of the pointer MyPixel. To get the value you have to dereference the pointer to the pixel value like this: *MyPixel
Then the printf would look like this:
printf("\npixelvalue is : %d and the address of that pixel is: %p\n",*MyPixel , MyPixel);
Other errors:
Your for loops are incorrect. You should loop from 0 to less than width or height, or else you will read uninitialized memory.
You didn't lock the surface. Although you are only reading the pixels and nothing should go wrong it is still not correct.
Test for correctness if the image pointer comes after you are already using the pointer. Put the test right after the initialization.
If I recall correctly I used sdl_gfx for pixel manipulation.
It also contains function like drawing a circle, oval etc.

OpenCV - Video playback is slow if slider updates its position while playing

I have picked up 'Learning OpenCV' and have been trying some of the code examples/exercises. In this code snippet, I want to get the slider to update its position with each video frame change, but for some reason it is slowing down the video playback speed.
The slider is updating the position during video playback using cvSetTrackbarPos() function but it is making the playback very slow.
#include <cv.h>
#include <highgui.h>
using namespace std;
int g_slider_position = 0;
CvCapture *g_capture = NULL;
void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
int main(int argc, char *argv[])
{
if(argc<2)
{
printf("Usage: main <video-file-name>\n\7");
exit(0);
}
// create a window
cvNamedWindow("Playing Video With Slider", CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture(argv[1]);
int frames = (int) cvGetCaptureProperty(g_capture, \
CV_CAP_PROP_FRAME_COUNT);
if(frames !=0)
{
cvCreateTrackbar("Slider","Playing Video With Slider", \
&g_slider_position,frames, onTrackbarSlide);
}
IplImage* frame = 0;
while(1)
{
frame = cvQueryFrame(g_capture);
if(!frame)
{
break;
}
cvShowImage("Playing Video With Slider", frame);
cvSetTrackbarPos("Slider","Playing Video With Slider", \
g_slider_position+1); //Slowing down playback
char c= cvWaitKey(33);
if(c == 27)
{
break;
}
}
// release the image
cvReleaseImage(&frame );
cvReleaseCapture(&g_capture);
// Destroy Window
cvDestroyWindow("Playing Video With Slider");
return 0;
}
This is an inefficiency in how opencv displays trackbars (the same problem occurs even if you don't update the slider, and in case when you refer to non-changing variable outside the processing loop).
A workaround might be to display the trackbar in a separate window.
Line char c= cvWaitKey(33); have problem.
It is in while(1) and every time it takes 33 milisecond to Wait for a pressed key.Make this number lesser.
EDITED LATER:
Make change as shown below
void onTrackbarSlide(int pos)
{
pos = g_slider_position;
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
The problem is that every time You call cvSetTrackbarPos("Slider","Playing Video With Slider", g_slider_position+1); callback onTrackbarSlide changing the video position another time and slowing down the program flow.
The way I find out to avoid that is with a flag. It tells the callback if the change in the Trackbar is produced by the normal update flow or is produced by You.
int g_slider_position = 0;
int g_update_slider = 0;//flag
CvCapture *g_capture = NULL;
void onTrackbarSlide(int pos)
{
if (!g_update_slider)//if not changed by the video flow
{
cvSetCaptureProperty(
g_capture,
CV_CAP_PROP_POS_FRAMES,
pos
);
}
}
void updateSlider(int pos)
{
g_update_slider = 1; //Changed by the video flow
cvSetTrackbarPos("Position", "Example3", pos);
g_update_slider = 0; //Returns the flag when the change is performed
}
In the main I call for updateSlider instead of cvSetTrackbarPos.

How Copy frame to farme

How can a variable in one frame to another frame it is that kind of copy that is not a memory management problem
for example :
iplimage *frame = NULL;
iplimage *Temp_frame = NULL;
while(1) {
frame = cvQueryFrame( capture );
if( !frame ) break;
Temp_frame=cvcloneimage(frame);
cvreleaseImage(&Temp_frame);
cvreleaseImage(&frame);
}
Error:
Unhandled exception at 0x75b39673 in open cv.exe: Microsoft C++ exception: cv::Exception at memory location 0x0015f250..
Please help.
iplimage *frame = NULL;
iplimage *Temp_frame = NULL;
while(1)
{
frame = cvQueryFrame(capture);
if (!frame)
break;
if (!Temp_frame) // creates Temp_frame only once
Temp_frame = cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
cvCopy(frame , Temp_frame, NULL);
// DO NOT RELEASE the return of cvQueryFrame()!
// I believe that's what crashing your application.
//cvreleaseImage(&frame);
}
// Since the size of "frame" won't change, there's no need to to create/release
// Temp_frame on every iteration of the loop. So we release it at the end:
cvReleaseImage(&Temp_frame);

Writing AVI files in OpenCV

There example on the net and code given in Learn OpenCv,Orielly.
After many attempts the out.avi file is written with 0 bytes.
I wonder where i went wrong.
The following are the code i used...
int main(int argc, char* argv[]) {
CvCapture* input = cvCaptureFromFile(argv[1]);
IplImage* image = cvRetrieveFrame(input);
if (!image) {
printf("Unable to read input");
return 0;
}
CvSize imgSize;
imgSize.width = image->width;
imgSize.height = image->height;
double fps = cvGetCaptureProperty(
input,
CV_CAP_PROP_FPS
);
CvVideoWriter *writer = cvCreateVideoWriter(
"out.avi",
CV_FOURCC('M', 'J', 'P', 'G'),
fps,
imgSize
);
IplImage* colourImage;
//Keep processing frames...
for (;;) {
//Get a frame from the input video.
colourImage = cvQueryFrame(input);
cvWriteFrame(writer, colourImage);
}
cvReleaseVideoWriter(&writer);
cvReleaseCapture(&input);
}
My bet is that cvCreateVideoWriter returns NULL. Just step through it to see if it's true. In that case, the problem is probably with CV_FOURCC(..) which doesnt find the codec and force a return 0;
you can try using -1 instead of CV_FOURCC. There is gonna be a prompt during runtime for you to chose the appropriate codec
When i google this problem i meet an answer: "OpenCV on mac os x don`t support avi write until it will be compiled with a ffmpeg"
For me seem to wrok this solution
http://article.gmane.org/gmane.comp.lib.opencv/16005
You need to provide the full path to
the file with the movie in
cvCreateVideoWriter. I don't know
whether it's only an Mac OS X port
issue, but might be, since
QTNewDataReferenceFromFullPathCFString
from the QT backend is used.
hey This code works in DevC++ try it:
#include<cv.h>
#include<highgui.h>
#include<cvaux.h>
#include<cvcam.h>
#include<cxcore.h>
int main()
{
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 5; // or 30
int frameW = 1600; //640; // 744 for firewire cameras
int frameH = 1200; //480; // 480 for firewire cameras
//writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),
// fps,cvSize(frameW,frameH),isColor);
writer=cvCreateVideoWriter("out.avi",-1,
fps,cvSize(frameW,frameH),isColor);
IplImage* img = 0;
img=cvLoadImage("CapturedFrame_0.jpg");
cvWriteFrame(writer,img); // add the frame to the file
img=cvLoadImage("CapturedFrame_1.jpg");
cvWriteFrame(writer,img);
img=cvLoadImage("CapturedFrame_2.jpg");
cvWriteFrame(writer,img);
img=cvLoadImage("CapturedFrame_3.jpg");
cvWriteFrame(writer,img);
img=cvLoadImage("CapturedFrame_4.jpg");
cvWriteFrame(writer,img);
img=cvLoadImage("CapturedFrame_5.jpg");
cvWriteFrame(writer,img);
cvReleaseVideoWriter(&writer);
return 0;
}
I compiled it and ran it, works fine.
(I did not see above whether you got your answer or not .. but for this particular thing I worked very hard earlier and suddenly I just did it, from some code snippets.)
It's a codec issue. Try out all the possible codecs (option -1 in cvCreateVideo). In my case Microsoft Video 1 worked well.
Maybe you could try inserting a printf("Frame found\n") inside the for(;;) to see if it is actually capturing frames. Or even better:
if(colourImage == NULL) {
printf("Warning - got NULL colourImage\n");
continue;
}
cvNamedWindow( "test", 1);
cvShowImage( "test", colourImage );
cvWaitKey( 0 );
cvDestroyWindow( "test" );
Then see if you get any windows, and if they contain the right contents.
This code worked fine:
cv.h
highgui.h
cvaux.h
cvcam.h
cxcore.h
int main(){
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 5; // or 30
IplImage* img = 0;
img=cvLoadImage("animTest_1.bmp");
int frameW = img->width; //640; // 744 for firewire cameras
int frameH = img->height; //480; // 480 for firewire cameras
writer=cvCreateVideoWriter("out.avi",-1,
fps,cvSize(frameW,frameH),1);
cvWriteFrame(writer, img); // add the frame to the file
char *FirstFile,fF[20]="",*fileNoStr,fns[4]="";
fileNoStr=fns;
for(int fileNo;fileNo<100;fileNo++){
FirstFile=fF;
itoa(fileNo,fileNoStr,10);
FirstFile=strcat ( FirstFile,"animTest_");
FirstFile=strcat ( FirstFile,fileNoStr);
FirstFile=strcat ( FirstFile,".bmp");
printf(" \n%s .",FirstFile);
img=cvLoadImage(FirstFile);
cvWriteFrame(writer, img);
}
cvReleaseVideoWriter(&writer);
return 0;
}
I think the problem you're encountering is that your "for" loop never ends; therefore, cvReleaseVideoWriter(&writer); and cvReleaseCapture(&input); never get called. Try something like for(int i=0; i<200; i++) and see if you end up with a working video.
Often video is written to a temporary files before being finalized on disk. If your file isn't finalized, there won't be anything to see.
Hope that helps.

Resources