วันจันทร์ที่ 17 ตุลาคม พ.ศ. 2554

บันทึกภาพวิดีโอด้วย Flash Media Server

การบันทึกภาพวิดีโอลง Harddisk ที่เป็น localhost มีเครื่องมีอให้เลือกใช้หลายตัวไม่ว่าจะเป็น FMS หรือ Red5 ซึ่งทั้ง 2 นี้เป็น server ที่ทำหน้าที่ในการบันทึกภาพวิดีโอลงบนเครื่องของคุณนั่นเอง แต่สำหรับบทความนี้ผู้เขียนขอเขียนเกี่ยวกับการเขียนร่วมกับ Flash Media Server ครับ ซึ่ง FMS มีหน้าที่ในการเข้ารหัสภาพจากกล้อง Webcam ของเราในรูปแบบของไฟล์ .flv โดยผ่าน Protocal Real-Time Messaging Protocol (RTMP) และทำการบันทึกลงบนแฟ้มที่เราตั้งค่าไว้ ซึ่งเราสามารถเขียนโปรแกรมเพื่อควบคุมการทำงานด้วย Flash Actionscript 2.0 หรือ Actionscript 3.0 ก็ได้ครับ


หลังจากติดตั้ง Flash Media Server เราต้อง Start การทำงานของ FMS ให้เริ่มทำ connection ก่อนครับ (ดังภาพ)



ก่อนเริ่มเขียนโปรแกรมบันทึกเราต้องทำการ config ค่าของ FMS ก่อน

เริ่มต้นการเขียนโปรแกรมกันเลยครับ

ขั้นแรกเราต้องทำการสร้าง Class NetConnect เพื่อเชื่อมต่อระหว่าง Client กับ Server หลังจากนั้นสร้าง Class NetStream มาใช้งาน ซึ่ง NetStream จะเป็น Class ที่ดูแลการส่ง stream ข้อมูลระหว่าง Server และ Client ครับ

import flash.net.netstream;
import flash.net.NetConnection;


var nc:NetConnection = new NetConnection;
nc.connect(rtmp://localhost:1935/sample);
var ns:NetStream = new NetStream(nc);

เมื่อสร้าง NetConnection Class และ NetStream เรียบร้อยแล้ว เราก็เริ่มเชื่อมต่อกล้อง Webcam ครับ

var cam:Camera = Camera.get();
ns.attachVideo(cam);

ทำการเรียกไมโครโฟนเพื่อนำเสียงมาบันทึกครับ

var mic:Microphone = Microphone.get();
ns.attachAudio(mic);

เมื่อเราเรียก class ทั้งหมดเรียบร้อยแล้วเราจึงเขียนเพื่อประกอบกับ Application ที่เราได้ออกแบบไว้ โดยเป็นดังนี้ครับ



กล่าวโดยสรุป ในบทความนี้กล่าวถึงขั้นตอนการสร้างโปรแกรมเบื้องต้นเพื่อทำงานทางฝั่ง Client และกระบวนการแลกเปลี่ยนข้อมูลระหว่าง Flash Media Server กับ Client ซึ่งเขียนด้วยโปรแกรม Flash เพื่อสามารถสร้างกราฟฟิกได้อย่างสวยงาม โดยเริ่มต้นจากการสร้าง function บน Flash Media Server เพื่อรับข้อมูลจาก client แล้วนำมาประมวลผล ส่งผลลัพธ์กลับไปยัง client ซึ่งต้องมี function หรือ Responder มารองรับ และการติดต่อและการแลกเปลี่ยนข้อมูลต่าง ๆ ต้องอาศัย NetConnection เป็นตัวจัดการ  ขั้นตอนต่อไปเราจะเริ่มทำการเขียนเพื่อเรียกไฟล์วิดีโอแนะนำการใช้งานขึ้นมาปรากฏครับ

การเรียกไฟล์วิดีโอขึ้นมาแสดง

ขั้นตอนแรกคือการสร้าง Class NetConnection และ Class NetStream เหมือนกับการเขียนเพื่อบันทึกภาพครับ

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
videoPlayer.attachVideo(ns);

ขั้นตอนที่สอง เรียกไฟล์ .flv ที่เราตัดต่อไว้เพื่อมาแสดงครับ

ns.play("externalVideo.flv");

ขั้นตอนสุดท้ายคือการตรวจสอบการว่าวิดีโอจบหรือยังเพื่อที่จะไปยังหน้าต่อไป

if(myMovie._currentframe == myMovie._totalframes){
//Do something
}

วันอาทิตย์ที่ 29 พฤษภาคม พ.ศ. 2554

Multitouch Screen ราคาถูกครับ

เมื่อประมาณเดือนตุลาคมปีที่แล้ว (2553) ผู้เขียนได้มีโอกาสเข้านั่งชมบริษัทเข้ามานำเสนอเทคโนโลยีใหม่ๆที่นำเข้ามาในเมืองไทย เพื่อใช้ประโยชน์ในการนำเสนอข้อมูลต่างๆ ไม่ว่าจะเป็นในรูปแบบวิดีโอหรือภาพถ่าย ซึ่งมีหลากหลายรูปแบบ แต่ที่ผู้เขียนสนใจมากที่สุดก็คือ จอ Multitouch Screen ที่มีหลากหลายรูปแบบ ไม่ว่าจะเป็น Wall Multitouch Screen หรือ Table Multitouch Screen แต่เมื่อสอบถามบริษัทที่นำเข้ามาก็ได้คำตอบว่า ราคาของจอตัวนี้ค่อนข้างสูง เป็นหลักหลายแสนเลยทีเดียว



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



เมื่อลองศึกษาอย่างละเอียดแล้วเห็นว่าเราสามารถทำได้ด้วยการใช้อุปกรณ์ที่หาได้ในบ้านเราเกือบทั้งหมด ยกเว้นเพียงหลอด IR ที่มีความเข้มของแสงที่สูงซึ่งไม่มีขายในบ้านเราครับ จึงจำเป็นต้องสั่งจากต่างประเทศเพียงอย่างเดียว แต่โดยรวมแล้วราคาก็ถือว่าย่อมเยาว์กว่า การนำเข้าจอจากต่างประเทศมาก ซึ่งราคาไม่น่าจะเกิน 8 หมื่นบาท (ขึ้นอยู่กับขนาดของจอที่ต้องการ) ผู้เขียนจะขออธิบายหลักการทำงานคราวๆของระบบนี้ให้เข้าใจก่อนนะครับเพื่อให้เข้าใจว่ามันจะทำงานอย่างไร หลักการคร่าวๆก็คือ เราจะใช้หลอด IR LED ฉายรอบๆแผ่นอะคลิลิคใส 2 แผ่นที่ประกบกันเพื่อให้เกิดการสะท้อนแสงภายในแผ่นอะคลิลิคใสและเมื่อเกิดการกดลงบนแผ่นอะคลิลิค จะเกิดการหักเหของแสงที่กระจัดกระจายซึ่งจะทำให้นิ้วของเราเกิดการเรืองแสงขึ้นที่นิ้วที่สัมผัสซึ่งเราจะเห็นการเรืองแสงได้เมื่อจับด้วยกล้อง และด้านล่างของแผ่นอะคลิลิคใสเราจะจับการสัมผัสหรือการเรืองแสงด้วยกล้อง PS3Eye ซึ่งเรานำมาดัดแปลงให้จับได้เฉพาะแสง IR เท่านั้น โดยเราจะถอด IR block filter ออกจากกล้อง PS3Eye ซึ่งวิธีการดัดแปลงดังกล่าวจะกล่าวถึงต่อไปครับ เมื่อมีการสัมผัสบนแผ่นอะคลิลิคใสและกล้องสามารถจับภาพของการสัมผัสได้แล้วนั้น เราจะใช้โปรแกรม CCV เพื่อการคำนวนและบอกตำแหน่งของการสัมผัส ซึ่งโปรแกรมดังกล่าวสามารถเชื่อมโยงกับโปรแกรมที่เราเขียนด้วย Flash Builder หรือภาษา C เพื่อเป็นโปรแกรมสำหรับนำเสนอครับ หลังจากที่ศึกษาทำให้ทราบได้ว่าอุปกรณ์ที่เราจำเป็นต้องใช้ในการทำ มีดังนี้ครับ




1. หลอด IR LED 5V 100mA

2. แผ่นปริ้นไข่ปลา

3. แผ่นอะคลิลิคใสขนาดเท่ากันจำนวน 2 แผ่น
4. สติ๊กเกอร์ขุ่น ขนาดเท่ากับแผ่นอะคลิลิค จำนวน 1 แผ่น


5. กล้อง Webcam PS3Eye
6. คอมพิวเตอร์

7. Projector
8. Program CVV

หลังจากที่ได้อุปกรณ์ทั้งหมดครบแล้ว เราก็เริ่มทำการประกอบ IR LED เข้ากับปริ้นไข่ปลาเลยครับโดยสถานที่ที่จะติดตั้งจะเป็นห้องกระจก ซึ่งเราจะติดตั้งจอของเรากับกระจกขนาด 135 cm X 110 cm ครับ เมื่อประกอบและบัดกรีเสร็จจะเป็นไปตามภาพข้างล่างนี้ครับ




ทดสอบการจ่ายไฟเข้าหลอด IR LED ที่ติดตั้งแล้ว



นำเอาสติ๊กเกอร์ขุ่นติดกับแผ่นอะคลิลิคใสที่เตรียมไว้โดยจะต้องติดหลังสุดของแผ่นอะคลิลิค ซึ่งแผ่นสติ๊กเกอร์ใสจะทำหน้าที่เป็นฉากรับภาพของ Projector ดังแสดงให้เห็นจากแผนผังดังภาพนี้ครับ และติดตั้งบนกระจกในสถานที่จริงได้เลยครับ



แต่จากภาพข้างบนจะเห็นว่า ต้องมีชั้นของ Silicone และ Diffuser เพิ่มขึ้นมา แต่จากที่ผู้เขียนได้ทดลองดูแล้วนั้น ทั้งสองชั้นนี้ไม่จำเป็นต้องใช้ครับ


นำเอา IR LED ที่ประกอบกับปริ้นไข่ปลาเรียบร้อยแล้ว จึงนำไปติดตั้งไว้รอบๆแผ่นอะคลิลิค 2 แผ่นที่ประกบกันให้เป็นที่เรียบร้อยครับ



เมื่อเราติดตั้งแผ่นอะคลิลิคและหลอด IR LED เรียบร้อยแล้ว ขั้นตอนต่อไปคือ การดัดแปลงกล้อง PS3Eye Webcam เพื่อเอา IR block filter ออก เพื่อให้กล้องสามารถจับแสง IR เมื่อเราทำการสัมผัสบนแผ่นอะคลิลิคครับ โดยวิธีการถอดจะเป็นดังขั้นตอนตามวิดีโอข้างล่างนี้ครับ


หลังจากที่ถอด IR block filter  แล้วนั้น เราจะทำการติดตั้ง Bandpass filter เข้าไปในกล้องครับ Bandpass filter มีหน้าที่ตัดแสงของ Projector ที่จะสะท้อนมารบกวนแสง IR ที่เกิดจากการสัมผัสบนแผ่นอะคลิลิค โดยปกติแล้ว Bandpass filter จะมีจำหน่ายในลักษณะของเลนส์ แต่มีราคาสูงมาก ซึ่งถ้าชมจากวิดีโอต่อไปนั้นจะเห็นได้ว่าเค้าจะนำแผ่นเก็บข้อมูลของ Floppy disk มาใช้แทน ซึ่งแผ่นข้อมูล Floppy Disk ดังกล่าวจะมีประสิทธิภาพใกล้เคียงกับเลนส์กรองแสงที่มีราคาสูงมาก และยังหาง่ายจึงเป็นที่นิยมในการนำมาใช้ทดแทน Bandpass filter แบบเลนส์ที่มีราคาสูงครับ


เมื่อเราทำการ Modify กล้องเรียบร้อยแล้ว ขั้นตอนต่อไปเราก็จะทำการตั้งค่าการมองเห็นของโปรแกรม CCV กันเลยครับ
ตัวโปรแกรม CCV หรือที่เรียกกันว่า TBeta หน้าตาจะเป็นอย่างนี้ครับ


อันนี้เป็นผลงานที่สำเร็จแล้วครับ



ครั้งหน้าจะเป็นเรื่องของการทำ Multitouch Screen แบบโต๊ะ โดยใช้จอ LCD มาโมดิฟาย ซึ่งจะออกมาประมาณวิดีโอนี้ครับ


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


วันพุธที่ 11 พฤษภาคม พ.ศ. 2554

เริ่มต้นกับงาน Augmented Reality

อ่านตามหนังสือเกี่ยวกับเทคโนโลยีของเมืองนอกหลายๆเล่ม เห็นเค้าว่า AR (Augmented Reality) กำลังมาแรงในช่วงนี้ เลยอยากลองทำดูว่ามันเป็นยังงัยน้า...มันเจ๋งจริงหรือเปล่าแล้วมันเจ๋งยังงัย เริ่มแรกก็เลยไปหาดู Youtube ก่อนว่าเป็นยังงัยกับเจ้า AR เนี่ยก็พอได้พอเห็นภาพลางๆว่ามันใช้ประโยชน์อะไร ซึ่ง AR มันก็คือการจะลองภาพจากจิตนาการมาให้เราเห็นในรูปแบบ 3D หรือวิดีโอ หรืออะไรก็ได้ที่ให้ผู้ชมได้เห็นภาพชัดเจนยิ่งขึ้นนั่นเอง อย่างเช่นตัวอย่างของ Lego ครับ เค้านำ AR มาใช้เพื่อให้ลูกค้าที่สนใจสินค้าของ Lego ได้เห็นตัวต่อข้างในก่อนเมื่อต่อเสร็จแล้วในรูปแบบของ 3D ที่สามารถหมุนดูได้รอบตัวทุกซอกทุกมุม เพื่อให้ลูกค้าที่เลือกซื้อสามารถเห็นสินค้าโดยที่ไม่ต้องแกะกล่อง แถมยังลด Cost ของทาง Lego เองที่ไม่ต้องนำตัวอย่างไปตั้ง ณ จุดขายให้เปลืองสตางค์ ซึ่ง Lego จะมีบริการเหล่านี้ ณ จุดขาย Lego ตามห้างต่าง (ไม่รู้ว่าบ้านเราจะมีรึยัง เพราะผมไม่ค่อยได้เดินห้างฯเท่าไหร่ ^^)



วิดีโอตัวอย่างของ Lego ครับ

หลังจากที่ได้ลองหาตัวอย่าง Sourcecode ตามเว็บไซด์ต่างๆที่เขียนด้วย Flex ดูแล้ว ก็พบว่าหลายๆตัวอย่างเช่นของ Saqoocha ก็พบว่า Starter Kid ซึ่งมันจะแสดงผลได้เพียง 1 Marker ต่อ 1 การแสดงผล เท่านั้น ซึ่ง Sourcecode ที่ได้มาก็จะเป็นประมาณนี้ครับ


package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Camera;
import flash.media.Video;
import flash.ui.Mouse;
import org.ascollada.*;
import org.ascollada.namespaces.collada;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.utils.Mouse3D;
import org.papervision3d.events.FileLoadEvent;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.render.LazyRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.view.stats.StatsView;

//import org.libspark.flartoolkit.core.param.FLARParam;

[SWF(width=640, height=480, backgroundColor=0x808080, frameRate=25)]
public class Earth extends PV3DARApp {
private var stats:StatsView;
private var renderer:LazyRenderEngine;
private var viewport:Viewport3D;
private var cam:Camera3D;
private var scene:Scene3D;
private var webcam:Camera
private var video:Video

//private var _earth:Collada;
private var _earth:DAE;
public function Earth() {
addEventListener(Event.INIT, _onInit);
init('Data/camera_para.dat', 'Data/flarlogo.pat');
//this.cameraParamFile = 'data/camera_para.dat';
//this.markerPatternList = new Vector.<FLARCode>();
//this.markerPatternFileList = new Vector.<String>();
//this.markerPatternFileList.push('data/flarlogo.pat','data/NECTEC.pat','Papervision.pat');
//_raster = new FLARRgbRaster_BitmapData(_capture.bitmapData);

}
private function _onInit(e:Event):void
{
_earth = new DAE();
_earth.load('model/earth.dae');
_earth.scale = 50;
_earth.rotationX = -270;
_earth.rotationZ = 180;
_markerNode.addChild(_earth);
//addEventListener(Event.ENTER_FRAME, _update); 
_earth.addEventListener(MouseEvent.MOUSE_OVER, _update);
}

private function _update(Event:MouseEvent):void {
_earth.rotationZ -= 0.5
}
}
}




จาก Sourcecode ที่แสดงข้างบนจะเห็นได้ว่า Application จะ init กล้อง 1 ตัว กับ Pattern 1 Marker เท่านั้น จะเป็นดังวิดีโอข้างล่างนี้ครับ

 


ซึ่ง Sourcecode ที่หามาได้ยังไม่ตรงกับจุดประสงค์ที่ต้องการเท่าไหร่เพราะหากเราต้องการที่จะแสดงผลแบบ Multimarker (หลาย Marker ต่อ 1 การแสดงผล) หรือ หลาย Marker ต่อ หลายการแสดงผล ก็จำเป็นต้องเขียนเพิ่มเติมนิดหน่อย ซึ่งจะมีให้ชมในตอนต่อไปนะครับ