2012年9月26日 星期三

[教學] Panorama 全景圖實作

日本的Spark project 為Action Script 開發人員提供大量程式庫. 其中AlternativaTemplate 編寫的Camera 操作控制, 能簡單實作全景圖, 並透過Alternativa3D 運行Stage3D 硬體加速顯示.

請按 [觀看] 範例

以下是編寫的步驟:

  1. 建立一個新類別並繼承AlternativaTemplate 類別
  2. 設定CameraCameraType.PANORAMA 模式
  3. 設定紋理材料(TextureMaterial) 為內嵌的全景圖像(assets/test1.jpg)
  4. 建立一個幾何球體(GeoSphere) 並貼上紋理材料
package
{
  import alternativa.engine3d.materials.TextureMaterial;
  import alternativa.engine3d.primitives.GeoSphere;
  import alternativa.engine3d.resources.BitmapTextureResource;
  
  import org.libspark.alternativa3d.camera.CameraType;
  import org.libspark.alternativa3d.view.AlternativaTemplate;
  
  [SWF(backgroundColor="#000000", frameRate="60", quality="LOW", width="800", height="480")]
  public class Alternativa_Panorama extends AlternativaTemplate
  {
    [Embed(source = "assets/test1.jpg")]
    private static var ImageCls:Class;
    
    public function Alternativa_Panorama():void{
      super({
        cameraType:CameraType.PANORAMA,
        useDiagram : true
      });
    }
    override protected function atInit():void{
      var material:TextureMaterial = new TextureMaterial(new BitmapTextureResource(new ImageCls().bitmapData));
      var shpere:GeoSphere = new GeoSphere(100, 32, true, material);
      scene.addChild(shpere);
    }
  }
} 
在Android 和iOS 運作正常, 大家可以 [下載] 範例試試看.

參考資料: http://clockmaker.jp/blog-en/2011/11/alternativa3d-panorama/

2012年9月24日 星期一

SpriteSheetClip 的高效能渲染

關於2D 渲染部分, 我們大多選擇以Stage3D 為基礎的Starling 圖像引擎, 其效能必然是最好. 若大家希望簡單製作, 又要求達到一個理想的渲染效果, SpriteSheetClip 相信是個好選擇, 它比傳統MovieClip 效能高很多.


SpriteSheetClip 運作原理十分簡單, 它是繼承Bitmap 類別, 建立時記錄Sprite Sheet 的內容. 當播放時更換相對的BitmapData 內容, 達到連續播放效果.

請按 [觀看] 範例
以下是使用方法:
  1. 準備一份Sprite Sheet 格式檔案的PNG 與JSON:
    [Embed("assets/Animation.png")]
    public var AnimationImage:Class;
     
    [Embed("assets/Animation.json", mimeType="application/octet-stream")]
    public var AnimationData:Class;
    

  2. 透過SpriteSheetClip 產生實體:
    var mc:SpriteSheetClip = new SpriteSheetClip(AnimationImage, AnimationData);
    mc.gotoAndPlay("someLabel");
    this.addChild(mc);
    

  3. 設定實體位置(x, y), 縮放(scaleX, scaleY), 旋轉(rotation) 或透明度(alpha):
    mc.x = 10;
    mc.y = 10;
    mc.scaleX = 0.5;
    mc.scaleY = 0.5;
    mc.rotation = 90;
    mc.alpha = 0.8;
    

  4. Event.ENTER_FRAME 呼叫step() 功能, 手動觸發播放:
    this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    ...
    function onEnterFrame(event:Event):void {
          mc.step();
    }

在沒有Stage3D 硬體加速幫助下, 純粹更換BitmapData 能給出高效能渲染, 這個既簡單又實用的手法, 確實令人驚訝喔.

參考資料: http://blog.domlib.com/articles/291

後記:
由於SpriteSheetClip 依賴Zoe 產生相關的PNG 與JSON. 若Zoe 產生內容有所更改, SpriteSheetClip 需要作出相應的改動, 它們之間沒有統一的標準.

2012年9月21日 星期五

[教學] AIRKinect 的魔法帽子

Kinect 與Flash 的連接, 我們透過AIRKinect (安裝參考)簡單地完成. 以下為大家介紹魔法帽子範例, 當一個人走進Kinect 範圍, 在螢幕為她蓋上一個魔法帽子.


  1. 在程序啟動時, 對AIRKinect 物件加入三個事件監聽器:
      CameraImageEvent.RGB_IMAGE_UPDATE - 影像每次更新產生的事件
      UserEvent.USERS_WITH_SKELETON_ADDED - 發現一個新骨架時事件
      UserEvent.USERS_WITH_SKELETON_ADDED - 骨架離開Kinect 事件
    if (Kinect.isSupported()) {
      // <----- get Kinect instance
      _device = Kinect.getDevice();
      
      // <----- add listener for Kinect
      _device.addEventListener(CameraImageEvent.RGB_IMAGE_UPDATE, rgbImageUpdateHandler, false, 0, true);
      _device.addEventListener(UserEvent.USERS_WITH_SKELETON_ADDED, skeletonsAddedHandler, false, 0, true);
      _device.addEventListener(UserEvent.USERS_WITH_SKELETON_REMOVED, skeletonsRemovedHandler, false, 0, true);
      
      ...
      
      // <----- start the Kinect
      _device.start(settings);
    }
    

  2. 當發現一個新骨架, 我們建立一個帽子MovieClip, 產生魔法效果:

    帽子(_Hat1) 魔法效果是由Flash IDE 的時間軸製作
    ...
    [Embed(source="assets/hat1.swf")]
    private var _Hat1:Class;
    ...
    private function skeletonsAddedHandler(event:UserEvent):void{
      for each(var addedUser:User in event.users){
        var sprite:Sprite = new Sprite();
        var head:SkeletonJoint = addedUser.getJointByName("head");
        var headRGB:Point = head.position.rgb;
        sprite.name = addedUser.trackingID.toString();
        sprite.x = headRGB.x;
        sprite.y = headRGB.y;
        
        // <----- add the MovieClip to stage
        sprite.addChild(new _Hat1() as MovieClip);
        _sprites.push(sprite);
        this.addChild(sprite);
      }
    }
    

  3. 若骨架離開Kinect, 把相對於這個骨架的帽子刪除:
    private function skeletonsRemovedHandler(event:UserEvent):void{
      for each(var removedUser:User in event.users){
        for(var i:int=0; i<_sprites.length; i++){
          var id:String = removedUser.trackingID.toString();
          if(_sprites[i].name==id){
            this.removeChild(_sprites[i]);
            _sprites.splice(i, 1);
          }
        }
      }
    }
    

  4. 影像每次更新時, 追蹤每個骨架頭部(head) 和頸部(neck) 關節位置, 計算兩者距離來決定帽子大小, 並利用TweenLite 把帽子移至頭部:

    Kinect 關節名稱
    private function rgbImageUpdateHandler(event:CameraImageEvent):void{
      // <----- get Kinect RGB Camera image to display
      _bitmapData.draw(event.imageData);
      
      for each(var user:User in _device.users) {
        if (user.hasSkeleton) {
          var head:SkeletonJoint = user.getJointByName("head");
          var neck:SkeletonJoint = user.getJointByName("neck");
          var headRGB:Point = head.position.rgb;
          var neckRGB:Point = neck.position.rgb;
          var diff:Number = Math.abs(neckRGB.y - headRGB.y);
          var diffBase:Number = 50;
          var scale:Number = diff/diffBase;
          var id:String = user.trackingID.toString();
          
          // <----- find the MovieClip
          for(var i:int=0; i<_sprites.length; i++){
            if(_sprites[i].name==id){
              // <----- change the MovieClip position
              TweenLite.to(_sprites[i], 0.1, {x:headRGB.x, y:headRGB.y, scaleX:scale, scaleY:scale});
              break;
            }
          }
        }
      }
    }
    
大家可以 [下載] 範例試試看.

後記:
微軟推出的Kinect 硬體在不同的版本, 是有不同的支援上限:
Kinect for Xbox 360 是由2009 年6 月份推出, 支援追蹤兩組骨架, 解像度640x480 @30Hz.
Kinect for Windows 是由2012 年2 月份推出, 支援追蹤四組骨架, 解像度1280x960 @30Hz.

2012年9月12日 星期三

[教學] 原生OpenCV 編譯C++ 成SWC 庫

研究Augmented Reality 的朋友, 相信對OpenCV (Open Source Computer Vision Library) 有一定認識. 她是由英特爾(Intel) 公司發起並參與開發, 以BSD 許可證授權發行, 可以在商業和研究領域中免費使用. 我們可用於開發實時的圖像處理, 計算機視覺以及模式識別程序.

wouter 編譯的OpenCV SWC 庫, 能透過讀取Cascade XML檔案辨認不同物件

現在為大家介紹如何在MAC OS X 中, 透過Adobe Alchemy (安裝參考) 編譯原生OpenCV:
  1. 我們到bonext 下載已整理的OpenCV 包. (OpenCV2.2.0 版本)
  2. 把bonext 解壓並存於/Library/bonext/ 路徑上.
  3. 在Terminal 中, 分別進入以下五個路徑:
    cd /Library/bonext/src/opencv/calib3d/
    cd /Library/bonext/src/opencv/contrib/
    cd /Library/bonext/src/opencv/core/
    cd /Library/bonext/src/opencv/imgproc/
    cd /Library/bonext/src/opencv/objdetect/

    並在每個路徑請輸入以下指命進行編譯:
    repo_root=/Library/bonext/;
    alc-on; rm -rdf log ; rm -f *.o; mkdir log ; for src in *.cpp ; do g++ -I$repo_root/include -DOSX -c -Wall -O3 -o ${PWD##*/}_`basename $src .cpp`.o $src 2> `basename $src .cpp`.log ; done ; mv -v *.log ./log ; alc-off; for f in ./log/*.log ; do grep 'error' $f ; done | cat | sort -u > ./log/errors.log ; less ./log/errors.log
  4. 若編譯正確, 會在每一個路徑找到多個.o 檔案. 把它們移至/Library/bonext/flash/ 路徑上.
  5. 根據bonext 者作提示, 我們需要刪除core_system.o 檔案.
  6. 最後, 在/Library/bonext/flash/ 路徑, 輸入以下指命編譯成.swc 檔案:
    rm *achacks* *.swc ; alc-on; g++ -swc -Wall -O3 -DOSX -I../include -o camlib.swc *.o camlib.cpp ; alc-off;
我們透過Adobe Alchermy 成功產生swc 元件, 在Flash Builder 設定swc 路徑後, 便可以使用:
package
{
  import flash.display.Sprite;
  import cmodule.camlib.CLibInit;
  
  public class Bonext_WebCam extends Sprite
  {
    private var lib:Object;
    ...
    public function setupCLib():void
    {
      ...
      // <----- create a library instance from swc
      var loader:CLibInit = new CLibInit;
      lib = loader.init();
      ...
    }
    ...
    public function enterFrameHandler(event:Event):void
    {
      ...
      // <----- call a method from swc
      var outPixels:ByteArray = lib.setFramePtr(pixels,pixels.length);
      ...
    }
    ...
  }
}

在bonext 的作者純粹示範呼叫OpenCV 使影像變成灰色. 當然我們可以修改camlib.cpp 檔案, 加入相對的函數給Action Script 調用, 發揮OpenCV 的強大功能. 大家可以 [下載] 範例試試看.

2012年9月7日 星期五

AIRKinect 怪獸

AIRKinect 配合Away3D 可以製作很多有趣事, 我們把Away3D 當中的怪獸, 配合AIRKinect 的骨架移動3D 模型, 怪獸起動來喔~~~



只要修改AIRKinect 內建範例, 把關節名稱對應為Away3D 怪獸範例的模型:
var jointMapping:Vector.<Number> = Vector.<Number>([
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("head"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("neck"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("waist"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("luparm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lloarm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lhand"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("ruparm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rloarm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rhand"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lupleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lloleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lfoot"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rupleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rloleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rfoot")
]);

大家可以 [下載] 範例試試看.

2012年9月4日 星期二

Beyond Reality Face 臉部偵測引擊

Beyond Reality Face 是一個臉部偵測引擊, 能夠實時偵測臉部輪廓. 她們提供SDK 免費下載和測試, 若開發人員於商業用途, 需要購買許可證. 雖然不是完全免費, 但作為Augmented Reality 引擊, 她是一個不錯的參考.

請按 [觀看] 範例 (需要Web Camera)

識別臉部的位置

者作把Beyond Reality Face 範例整理, 發現十分有趣, 大家可以 [下載] 範例試試看.

2012年9月2日 星期日

foxhole 元件

foxhole 是一個以Starling Framework 為基礎的元件庫, 與MadComponents 性質十分相似, 它們都是以Stage3D 技術, 在iOS 或Android 中流暢操作的UI 框架.

請按 [觀看] Layout Explorer 範例

請按 [觀看] Gallery 範例

請按 [觀看] Tile List 範例

foxhole 主要透過程式編寫來決定元件的位置與關係. 與MadComponents 的XML 設定有所不同.

API 參考: http://flashtoolbox.com/foxhole-starling/documentation/