Created
August 25, 2020 07:24
-
-
Save suvirbhargav/af7f3ef77072e52a8b15b0c4fff9c7c6 to your computer and use it in GitHub Desktop.
Using webcam video as texture in OpenGL + some modification to run it with current opencv on Linux.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Original gist was here: https://gist.github.com/Ashwinning/baeb0835624fedc2e5b809d42417b70e | |
// Modified from "Video Texture" code | |
// Copyright (C) 2009 Arsalan Malik ([email protected]) | |
// | |
// On Mac OS X, compile with: | |
// g++ -o VideoTexture VideoTexture.cpp -framework OpenGL -framework Glut -I | |
// /usr/local/include/opencv/ $(pkg-config --libs opencv) | |
////////////////////////////////////////////////////////////////////////////// | |
// On Linux, | |
// g++ -o example-opengl example-opengl.cpp -I/usr/include/opencv4 | |
// `pkg-config opencv4 --libs` -lGL -lGLU -lglut -lglfw -lGL -lX11 -lpthread -lXrandr -lXi -ldl | |
////////////////////////////////////////////////////////////////////////////// | |
// Open CV includes | |
//#include <cv.h> | |
#include "opencv2/core/utility.hpp" | |
#include "opencv2/imgproc.hpp" | |
#include "opencv2/imgcodecs.hpp" | |
#include "opencv2/highgui.hpp" | |
#include <opencv2/videoio/videoio_c.h> | |
//#include <highgui.h> | |
// Standard includes | |
#include <stdio.h> | |
#include <string.h> | |
#include <assert.h> | |
// OpenGL/Glut includes | |
#ifdef __APPLE__ | |
#include <GLUT/glut.h> | |
#else | |
#include <GL/glut.h> | |
#endif | |
// Timing includes | |
#include <sys/time.h> | |
#define KEY_ESCAPE 27 | |
//CvCapture *g_Capture; | |
cv::VideoCapture g_Capture; | |
GLint g_hWindow; | |
// Frame size | |
int frame_width = 640; | |
int frame_height = 480; | |
// current frames per second, slightly smoothed over time | |
double fps; | |
// show mirror image | |
bool mirror = true; | |
// Return current time in seconds | |
double current_time_in_seconds(); | |
// Initialize glut window | |
GLvoid init_glut(); | |
// Glut display callback, draws a single rectangle using video buffer as | |
// texture | |
GLvoid display(); | |
// Glut reshape callback | |
GLvoid reshape(GLint w, GLint h); | |
// Glut keyboard callback | |
GLvoid key_press(unsigned char key, GLint x, GLint y); | |
// Glut idle callback, fetches next video frame | |
GLvoid idle(); | |
double current_time_in_seconds() | |
{ | |
timeval timer; | |
gettimeofday(&timer, NULL); | |
double seconds = 1e-6 * timer.tv_usec + timer.tv_sec; | |
return seconds; | |
} | |
GLvoid init_glut() | |
{ | |
glClearColor(0.0, 0.0, 0.0, 0.0); | |
// Set up callbacks | |
glutDisplayFunc(display); | |
glutReshapeFunc(reshape); | |
glutKeyboardFunc(key_press); | |
glutIdleFunc(idle); | |
} | |
GLvoid display(void) | |
{ | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glEnable(GL_TEXTURE_2D); | |
// These are necessary if using glTexImage2D instead of gluBuild2DMipmaps | |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); | |
// Set Projection Matrix | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
gluOrtho2D(0, frame_width, frame_height, 0); | |
// Switch to Model View Matrix | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
// Draw a textured quad | |
glBegin(GL_QUADS); | |
glTexCoord2f(0.0f, 0.0f); | |
glVertex2f(0.0f, 0.0f); | |
glTexCoord2f(1.0f, 0.0f); | |
glVertex2f(frame_width, 0.0f); | |
glTexCoord2f(1.0f, 1.0f); | |
glVertex2f(frame_width, frame_height); | |
glTexCoord2f(0.0f, 1.0f); | |
glVertex2f(0.0f, frame_height); | |
glEnd(); | |
glFlush(); | |
glutSwapBuffers(); | |
} | |
GLvoid reshape(GLint w, GLint h) | |
{ | |
glViewport(0, 0, w, h); | |
} | |
GLvoid key_press(unsigned char key, int x, int y) | |
{ | |
switch (key) | |
{ | |
case 'f': | |
printf("fps: %g\n", fps); | |
break; | |
case 'm': | |
mirror = !mirror; | |
break; | |
case KEY_ESCAPE: | |
//cvReleaseCapture(&g_Capture); | |
glutDestroyWindow(g_hWindow); | |
exit(0); | |
break; | |
} | |
glutPostRedisplay(); | |
} | |
GLvoid idle() | |
{ | |
// start timer | |
double start_seconds = current_time_in_seconds(); | |
// Capture next frame, this will almost always be the limiting factor in the | |
// framerate, my webcam only gets ~15 fps | |
//IplImage *image; // = cvQueryFrame(g_Capture); | |
cv::Mat image; | |
//frame = cvQueryFrame( capture ); //assegna frame | |
g_Capture.read(image); | |
// Of course there are faster ways to do this with just opengl but this is to | |
// demonstrate filtering the video before making the texture | |
if (mirror) | |
{ | |
// cvFlip(image, NULL, 1); | |
flip(image, image, +1); | |
} | |
// Image is memory aligned which means we there may be extra space at the end | |
// of each row. gluBuild2DMipmaps needs contiguous data, so we buffer it here | |
char *buffer = new char[image.cols * image.rows * image.channels()]; | |
int step = image.step; //widthStep; | |
int height = image.rows; | |
int width = image.cols; | |
int channels = image.channels(); | |
char *data = (char *)image.data; //imageData; | |
// memcpy version below seems slightly faster | |
//for(int i=0;i<height;i++) | |
//for(int j=0;j<width;j++) | |
//for(int k=0;k<channels;k++) | |
//{ | |
// buffer[i*width*channels+j*channels+k] = data[i*step+j*channels+k]; | |
//} | |
for (int i = 0; i < height; i++) | |
{ | |
memcpy(&buffer[i * width * channels], &(data[i * step]), width * channels); | |
} | |
// Create Texture | |
glTexImage2D( | |
GL_TEXTURE_2D, | |
0, | |
GL_RGB, | |
image.cols, | |
image.rows, | |
0, | |
GL_BGR, | |
GL_UNSIGNED_BYTE, | |
buffer); | |
// Clean up buffer | |
delete[] buffer; | |
// Update display | |
glutPostRedisplay(); | |
double stop_seconds = current_time_in_seconds(); | |
fps = 0.9 * fps + 0.1 * 1.0 / (stop_seconds - start_seconds); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
// Create OpenCV camera capture | |
// If multiple cameras are installed, this takes "first" one | |
//g_Capture = cvCaptureFromCAM(0); | |
//assert(g_Capture); | |
g_Capture.open(0); // open the default camera | |
if (!g_Capture.isOpened()) | |
{ | |
//std::cout << "Capture not open successfully 0" << std::endl; | |
printf("Capture not open successfully"); | |
getchar(); | |
//return -1; | |
} | |
// capture properties | |
//frame_height = (int)cvGetCaptureProperty(g_Capture, CV_CAP_PROP_FRAME_HEIGHT); | |
//frame_width = (int)cvGetCaptureProperty(g_Capture, CV_CAP_PROP_FRAME_WIDTH); | |
//setting the dimensions of webcam frame | |
frame_width = g_Capture.get(cv::CAP_PROP_FRAME_WIDTH); | |
frame_height = g_Capture.get(cv::CAP_PROP_FRAME_HEIGHT); | |
// Create GLUT Window | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); | |
glutInitWindowSize(frame_width, frame_height); | |
g_hWindow = glutCreateWindow("Video Texture"); | |
// Initialize OpenGL | |
init_glut(); | |
glutMainLoop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for code