Mirroring Video with openFrameworks
When you create an installation that uses a webcam to analyse the behavior of people, you often need to mirror the video to use it. In this article I’m going to explain how to do this in openFrameworks.
The first thing you need to do is to declare some variables in testApp.h. You’ll need an ofVideoGrabber to capture video from the webcam, an ofTexture to render the mirrored video to the screen, a char array to store temporary pixel values and two integers for the width and height of the video to capture. Add this code to testApp.h, right after the standard methods.
ofVideoGrabber vidGrabber; ofTexture mirrorTexture; unsigned char * videoMirror; int camWidth; int camHeight;
Next up is setting the values of these variables in the setup() method of testApp.cpp. Set the width and height of the video to capture first, set up the grabber, create a new unsigned char for the temporary pixel values and allocate a texture for the mirrored video. Note that the lenght of the temporary pixel array is camWidth x camHeight x 3. Each pixel takes up 3 places in the array. One for each RGB component. Add the code below to setup().
camWidth = 320; camHeight = 240; vidGrabber.setVerbose(true); vidGrabber.initGrabber(camWidth, camHeight); videoMirror = new unsigned char[camWidth*camHeight*3]; mirrorTexture.allocate(camWidth, camHeight, GL_RGB);
Once the variables are all set up, you’ll need the algorithm to swap pixels. This is a bit tricky because you need to swap them in blocks of three values. You can’t just reverse the pixels as the R, G and B components need to stay in place. If you don’t do this, the colors of the mirrored video will look weird.
This is the code to add to the update() method.
ofBackground(0, 0, 0);
vidGrabber.grabFrame();
if (vidGrabber.isFrameNew()) {
unsigned char * pixels = vidGrabber.getPixels();
for (int i = 0; i < camHeight; i++) {
for (int j = 0; j < camWidth*3; j+=3) {
// pixel number
int pix1 = (i*camWidth*3) + j;
int pix2 = (i*camWidth*3) + (j+1);
int pix3 = (i*camWidth*3) + (j+2);
// mirror pixel number
int mir1 = (i*camWidth*3)+1 * (camWidth*3 - j-3);
int mir2 = (i*camWidth*3)+1 * (camWidth*3 - j-2);
int mir3 = (i*camWidth*3)+1 * (camWidth*3 - j-1);
// swap pixels
videoMirror[pix1] = pixels[mir1];
videoMirror[pix2] = pixels[mir2];
videoMirror[pix3] = pixels[mir3];
}
}
mirrorTexture.loadData(videoMirror, camWidth, camHeight, GL_RGB);
}
Drawing the video to the screen is easy. You do need to set the background to solid white before drawing, otherwise the video will be tinted in the color that was last set. Add this code to testApp.cpp in draw()
ofSetColor(255, 255, 255); vidGrabber.draw(0, 0); mirrorTexture.draw(camWidth, 0, camWidth, camHeight);
Now build that app and it should look somewhat like the picture below.

So now you know how to mirror an RGB video. This is useful for tracking colors. Next article will be about mirroring grayscale video, which is a lot faster and good if you only need to track motion.
Downloads
Related Articles
Browse Articles
Comments (7)
From:Theodore Watson
Date:19.01.2010
Nice tutorial!
Another easier way to do it is to use the ofxOpenCv addon.
Both the ofxCvColorImage and ofxCvGrayscaleImage have a mirror(bool flipHorizontal, bool flipVertical) method, so you can stick the pixels in a cvimage flip them and get them back.
Its nice to know how to do it by hand though- I made my students learn it by hand before I told them about the mirror function :)
Hardest yet is a 90/270 Degree rotate – especially with an RGB array.
From:Bart
Date:16.02.2010
This works as well:
glPushMatrix();
ofTranslate(camWidth,camHeight);
glScalef(-1, -1,1);
vidGrabber.draw(0,0);
glPopMatrix();
You can also rotate it by exchanging the glScalef with an ofRotate. Problem is that they both work with a pivot situated at (0,0)
From:xenomuta
Date:03.03.2010
Both of your examples have enlightened me anyways, but I was getting this done with better performance by drawing images with negative width:
image.setFromPixels(vidGrabber.getPixels(), camWidth, camHeight);
image.draw(xPos + camWidth, yPos, -camWidth, camHeight);
From:Jan Vantomme
Date:03.03.2010
I wouldn’t recommend using the algorithm in this article if you only use it to display images. I wrote it just to show how the pixel arrays in openFrameworks work.
Algorithms like this can be used to track objects without using OpenCV or as a base for Augmented Reality applications.
From:Chris Hodapp
Date:12.06.2011
Thank you for this page! I’m new to OpenFrameworks and was trying to complete the simple task of writing some pixels to a texture, then displaying that texture on the screen. Your example pointed out that I just needed to precede my texture.draw(…) call with ofSetColor(255,255,255).
From:Keith
Date:06.07.2011
Very helpful post (and comments), thanks!
Popular Articles
- Introduction to openFrameworks
- Creating 3D Shapes with Hemesh
- Mirroring Video with openFrameworks
- An Introduction to colorLib
- How to create a FullScreen iPhone Application
Popular Tags
- processing (90)
- software (50)
- web design (40)
- art (39)
- css3 (37)
From:Jan Vantomme
Date:19.01.2010
Didn’t know about the mirror function in ofxOpenCv. Wrote this on the train and didn’t have any documentation with me. Was fun to do.
Wouldn’t ask my students to write algorithms like this. Most of them think it’s hard enough to draw simple shapes with code.
Top · Permanent link to this comment