How Copy frame to farme - c

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);

Related

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.

Severe breaks and leaks

I have a code which basically detects playing cards, isolates them from a dynamic background based on HSV settings, then uses contours to detect the 4 points of the card to find the exact x and y position of the card. From there, the ROI is set and I can perform further processing to detect the face value of the card.
However, I the code seems to be breaking and I can't seem to find the root cause of it.
I have cleared images & memory storages, I've ensured that all the Iplimages have the same formatting and resolution.
IplImage* GetThresholdedImage(IplImage* imgHSV){
IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
cvInRangeS(imgHSV, cvScalar(95,67,170), cvScalar(110,119,254), imgThresh); //Morning
return imgThresh;
}
IplImage* RedCheck(IplImage* imgBGR){
IplImage* img=cvCreateImage(cvGetSize(imgBGR),IPL_DEPTH_8U, 1);
cvInRangeS(imgBGR, cvScalar(0,0,100), cvScalar(100,100,254), img); //BGR
return img;
}
int main()
{
CvCapture* capture =0;
capture = cvCaptureFromCAM(0);
if(!capture)
{
printf("Capture failure\n");
return -1;
}
IplImage* frame = cvCreateImage(cvSize(48,64),IPL_DEPTH_8U,3);
while(true)
{
frame = cvQueryFrame(capture);
if(!frame) break;
frame=cvCloneImage(frame);
cvSmooth(frame, frame, CV_GAUSSIAN,3,3); //smooth the original image using Gaussian kernel
IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvCvtColor(frame, imgHSV, CV_BGR2HSV); //Change the color format from BGR to HSV
IplImage* imgThresh = GetThresholdedImage(imgHSV);
cvSmooth(imgThresh, imgThresh, CV_GAUSSIAN,3,3); //smooth the binary image using Gaussian kernel
CvSeq* contours;
CvSeq* result;
CvMemStorage *storage = cvCreateMemStorage(0);
cvFindContours(imgThresh, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
while(contours)
{
result = cvApproxPoly(contours, sizeof(CvContour),storage,CV_POLY_APPROX_DP,cvContourPerimeter(contours)*0.02,0);
if(result->total == 4)
{
CvPoint *pt[4];
for(int i=0;i<4;i++)
{
pt[i] = (CvPoint*)cvGetSeqElem(result,i);
}
if (cvArcLength(result,CV_WHOLE_SEQ,1) >= 400)
{
cvLine(imgThresh,*pt[0],*pt[1],cvScalar(255,0,0),4);
cvLine(imgThresh,*pt[1],*pt[2],cvScalar(255,0,0),4);
cvLine(imgThresh,*pt[2],*pt[3],cvScalar(255,0,0),4);
cvLine(imgThresh,*pt[3],*pt[0],cvScalar(255,0,0),4);
int ROIwidth = abs((*pt[0]).x - (*pt[1]).x);
int ROIheight = abs((*pt[1]).y - (*pt[2]).y);
cvSetImageROI(frame,cvRect((*pt[1]).x,(*pt[1]).y,ROIwidth,ROIheight));
IplImage* temp = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
cvCopy(frame,temp,0);
cvResetImageROI(frame);
cvNamedWindow( "ROI", CV_WINDOW_AUTOSIZE );
cvShowImage( "ROI", temp);
printf("Width = %d\n",ROIwidth); //255-275
printf("Height = %d\n",ROIheight); //140-160
//Card Value Detection Starts Here
IplImage* colorcheck = RedCheck(temp);
int redpixelcheck = cvCountNonZero(colorcheck);
if (redpixelcheck <= 15)
{
printf("Card is Black\n");
}
else if (redpixelcheck >= 16)
{
printf("Card is Red\n");
}
//Card Value Detection Ends Here
cvReleaseImage(&temp);
cvReleaseImage(&frame);
cvReleaseImage(&colorcheck);
delete &ROIwidth;
delete &ROIheight;
delete &redpixelcheck;
}
//delete [] pt[4];
}
delete &result;
contours = contours->h_next;
//cvPutText (frame_t,text,cvPoint(200,400), &font, cvScalar(255,255,0));
}
cvNamedWindow( "Contour", CV_WINDOW_AUTOSIZE );
cvShowImage( "Contour", imgThresh);
cvNamedWindow("Video",CV_WINDOW_AUTOSIZE);
cvShowImage("Video", frame);
//Clean up used images
cvReleaseImage(&imgHSV);
cvReleaseImage(&imgThresh);
cvReleaseImage(&frame);
cvClearMemStorage(storage);
cvReleaseMemStorage(&storage);
//Wait 50mS
int c = cvWaitKey(10);
//If 'ESC' is pressed, break the loop
if((char)c==27 ) break;
}
cvDestroyAllWindows() ;
cvReleaseCapture(&capture);
return 0;
}
The disassembly always points to the same address
770915DE add esp,4

Opencv Capture Causes Memory Allocation Error

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.

Taking a screenshot of the Windows desktop with a C program.

Is it possible to take a screenshot of the desktop and save it as .jpg,jpeg,...at any location in the computer by C programming? I am curious to know if there is any method and way to achieve this task. I'm using Windows XP.
Assuming Visual Studio:
This is copy & paste from working code (some lines ommited):
HDC hdcScreen = NULL;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
CImage myimage;
IStream* pIStream = NULL;
STATSTG stg;
HGLOBAL hGlobal = NULL;
HRESULT hResult = 0;
UINT nDataSize = 0;
do
{
//
// Get the screen capture in an HBITMAP.
// -------------------------------------
// Retrieve the handle to a display device context for the client
// area of the window.
hdcScreen = ::GetDC(NULL);
if ( hdcScreen == NULL )
{
SET_CHECKPOINT();
break;
}
// Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcScreen);
if ( hdcMemDC == NULL )
{
SET_CHECKPOINT();
break;
}
// Get the client area for size calculation
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
// Create a compatible bitmap from the Window DC
hbmScreen = CreateCompatibleBitmap(hdcScreen, cx, cy);
if ( hbmScreen == NULL )
{
SET_CHECKPOINT();
break;
}
// Select the compatible bitmap into the compatible memory DC.
SelectObject(hdcMemDC,hbmScreen);
// Bit block transfer into our compatible memory DC.
BitBlt(hdcMemDC, 0,0, cx, cy, hdcScreen, 0,0, SRCCOPY);
// Create a stream to have CImage write data to.
hResult = CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
if ( hResult != S_OK )
{
SET_CHECKPOINT();
break;
}
// Attach an ATL CImage to the hbitmap.
myimage.Attach(hbmScreen);
// Write data to stream.
hResult = myimage.Save(pIStream, Gdiplus::ImageFormatJPEG);
if ( hResult != S_OK )
{
SET_CHECKPOINT();
break;
}
myimage.Detach();
// Get the stream's HGLOBAL.
hResult = GetHGlobalFromStream(pIStream, &hGlobal);
if ( hResult != S_OK )
{
SET_CHECKPOINT();
break;
}
// Get a pointer to the data in the HGLOBAL.
char* pJPGData = (char*)GlobalLock(hGlobal);
pIStream->Stat(&stg, STATFLAG_NONAME);
nDataSize = (UINT)stg.cbSize.QuadPart;
// TODO: Open a file instead of a pipe...
//pJPGData points to the data, nDataSize is, well...
if ( WriteFile(hFile, pJPGData, nDataSize, &dwBytesWritten, NULL) == FALSE )
{
SET_CHECKPOINT();
break;
}
// TODO: Close the file.
}
while (0,0);
//
// Free resources.
// ---------------
if ( pIStream != NULL ) pIStream->Release();
//Clean up
if ( hbmScreen ) DeleteObject(hbmScreen);
if ( hdcMemDC ) DeleteObject(hdcMemDC);
if ( hdcScreen ) ::ReleaseDC(NULL,hdcScreen);

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