2011-01-23 12 views
5

Devo implementare la chroma keying (rimozione di uno sfondo a tinta unita) in un'applicazione openFrameworks.chroma key con openframeworks/opengl

Riproduco molti (10 o più) video contemporaneamente (nello stesso fotogramma) e li disegno sullo schermo insieme a sfondi alternativi. Posso ottenere un effetto simile a una chiave cromatica eseguendo il iterazione attraverso i pixel di ogni fotogramma e impostando valori alfa per ognuno in base a una soglia verde, ma con così tanti video contemporaneamente, questo sbarramento di pixel diventa proibitivo.

C'è una semplice modalità di fusione OpenGL o un'operazione di mascheramento che può evitare di disegnare tutti i pixel di un determinato valore di colore? O c'è un'altra libreria open source OpenFrameworks o compatibile con OpenFrameworks che può farlo in modo efficiente?

In alternativa, esiste un buon metodo (efficiente in termini di spazio) per archiviare il canale alfa in file video compatibili quicktime? Memorizzeremo terabyte di video (settimane di registrazione continua), quindi è importante utilizzare formati efficienti in termini di spazio.

Una nota: il colore della chiave di crominanza nei file sorgente sarà "perfetto" - viene aggiunto digitalmente. Quindi, se c'è una sorta di trucco di soglia o di logica bit per fare questo, potrebbe funzionare anche questo.


EDIT: Ecco che cosa ha funzionato, seguendo il suggerimento di VJO per un pixel shader. Abbiamo usato glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), e il successivo pixel shader (per il colore magenta come il colore sostituito):

"dati/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; 
     } 
} 

"dati/shaders/chromakey.vert":

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

Il C++ classi proxy per gli shader - 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; 

}; 

s haderChromakey.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); 
} 

Per istanziare lo shader, nel progetto:

shaderChromakey chromakey; 
chromakey.setup(HORIZONTAL, VERTICAL) 

Nel ciclo pareggio, per consentire lo shader:

chromakey.beginRender(); 
    // draw chomakeyed frame here 
chromakey.endRender(); 

risposta

2

Si potrebbe utilizzare glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA) e poi quando abiliti la fusione, puoi usare un pixel shader per fare ciò che vuoi se il pixel è di un colore specifico (imposta alfa su 0).