Color Keying Pixel Bender

Um die Arbeitsweise mit Pixel Bender (ehemals Hydra) auszuprobieren, habe ich einen Filter geschrieben, der in Echtzeit ein Green-Screen-Video filtert. Über einen Threshold-Regler lässt sich die Stärke des Filters regeln. Über drei Slider (RGB-Farbwert) kann die Keyfarbe festgelegt werden.

Hier das Beispiel zum Anschauen: Demo

Hinweis: Um das Beispiel zu betrachten, wird der Flash Player 10 (zurzeit in der Betaphase) benötigt.

Pixel Bender Colorkey Filter

Der Colorkey-Filter hat eine RGB-Farbe als Grundlage, also die Keyfarbe. Alle Werte, die dieser Farbe exakt entsprechen werden transparent gemacht. Des Weiteren werden alle ähnlichen Farben unsichtbar gemacht, wobei die Toleranz über den "Threshold" genauer geregelt werden kann.

Mit weiteren Bearbeitungsschritten wie Kantenglättung, etc. würde sich die Qualität des Filters sicherlich um einiges optimieren lassen. Außerdem ist das Grün im Beispielvideo relativ dunkel und wäre bei gutem Footage wesentlich besser zu filtern.

Der Filtercode für Pixel Bender lautet:

CODE:
  1. /*****************************************************************************
  2. *
  3. * by Florian Plag
  4. * www.video-flash.de
  5. *
  6. *****************************************************************************/
  7.  
  8. <languageVersion: 1.0;>
  9.  
  10. // color keying
  11. kernel colorKey
  12. <  namespace : "AIF";
  13.     vendor : "Florian Plag";
  14.     version : 1;
  15.     description : "Color keying";>
  16. {
  17.     input image4 src;
  18.    
  19.     output float4 dst;
  20.    
  21.     // Threshold
  22.     parameter float threshold
  23.     <minValue: 0.0;
  24.      maxValue: 1.0;
  25.      defaultValue: 0.1;>;
  26.      
  27.     // key color (RGB)
  28.     parameter float3 keyColor;
  29.  
  30.    
  31.     void
  32.     evaluatePixel()
  33.     {
  34.         // Obtain the input pixel color
  35.         float4 inputColor = sampleNearest(src, outCoord());
  36.        
  37.         // tolerance for key color
  38.         float3 keyCMinusThr = float3 ( (keyColor.r - threshold), (keyColor.g - threshold), (keyColor.b - threshold));
  39.         float3 keyCPlusThr = float3 ( (keyColor.r + threshold), (keyColor.g + threshold), (keyColor.b + threshold));       
  40.  
  41.         // if color is the key color (or similar)
  42.         if (  ((inputColor.r> keyCMinusThr.r) && (inputColor.r <keyCPlusThr.r)) &&  ((inputColor.g> keyCMinusThr.g) && (inputColor.g <keyCPlusThr.g)) &&  ((inputColor.b> keyCMinusThr.b) && (inputColor.b <keyCPlusThr.b))        )  {
  43.           // transparent pixel 
  44.           dst.rgba = float4(1.0, 1.0, 0.0, 0.0);
  45.         }
  46.         else {
  47.          // keep source pixel
  48.          dst.rgb = inputColor.rgb;
  49.          // and source alpha
  50.          dst.a = inputColor.a;
  51.         }
  52.  
  53.  
  54.     }
  55. }

Wie nutzt man Pixel Bender in Flash/Flex?

Anhand des Beispiels sieht man, wie man einen Pixel Bender Filter in Flex verwendet.

XML:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application
  3.     xmlns:mx="http://www.adobe.com/2006/mxml"
  4.     xmlns:test="*"
  5.     width="800" height="800" backgroundImage="bgpattern.png"
  6.     creationComplete="creationCompleteHandler()"
  7. >
  8.  
  9.  
  10. <mx:Script>
  11.     <![CDATA[
  12.  
  13.     import flash.display.*;
  14.     import flash.events.*;
  15.     import flash.net.*;
  16.     import flash.filters.*;
  17.     import flash.utils.*;
  18.  
  19.     private var shader:Shader;
  20.     private var shaderFilter:ShaderFilter;
  21.     private var myVideo:Video;
  22.     private var ns:NetStream;
  23.    
  24.  
  25.         public function creationCompleteHandler():void  {
  26.  
  27.  
  28.             // new video
  29.             myVideo = new Video(400,300);
  30.             myUIComponent.addChild(myVideo);
  31.             var nc:NetConnection = new NetConnection();
  32.             nc.connect(null);
  33.             ns = new NetStream(nc);
  34.             ns.client = new Object();
  35.             myVideo.attachNetStream(ns);
  36.             ns.play("green-screen.flv");
  37.  
  38.            
  39.             [Embed(source="colorkey.pbj", mimeType="application/octet-stream")]
  40.             var Filter:Class;
  41.             shader = new Shader(new Filter());
  42.            
  43.             updateFilter();
  44.            
  45.         }
  46.  
  47.  
  48.        
  49.         private function updateFilter():void {
  50.            
  51.             // set threshold (pixel bender filter parameter)
  52.             shader.data.threshold.value = [mySlider.value];
  53.            
  54.             // set key color (pixel bender filter parameter)           
  55.             shader.data.keyColor.value = [mySliderR.value, mySliderG.value, mySliderB.value];   
  56.            
  57.             // new shaderFilter
  58.             shaderFilter = new ShaderFilter();
  59.             shaderFilter.shader = shader;
  60.            
  61.             // apply filter
  62.             if (myCheckBox.selected == true) {
  63.                 myUIComponent.filters = [shaderFilter];
  64.             }
  65.             else {
  66.                 myUIComponent.filters = null;
  67.             }
  68.         }      
  69.  
  70.  
  71.  
  72.         ]]>
  73.  
  74.     </mx:Script>
  75.  
  76.  
  77.     <mx:HBox>
  78.        
  79.  
  80.         <mx:Panel title="Color keying with Pixel Bender" width="300" height="180"
  81.             headerColors="[0xc6d381, 0xc6d381]" paddingLeft="10" paddingTop="10" id="myParamPanel">
  82.  
  83.             <mx:HBox>   
  84.                 <mx:Label text="Threshold"/>
  85.                 <mx:HSlider id="mySlider" value="0.2" maximum="1.0" minimum="0.0" thumbRelease="updateFilter();" />
  86.             </mx:HBox>
  87.  
  88.             <mx:HBox>
  89.                 <mx:Label text="R"/>
  90.                 <mx:HSlider id="mySliderR" value="0.37" maximum="1.0" minimum="0.0" thumbRelease="updateFilter();"  />
  91.             </mx:HBox>
  92.            
  93.             <mx:HBox>
  94.                 <mx:Label text="G"/>
  95.                 <mx:HSlider id="mySliderG" value="0.52" maximum="1.0" minimum="0.0" thumbRelease="updateFilter();"  />
  96.             </mx:HBox>
  97.            
  98.             <mx:HBox>
  99.                 <mx:Label text="B"/>
  100.                 <mx:HSlider id="mySliderB" value="0.25" maximum="1.0" minimum="0.0" thumbRelease="updateFilter();"  />
  101.             </mx:HBox>
  102.                
  103.             <mx:HBox>
  104.                 <mx:CheckBox id="myCheckBox" label="Color key active" selected="true" change="updateFilter();" />
  105.             </mx:HBox> 
  106.                
  107.         </mx:Panel>
  108.  
  109.  
  110.     </mx:HBox>
  111.    
  112.     <mx:VBox>
  113.         <mx:UIComponent id="myUIComponent" width="400" height="300" />
  114.         <mx:Button click="ns.pause()" label="Pause video"/>  
  115.         <mx:Button click="ns.resume()" label="Continue video"/> 
  116.         <mx:Button click="ns.seek(0);" label="Reset video"/>
  117.     </mx:VBox>
  118.  
  119.    
  120. </mx:Application>

Link: Beispiel anschauen