John Mars

10 Feb 2015

Magic Eye images, or Autostereograms are those cool pictures that make a 3D object appear when you cross your eyes funny. I’ve made an application using kylemcdonald/ofxAutostereogram and Geistyp/ofxGif to import a depth-map gif like the one below, and an obfuscation image (the crumpled paper) and export a Magic Eye GIF. I thought it would be an interesting twist on something from my childhood, and I wanted to see if the effect would even work on a lenticular print. I also wanted to add autostereogram 3d to my 3d image toolkit, as well as 3d animations.

I originally tried to generate a rotating icosahedron and use its openGL depth map texture as the depth map image instead of using the Kinect depth video, but I was ultimately unsuccessful. My next venture is certainly going to be exploring Fbos and shaders. I also tried generating a static image instead of using the paper tiles as the background, but it seems that autostereograms can’t use white noise for that purpose.

CAVEATS: I didn’t have access to a Kinect while I was building the application, so it’s currently using stills from a video I found online. I’ll switch it out to a video of me ASAP. Also, I didn’t even realize this until it was too late, but it looks like one of the examples in ofxAutostereogram creates animated stereograms from Kinect video, so, this isn’t even an original idea (although it was derived independently).

Here’s the ofApp.cpp:

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

    ofSetFrameRate(5);

    i = 0;
    
    bgTile.loadImage("paper.jpg");
    bgTile.resize(128, 128);
    
    gifLoader.load("kinect.gif");
    
    // allocate images
    depthMap.allocate(gifLoader.pages[0].getWidth(), gifLoader.pages[0].getHeight(), OF_IMAGE_GRAYSCALE);
    magicEye.allocate(depthMap.getWidth() + bgTile.getWidth(), depthMap.getHeight(), OF_IMAGE_COLOR);
    
    ofSetWindowShape(magicEye.width, magicEye.height + bgTile.getWidth());
    
    gifSaver.create("output.gif");
}

//--------------------------------------------------------------
void ofApp::update(){
    
    depthMap.setFromPixels(gifLoader.pages[i % 9]);
    depthMap.setImageType(OF_IMAGE_GRAYSCALE);
    
    i++;
}

//--------------------------------------------------------------
void ofApp::draw(){

    ofBackground(0);

    float depthMultiplier = .2;
    ofxAutostereogram::makeAutostereogram(bgTile, depthMap, depthMultiplier, magicEye);

    magicEye.update();
    magicEye.draw(0, 0, ofGetWidth(), ofGetHeight());
    
    if (i < 10) {
        ofImage img;
        img.grabScreen(0, 0, ofGetWidth(), ofGetHeight());
        gifSaver.append(img.getPixelsRef());
    }
    
    if (i == 10) {
        gifSaver.save();
        ofLog() << "SAVED";
    }
}

And the entire project’s code can be found here: https://github.com/marsman12019/stereoGIF