Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

chroma key with openframeworks/opengl

I need to implement chroma keying (removal of a solid color background) in an openFrameworks application.

I'll be playing many (10 or more) videos simultaneously (in the same frame), and drawing them to the screen along with alternate backgrounds. I can achieve a chroma-key-like effect by iterating through each frame's pixels and setting alpha values for each one based on a green threshold, but with so many videos at once, this pixel-banging becomes prohibitive.

Is there an easy OpenGL blend mode or masking operation which can avoid drawing all pixels of a certain color value? Or is there another openFrameworks or openFrameworks-compatible C++ library which can do this efficiently?

Alternatively, is there a good (space-efficient) way to store alpha-channel in quicktime-compatible video files? We're going to be storing terabytes of video (weeks of continuous recording), so it's important that we use space-efficient formats.

One note: the chroma-key color in the source files will be "perfect" -- it is added digitally. So if there's some sort of thresholding or bitwise-logic trick to do this, that could work too.


EDIT: Here's what worked, following VJo's suggestion for a pixel shader. We used glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), and the following pixel shader (for magenta as the replaced color):

"data/shaders/chromakey.frag":

#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect src_tex_unit0;
vec4 color;

void main( void )
{
        vec2 st = gl_TexCoord[0].st;
        vec4 sample = texture2DRect(src_tex_unit0, st );
        gl_FragColor = sample;
        if((sample.r > 0.5) && (sample.g < 0.5) && (sample.b > 0.5)) {
                gl_FragColor.a = 0.0;
        }
}

"data/shaders/chromakey.vert":

void main()
{
    gl_Position = ftransform();
    gl_TexCoord[0] = gl_MultiTexCoord[0];
}

The C++ proxy classes for the shaders -- shaderChromakey.h:

#include "ofMain.h"
#include "ofxShader.h"
#include "ofxFBOTexture.h"

class shaderChromakey{

    public:
        void setup(int fboW, int fboH);

        void beginRender();
        void endRender();

        void draw(int x, int y, int width, int height);

        ofxShader shader;

        ofxFBOTexture fbo;

};

shaderChromakey.cpp:

#include "shaderChromakey.h"

//--------------------------------------------------------------
void shaderChromakey::setup(int fboW, int fboH){ 

    ofBackground(255,255,255);
    ofSetVerticalSync(true);

    fbo.allocate(fboW, fboH, true);

    shader.loadShader("shaders/chromakey");
}

//--------------------------------------------------------------
void shaderChromakey::beginRender(){
    fbo.swapIn();
}

//--------------------------------------------------------------
void shaderChromakey::endRender(){
    fbo.swapOut();
}

//--------------------------------------------------------------
void shaderChromakey::draw(int x, int y, int width, int height){

    shader.setShaderActive(true);
    fbo.draw(x, y, width, height);
    shader.setShaderActive(false);
}

To instantiate the shader, in the project:

shaderChromakey chromakey;
chromakey.setup(HORIZONTAL, VERTICAL)

In the draw loop, to enable the shader:

chromakey.beginRender();
    // draw chomakeyed frame here
chromakey.endRender();
like image 441
user85461 Avatar asked Jan 23 '11 22:01

user85461


People also ask

Can Shotma chroma key?

Shotcut is an open-source video editor that works on Windows, macOS, and Linux. It's a powerful software with the chroma key feature available among the list of effects.

Can you do chroma key with any color?

Although green and blue are the most common in part because red, green and blue components are used to encode the visible light spectrum, any key colour can be used.


1 Answers

You could use glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA) and then when you enable blending, you could use a pixel shader to do what you want if the pixel is of specific color (set alpha to 0).

like image 113
BЈовић Avatar answered Sep 19 '22 15:09

BЈовић