PDA

View Full Version : [pls help] camera capture as background, object on



wearlab
03-19-2010, 10:38 PM
Hi all,

I'm beginner at OpenGL,

I want to display the video from a camera capture in the OpenGL window, then draw some contours or fonts in this window, and these contours or fonts will move or rotate all the time.

I have 2 problems about this:

(1) I've tried to use the OpenCV to get the camera capture, Iplimage it and texture it in the OpenGL window, it works but still have a problem of the Iplimage should be 2^X (like 256, 515) dimension, then it calls some distortion.
(2) When add some objects (eg. a plane) in the above (1) OpenGL window, I found when I try to rotate the plane, the camera video texture also rotate together with it, but I just want the object(the plane) rotate, the camera video act as the background.

I use Ubuntu 9.10, Eclipse, Opencv, Glut to do this.

Please help, here are the codes, thanks!!!


#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "ml.h"
#include "cvaux.h"
#include <iostream>
#include <stdlib.h>
#include<stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include<time.h>
#include<stdlib.h>
#include <GL/gl.h>
#include <GL/glut.h>

IplImage *ipl_src_camera = NULL;
IplImage *ipl_src_camera_resize = NULL;

IplImage *frame = NULL;
CvCapture* capture = NULL;
int nFrmNum = 0;

GLuint texture_list_camera;

void texture_load_from_camera() {
/*
* when using the camera direct rendering,
* should shut down the DEPTH_TEST function;
*/
glDisable(GL_DEPTH_TEST);

ipl_src_camera_resize = cvCreateImage(cvSize(256, 256), IPL_DEPTH_8U, 3);
capture = cvCaptureFromCAM(0);
cvNamedWindow("CV window");
while (frame = cvQueryFrame(capture)) {
nFrmNum++;
if (nFrmNum == 1) {
ipl_src_camera = cvCreateImage(cvSize(frame->width, frame->height),IPL_DEPTH_8U, 3);
} else {
cvCopy(frame, ipl_src_camera, 0);
cvResize(ipl_src_camera, ipl_src_camera_resize);

cvFlip(ipl_src_camera_resize, NULL, 0);
cvShowImage("CV window", ipl_src_camera_resize);

printf("load texture from camera\n");
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture_list_camera);

glPixelStorei(GL_UNPACK_ALIGNMENT, texture_list_camera);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
ipl_src_camera_resize->width,
ipl_src_camera_resize->height, 0, GL_BGR_EXT,
GL_UNSIGNED_BYTE, ipl_src_camera_resize->imageData);

//draw the plan to display the camera video;
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();

// draw another smaller plane on the camera video background
glRotatef(-_angle, 1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-0.5f, -1.0f, 0.0f);
glVertex3f(1.0f, -0.5f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(-0.3f, 0.2f, 0.0f);
glEnd();
}
if (cvWaitKey(2) >= 0) {
cvReleaseImage(&amp;ipl_src_camera);
cvReleaseImage(&amp;ipl_src_camera_resize);
cvDestroyWindow("CV window");
break;
}
}

void handle_resizeWindow(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float) w / (float) h, 1.0, 200.0);
}

void handle_keyPress(unsigned char key, int x, int y) {
switch (key) {
case 27: //Escape key
exit(0);
}
}
//Called every 25 milliseconds
void handle_update(int value) {
_angle += 0.2f;
if (_angle > 360) {
_angle -= 360;
}
glutPostRedisplay();
glutTimerFunc(25, handle_update, 0);
}
void handle_display() {
static int time_base = 0, frame = 0;
frame++;
// Get the number of milliseconds since "glutInit" has been called.
int time = glutGet(GLUT_ELAPSED_TIME);
if (time - time_base > 1000) {
sprintf(&amp;title[44], " (%3.2f FPS)", frame * 1000.0f
/ (time - time_base));
glutSetWindowTitle(title);
time_base = time;
frame = 0;
}

}
void glInit(int argc, char** argv) {
glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow(title);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
}

int main(int argc, char** argv) {

glInit(argc, argv);
glutKeyboardFunc(handle_keyPress);
glutReshapeFunc(handle_resizeWindow);
glutTimerFunc(25, handle_update, 0);
glutDisplayFunc(handle_display);

texture_load_from_camera();

glutMainLoop();
return 0;
}

Kelvin
03-19-2010, 11:27 PM
Re (1)

You don't have to use the full area of the texture image. You can use just part of it, and then adjust your texture coordinates to extract just the part of the image that you used.

On the other hand, if you stretch the image to fill the 256x512 texture, you can squish it again by adjusting your vertex positions.

Re (2)


// draw another smaller plane on the camera video background
glRotatef(-_angle, 1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-0.5f, -1.0f, 0.0f);
glVertex3f(1.0f, -0.5f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(-0.3f, 0.2f, 0.0f);
glEnd();

The glRotatef call above affects the current matrix permanently -- everything drawn after that is rotated -- even if the things drawn after that are in another iteration of the rendering loop. To protect against this, use the matrix stack glPushMatrix()/glPopMatrix() to save and restore the un-rotated version of the matrix, like so:


// draw another smaller plane on the camera video background
glPushMatrix(); // save current matrix
glRotatef(-_angle, 1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-0.5f, -1.0f, 0.0f);
glVertex3f(1.0f, -0.5f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(-0.3f, 0.2f, 0.0f);
glEnd();
glPopMatrix(); // restore saved matrix


A few more things:

A) It is usual to perform object rotations using the modelview matrix -- I leave the modelview matrix active by default. This looks like a good place (warning; I'm not very familiar with GLUT):



void handle_resizeWindow(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float) w / (float) h, 1.0, 200.0);
glMatrixMode(GL_MODELVIEW); // Apply transformations to modelview matrix by default.
}


B) glPushMatrix and glPopMatrix may be nested, but they must be eventually matched in pairs, or you will overflow or underflow the matrix stack -- you've got single glPushMatrix (I would delete it).

C) I'm not very familiar with GLUT, but expected to find your main drawing routine in handle_display(), where it would not need a loop -- I expect GLUT would call it periodically.

D) I suggest starting your modelview matrix in a known state at the beginning of every drawing frame, using glLoadIdentity(). Then you know where your glRotatef() etc. commands are starting from.