Chroma Key mit OpenFrameworks/OpenGL
-
23-10-2019 - |
Frage
Ich muss die Chroma -Keying (Entfernen eines festen Farbhintergrunds) in einer OpenFrameWorks -Anwendung implementieren.
Ich werde viele (10 oder mehr) Videos gleichzeitig (im selben Rahmen) spielen und sie zusammen mit alternativen Hintergründen auf den Bildschirm ziehen. Ich kann einen Chroma-Key-ähnlichen Effekt erzielen, indem ich die Pixel jedes Frame durch Iterien durch Iterien durch Iterien basiert, basierend auf einem grünen Schwellenwert, aber mit so vielen Videos gleichzeitig wird diese Pixel-Banging unerschwinglich.
Gibt es einen einfachen OpenGL -Mischmodus oder Maskierungsvorgang, mit dem alle Pixel eines bestimmten Farbwerts das Zeichnen eines bestimmten Farbwerts vermeiden können? Oder gibt es eine weitere OpenFrameworks oder OpenFrameWorks-kompatible C ++-Bibliothek, die dies effizient bewirkt?
Gibt es alternativ eine gute (platzeffiziente) Möglichkeit, Alpha-Kanal in QuickTime-kompatiblen Videodateien zu speichern? Wir werden Terabyte von Videos (Wochen der kontinuierlichen Aufnahme) aufbewahren. Daher ist es wichtig, dass wir platzeffiziente Formate verwenden.
Ein Hinweis: Die Chroma-Key-Farbe in den Quelldateien ist "perfekt"-sie wird digital hinzugefügt. Wenn es also eine Art Schwellenwert oder bitweise logische Trick gibt, könnte dies auch funktionieren.
BEARBEITEN: Hier ist das, was funktioniert hat und VJOs Vorschlag für einen Pixel -Shader folgt. Wir verwendeten glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
, und der folgende Pixel -Shader (für Magenta als ersetzte Farbe):
"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;
}
}
"Daten/Shaders/Chromakey.vert":
void main()
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord[0];
}
Die C ++ - Proxy -Klassen für die 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;
};
saderchromakey.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);
}
So instanziieren Sie den Shader im Projekt:
shaderChromakey chromakey;
chromakey.setup(HORIZONTAL, VERTICAL)
In der Zeichnungsschleife, um den Shader zu aktivieren:
chromakey.beginRender();
// draw chomakeyed frame here
chromakey.endRender();
Lösung
Du könntest benutzen glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA)
Und wenn Sie das Mischen aktivieren, können Sie einen Pixel -Shader verwenden, um das zu tun, was Sie wollen, wenn das Pixel eine bestimmte Farbe hat (Alpha auf 0 einstellen).