วันอังคารที่ 17 มิถุนายน พ.ศ. 2557

ทำ Multitouch screen บนกระจก ด้วยกล้อง Kinect

เทคโนโลยีใหม่ก้าวไกลขึ้นมากครับ เราสามารถสร้างระบบการทำงานแบบ Multitouch บนกระจกได้เหมือนที่เราเคยเห็นกันในหนังแนววิทยาศาสตร์ หรือโลกอนาคต เมื่อเทคโนโลยีมีวิวัฒนาการมากขึ้นทำให้เราสามารถดัดแปลงสิ่งต่างๆมาใช้งานเพื่อให้ได้เทคโนโลยีดังกล่าวเป็นจริงขึ้นมาได้

เทคโนโลยี Multitouch บนกระจกนั้นอาศัยอุปกรณ์ต่างๆดังนี้

1. กล้อง Kinect เพื่อใช้จับการเคลื่อนไหวของมือและนิ้วขณะสัมผัสที่กระจก
2. กระจก เพื่อให้มือสัมผัส
3. เครื่อง Projector เพื่อฉายภาพบนกระจก
4. ฟิล์มหรือสติ๊กเกอร์ขุ่น 3M รุ่น 30-110 ใช้ติดกระจกเป็นฉากรับภาพจาก Projector

ส่วน Code ที่ใช้ ผู้พัฒนา พัฒนาบน Flash Builder (Flex) ดังตัวอย่าง code ข้างล่างนี้ครับ

package
{
    import flash.display.DisplayObject;
    import flash.display.Loader;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.NetStatusEvent;
    import flash.events.TimerEvent;
    import flash.geom.Rectangle;
    import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.net.URLRequest;
    import flash.text.TextField;
    import flash.utils.Timer;
   
    import flashx.textLayout.tlf_internal;
   
    import mx.flash.ContainerMovieClip;
   
    import org.osmf.events.TimeEvent;
    import org.papervision3d.view.BasicView;
   
    import tuio.*;
    import tuio.TouchEvent;
   
    [SWF(width=1280, height=720, backgroundColor=0x000000, frameRate=25)]
    public class PEA extends BasicView
    {
        private var speed:Number = .1;

        public function PEA()
        {
            TUIO.init(this,'localhost',3000,'',true);
            super();
           
            var bt01_movieClip:MovieClip = new MovieClip();
            var bt01_loader:Loader = new Loader();
            bt01_loader.load(new URLRequest("bt01_1.swf"));
            bt01_movieClip.addChild(bt01_loader);
            stage.addChild(bt01_movieClip);
            bt01_movieClip.name = "bt01";
            bt01_movieClip.x=250;
            bt01_movieClip.y=300;
            bt01_movieClip.alpha=1;

            var bt02_movieClip:MovieClip = new MovieClip();
            var bt02_loader:Loader = new Loader();
            bt02_loader.load(new URLRequest("bt01_2.swf"));
            bt02_movieClip.addChild(bt02_loader);
            stage.addChild(bt02_movieClip);
            bt01_movieClip.name = "bt02";
            bt02_movieClip.x=1030;
            bt02_movieClip.y=300;
            bt02_movieClip.alpha=1;


            bt01_movieClip.addEventListener(TouchEvent.MOUSE_OVER, bt01_TouchOver);
            bt01_movieClip.addEventListener(TouchEvent.MOUSE_OUT, bt01_TouchOut);
            bt01_movieClip.addEventListener(TouchEvent.MOUSE_MOVE, bt01_TouchMove);
           
            bt02_movieClip.addEventListener(TouchEvent.MOUSE_OVER, bt02_TouchOver);
            bt02_movieClip.addEventListener(TouchEvent.MOUSE_OUT, bt02_TouchOut);
            bt02_movieClip.addEventListener(TouchEvent.MOUSE_MOVE, bt02_TouchMove);
           
            //////////////BT_01////////////////////
           
            //////////////BT Drag////////////////////
            function bt01_TouchMove(event:TouchEvent):void {
                bt01_movieClip.x = event.stageX;               
            }
            //////////////BT Drag////////////////////
           
            function bt01_TouchOver(event:TouchEvent):void {
                addEventListener(Event.ENTER_FRAME, bt01_loop_Over);
                removeEventListener(Event.ENTER_FRAME, bt01_loop_Out);

            }
           
            function bt01_loop_Over(e:Event) : void
            {
               
               
                if(bt01_movieClip.alpha<1)
                {
                    bt01_movieClip.alpha += speed;
                }
               
                if(bt01_movieClip.scaleX<1.2)
                {
                    bt01_movieClip.scaleX += speed;
                    bt01_movieClip.scaleY += speed;
                }
               
                //////////////BT Drag////////////////////

                if(bt01_movieClip.x>300){
                    bt01_movieClip.x=300;
                    bt01_movieClip.alpha = 1;
                }
                if(bt01_movieClip.x>=300&&bt02_movieClip.x<=800){
                    stage.removeChild(bt01_movieClip);
                    stage.removeChild(bt02_movieClip);
                   
                    video1();
                }

                //////////////BT Drag////////////////////

            }

            function bt01_TouchOut(event:TouchEvent):void {
                removeEventListener(Event.ENTER_FRAME, bt01_loop_Over);
                addEventListener(Event.ENTER_FRAME, bt01_loop_Out);
            }
           
            function bt01_loop_Out(e:Event) : void
            {
                bt01_movieClip.alpha = 1;
                bt01_movieClip.scaleX = 1;
                bt01_movieClip.scaleY = 1;
               
            }
           
           
           
            //////////////BT_02////////////////////
           
            //////////////BT Drag////////////////////           
            function bt02_TouchMove(event:TouchEvent):void {
                bt02_movieClip.x = event.stageX;
            }
            //////////////BT Drag////////////////////
           
            function bt02_TouchOver(event:TouchEvent):void {
                addEventListener(Event.ENTER_FRAME, bt02_loop_Over);
                removeEventListener(Event.ENTER_FRAME, bt02_loop_Out);
            }
           
            function bt02_loop_Over(e:Event) : void
            {
               
                if(bt02_movieClip.alpha<1)
                {
                    bt02_movieClip.alpha += speed;
                }
               
                if(bt02_movieClip.scaleX<1.2)
                {
                    bt02_movieClip.scaleX += speed;
                    bt02_movieClip.scaleY += speed;
                }
                //////////////BT Drag////////////////////

                if(bt02_movieClip.x<800){
                    bt02_movieClip.x=800;
                    bt02_movieClip.alpha = 1;
                }
                if(bt01_movieClip.x>=300&&bt02_movieClip.x<=800){
                    stage.removeChild(bt01_movieClip);
                    stage.removeChild(bt02_movieClip);
                   
                    video1();
                }

                //////////////BT Drag////////////////////
            }
            function bt02_TouchOut(event:TouchEvent):void {
                removeEventListener(Event.ENTER_FRAME, bt02_loop_Over);
                addEventListener(Event.ENTER_FRAME, bt02_loop_Out);

            }
           
            function bt02_loop_Out(e:Event) : void
            {
                bt02_movieClip.alpha = 1;
               
                bt02_movieClip.scaleX = 1;
                bt02_movieClip.scaleY = 1;
            }
           
           
            //////////////Video 1////////////////////
           
            function video1() : void
            {
                bt01_movieClip.removeEventListener(TouchEvent.MOUSE_OVER, bt01_TouchOver);
               
                var video1:Video = new Video(1280, 720);
                stage.addChild(video1);
           
                var nc_video1:NetConnection = new NetConnection();
                nc_video1.connect(null);
           
                var ns_video1:NetStream = new NetStream(nc_video1);
                video1.attachNetStream(ns_video1);
           
                ns_video1.play("video/video1.f4v");
               
                ns_video1.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
               
           
                function netStatusHandler(event:NetStatusEvent):void {
                   
                    if (event.info.code == "NetStream.Play.Stop")
                    {
                       
                        stage.removeChild(video1);
                        ns_video1.close();
                        nc_video1.close();
                       
                        iPhone_Slider();
                    }
                }
            }
           
            //////////////Video 1////////////////////
           
            //////////////Section 2 iPhone////////////////////
           
            function iPhone_Slider() : void
            {
                var SliderBT_movieClip:MovieClip = new MovieClip();
                var SliderBT_loader:Loader = new Loader();
                SliderBT_loader.load(new URLRequest("iPhone_Slider_02.swf"));
                SliderBT_movieClip.addChild(SliderBT_loader);
                stage.addChild(SliderBT_movieClip);
                SliderBT_movieClip.x=350;
                SliderBT_movieClip.y=350;
                stage.addChildAt(SliderBT_movieClip , 1);
               
                var SliderBG_movieClip:MovieClip = new MovieClip();
                var SliderBG_loader:Loader = new Loader();
                SliderBG_loader.load(new URLRequest("iPhone_Slider_BG.swf"));
                SliderBG_movieClip.addChild(SliderBG_loader);
                stage.addChild(SliderBG_movieClip);
                stage.addChildAt(SliderBG_movieClip , 0);
               
                SliderBT_movieClip.addEventListener(TouchEvent.MOUSE_OVER, SliderBT_TouchOver);
                SliderBT_movieClip.addEventListener(TouchEvent.MOUSE_MOVE, SliderBT_TouchMove);
               
                function SliderBT_TouchMove(event:TouchEvent):void {
                    SliderBT_movieClip.x = event.stageX;               
                }
               
                function SliderBT_TouchOver(event:TouchEvent):void {
                    addEventListener(Event.ENTER_FRAME, SliderBT_loop_Over);
                   
                }
               
                function SliderBT_loop_Over(e:Event) : void
                {
                    if(SliderBT_movieClip.x>740){
                        SliderBT_movieClip.x=920;
                    }
                    if(SliderBT_movieClip.x==920){
                        stage.removeChild(SliderBT_movieClip);
                        stage.removeChild(SliderBG_movieClip);
                        video2();
                    }
                }
               
                function SliderBT_TouchOut(event:TouchEvent):void {
                    SliderBT_movieClip.x=350;
                    SliderBT_movieClip.y=350;
                }
               
            }
               
            //////////////Section 2 iPhone////////////////////
           
           
           
            //////////////Video 2////////////////////
           
            function video2() : void
            {
                var video2:Video = new Video(1280, 720);
                stage.addChild(video2);
               
                var nc_video2:NetConnection = new NetConnection();
                nc_video2.connect(null);
               
                var ns_video2:NetStream = new NetStream(nc_video2);
                video2.attachNetStream(ns_video2);
               
                var listener_video2:Object = new Object();
                listener_video2.onMetaData = function(evt:Object):void {};
                ns_video2.client = listener_video2;
               
                ns_video2.play("video/video2.f4v");
               
                ns_video2.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler2);
               
                function netStatusHandler2(evt:NetStatusEvent):void {
                    if (evt.info.code == "NetStream.Play.Stop")
                    {
                        stage.removeChild(video2);
                        ns_video2.close();
                        nc_video2.close();
                       
                        line_Touch();
                    }
                }
            }
           
            //////////////Video 2////////////////////
           
            //////////////Section 3 Line////////////////////
           
            function line_Touch() : void
            {
                var Line_movieClip:MovieClip = new MovieClip();
                var Line_loader:Loader = new Loader();
                Line_loader.load(new URLRequest("Line_screen.swf"));
                Line_movieClip.addChild(Line_loader);
                stage.addChild(Line_movieClip);
                Line_movieClip.x = 400;
                stage.addChildAt(Line_movieClip , 0);
               
                var LineTimer:Timer = new Timer(2000, 6);
               
               
               
                Line_movieClip.addEventListener(TouchEvent.MOUSE_OVER, Line_TouchOver);
               
                function Line_TouchOver(event:TouchEvent):void {
                   
                    LineTimer.start();
                    LineTimer.addEventListener(TimerEvent.TIMER, Line_timerHandler);
                    LineTimer.addEventListener(TimerEvent.TIMER_COMPLETE, Line_timerHandler_Complete);
                       
                    var count5_loader:Loader = new Loader();
                    count5_loader.load(new URLRequest("count/5.jpg"));
                    count5_loader.x = 650;
                    count5_loader.y = 170;
                   
                    var count4_loader:Loader = new Loader();
                    count4_loader.load(new URLRequest("count/4.jpg"));
                    count4_loader.x = 650;
                    count4_loader.y = 170;
                   
                    var count3_loader:Loader = new Loader();
                    count3_loader.load(new URLRequest("count/3.jpg"));
                    count3_loader.x = 650;
                    count3_loader.y = 170;
                   
                    var count2_loader:Loader = new Loader();
                    count2_loader.load(new URLRequest("count/2.jpg"));
                    count2_loader.x = 650;
                    count2_loader.y = 170;
                   
                    var count1_loader:Loader = new Loader();
                    count1_loader.load(new URLRequest("count/1.jpg"));
                    count1_loader.x = 650;
                    count1_loader.y = 170;
                       
                        function Line_timerHandler(e:TimerEvent):void {
                           
                           
                            var myText:TextField = new TextField();
                            myText.text = e.currentTarget.currentCount;
                            addChild(myText);
                           
                            myText.border = true;
                            myText.width = 150;
                            myText.height = 40;
                           
                            if(myText.text=="1"){
                                stage.addChild(count5_loader);
                            }
                            else if(myText.text=="2"){
                                stage.removeChild(count5_loader);
                                stage.addChild(count4_loader);
                            }
                            else if(myText.text=="3"){
                                stage.removeChild(count4_loader);
                                stage.addChild(count3_loader);
                            }
                            else if(myText.text=="4"){
                                stage.removeChild(count3_loader);
                                stage.addChild(count2_loader);
                            }
                            else if(myText.text=="5"){
                                stage.removeChild(count2_loader);
                                stage.addChild(count1_loader);
                            }
                           
                        }
                        function Line_timerHandler_Complete(e:TimerEvent):void {
                            LineTimer.stop();
                            stage.removeChild(count1_loader);
                            stage.removeChild(Line_movieClip);
                            video3();
                        }
                }
               
            }
           
            //////////////Section 3 Line////////////////////
           
            //////////////Video 3////////////////////
           
            function video3() : void
            {
                var video3:Video = new Video(1280, 720);
                stage.addChild(video3);
               
                var nc_video3:NetConnection = new NetConnection();
                nc_video3.connect(null);
               
                var ns_video3:NetStream = new NetStream(nc_video3);
                video3.attachNetStream(ns_video3);
               
                var listener_video3:Object = new Object();
                listener_video3.onMetaData = function(evt:Object):void {};
                ns_video3.client = listener_video3;
               
                ns_video3.play("video/video3.f4v");
               
                ns_video3.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler3);
               
                function netStatusHandler3(evt:NetStatusEvent):void {
                    if (evt.info.code == "NetStream.Play.Stop")
                    {
                        stage.removeChild(video3);
                        ns_video3.close();
                        nc_video3.close();
                       
                    }
                }
            }
           
            //////////////Video 2////////////////////
        }
       
    }
}

Demo ของ Sourcecode ข้างบนครับ



การติดตั้งอุปกรณ์ทั้งหมดเป็นดังภาพนี้ครับ


วิดีโอตัวอย่างเมื่อติดตั้งอุปกรณ์ทั้งหมดเรียบร้อยแล้วครับ

รับทำ Air Multitouch (จอสัมผัสบนอากาศ สามารถสัมผัสได้พร้อมกันหลายคน) โดยใช้กล้อง Kinect เป็นตัวจับการเคลื่อนไหว สามารถเขียนส่วนติดต่อกับผู้ใช้งาน (User Interface) ได้ตามที่ต้องการ สนใจติดต่อ 08-1874-9168 กอล์ฟ