Sunday, April 12, 2015

เริ่มต้นกับ Kinect ด้วย C#

มี Kinect รุ่นแรกอยู่ในมือนานมากล่ะครับ ได้โอกาสเขียนโปรแกรมเล่นกับ Kinect แล้ว

สิ่งที่ต้องการ
1. KinectSDK ซึ่งถ้าใช้กับอุปกรณ์ Kinect รุ่นแรก ตัว SDK รุ่นล่าสุดจะเป็นรุ่น 1.8 ซึ่งดาวน์โหลดได้จาก http://www.microsoft.com/en-us/download/details.aspx?id=40278 จะได้ไฟล์ชื่อ KinectSDK-v1.8-Setup.exe มา ซึ่งใช้ได้กับทั้ง 32 และ 64 bits ครับ

2. Kinect for Windows Developer Toolkit (จะโหลดหรือไม่ก็ได้) ถ้าต้องการทดสอบ ดูตัวอย่างโค้ด ตัวอย่าง app สามารถดาวน์โหลดเพิ่มเติมได้ที่ http://go.microsoft.com/fwlink/?LinkID=323589 ในที่นี้ผมแนะนำให้โหลดครับ ก็จะได้ไฟล์ KinectDeveloperToolkit-v1.8.0-Setup.exe มา

3. Visual Studio สำหรับเขียนโปรแกรม ในที่นี้ผมได้ลองใช้ Visual Studio Express 2012 ซึ่งดาวน์โหลดได้ที่ http://www.microsoft.com/en-us/download/details.aspx?id=34673 มีตัว iso ให้ดาวน์โหลดเพื่อติดตั้งแบบ offline ครับ

ขั้นตอนการติดตั้ง
ว่าตามคำแนะนำของ Microsoft ในเว็บ http://www.microsoft.com/en-us/download/details.aspx?id=40278 เลยนะครับ
1. อย่าพึ่งต่อ Kinect เข้ากับคอม
2. ถ้าเคยติดตั้ง Kinect Driver แล้ว ลบออกให้หมดก่อน
3. ถ้าเคยติดตั้ง Microsoft Server Speech Platform ก็ลบออกให้หมดก่อน
4. ถ้าเคยติดตั้ง Kinect SDK แล้ว ไม่ต้องลบออกก็ได้ ลงตัวใหม่ก็จะไปอัพเดทให้ (ส่วนผมเองทำการลบออกไปก่อน)
5. ถ้าเปิด Visual studio อยู่ ให้ปิดไปก่อน
6. ติดตั้งไฟล์ KinectSDK-v1.8-Setup.exe
7. (ไม่บังคับ) ติดตั้ง KinectDeveloperToolkit-v1.8.0-Setup.exe
8. เสียบไฟ Kinect และเสียบเข้ากับพอร์ต USB ตัว driver จะถูกติดตั้งโดยอัตโนมัติ
9.  ตอนนี้ไฟที่ Kinect ก็จะติดเป็นสีเขียว

การทดสอบว่า Kinect ใช้งานได้
ถ้าติดตั้ง KinectDeveloperToolkit-v1.8.0-Setup.exe แล้ว ให้ไปที่ Start / Program / Kinect for Windows SDK 1.8 แล้วเลือก Developer Toolkit Browser

จากนั้นเลือกหัวข้อง Tools แล้วเลือก Run ของ Kinect Explorer-WPF ตามรูป

จะเห็นภาพจากกล้อง Kinect ครับ

ต่อไปเราจะลองเขียนโปรแกรมด้วย C# เพื่อเชื่อมต่อกับ Kinect กันครับ ดังนั้น จำเป็นต้องติดตั้ง Visual Studio Express 2012 ที่ดาวน์โหลดมา ก็ติดตั้งให้เรียบร้อยซึ่งใช้เวลานานพอสมควรครับ

หากสนใจหาหนังสือเกี่ยวกับ Kinect อ่าน ผมแนะนำเล่มนี้ครับ เขียนละเอียด เข้าใจง่ายดี

Start Here! Learn the Kinect API 
https://www.microsoft.com/learning/en-us/book.aspx?id=15815&locale=en-us

พบกันตอนต่อไปครับ

Friday, April 10, 2015

การแก้ปัญหาไม่สามารถเรียกใช้งาน Genymotion ได้

วันนี้เจอปัญหาว่าทำไมเครื่องคอมบางเครื่องก็รัน Genymotion ได้ แต่บางเครื่องไม่ได้ เครื่องที่เป็น Windows 8 ใช้งานได้ แต่พอมาใช้ Windows 7 ใช้ไม่ได้ซะงั้น ลองดูแต่ละปัญหาและวิธีแก้ไขกันครับ

ปัญหา Cannot create OVA
อันนี้เป็นปัญหาแรกๆเลย คือ ไม่สามารถสร้าง virtual device จาก ova ไฟล์ได้ วิธีแก้ไขคือให้ลองไปลบไฟล์ deployed ที่อาจจะเคยมีการสร้าง device ไว้ก่อนแล้วแต่ไม่สำเร็จ ซึ่งจะอยู่ที่ C:\Users\xxx\AppData\Local\Genymobile\Genymotion\deployed (ต้องกำหนดให้ show hidden files ก่อนจึงจะเห็นโฟลเดอร์นี้) ให้ลบทุกอย่างในโฟลเดอร์ deployed นี้แล้วลองสร้าง device ใหม่ครับ

ปัญหา Genymotion cannot start virtual device
วิธีตรวจสอบ ไปเปิด Virtualbox แล้วลองรัน device เอง ถ้ารันไม่ได้ แสดงว่าเป็นที่ Virtualbox ในที่นี้ผมได้ลองสองวิธีคือ
1. รัน Virtualbox แยกต่างหาก แล้วเลือกเมนู File/ Preferences/ Network เลือกแท็บ Host-only networks แล้วลบรายการ Adapter ที่มีอยู่ทั้งหมดออก จากนั้นค่อยรัน Genymotion ใหม่ ซึ่งมันจะมาสร้าง Adapter ที่นี่ใหม่ให้เอง
ถ้าไม่สำเร็จ อาจจะต้อง
2. downgrade Virtualbox ซึ่งผมได้ลองใช้เวอร์ชัน 4.3.12 แล้วใช้งานได้ครับ

ปัญหาที่ player.exe has stopped working
หลังจาก Virtualbox ทำงานแล้ว Genymotion ดันแครชแล้วแสดงข้อความข้างต้นแทน เท่าที่ค้นหาดูแล้วพบว่าเป็นเพราะ driver การ์ดจอไม่อัพเดท ประกอบกับเครื่องที่ใช้มีการ์ดจอสองแบบที่สลับใช้งานกันได้ เลยลองสลับเป็นการ์ดจออีกตัวนึง ก็ใช้งานได้เลย แต่ถ้าต้องการใช้การ์ดจอตัวแรกที่มีปัญหา ก็คงต้องไปอัพเดท driver มันใหม่ครับ ยืนยันว่าลองไปอัพเดทไดร์เวอร์การ์ดจอใหม่แล้ว ปัญหานี้ก็หายไปครับ

Friday, April 3, 2015

Microsoft Word กับการทำ บทที่ เลขหัวข้อ รูปที่ ตารางที่

ชื่อหัวข้อวันนี้เหมือนค่อนข้างยาว แต่มันตรงประเด็นเลยครับ คือทุกทีเวลาเราใช้ word ทำเอกสารที่เป็นรูปเล่ม มันก็ต้องมีตัวเลขของบท ของหัวข้อ รูป ตาราง ฯลฯ ซึ่งปกติ (มั้ง) เราก็จะพิมพ์กันเอง จัดรูปแบบกันเอง เพราะมันดูง่ายสุด แต่.....มันต้องทำทุกอัน ทุกเลข และยังไม่พอ ตอนไปทำสารบัญ สารบัญตาราง+รูป ต้องมาใส่เลขเอง ถ้าหน้าเลื่อน ก็ต้องกลับไปแก้เลขอีก หรือถ้าลบรูปหนึ่งรูป ก็ต้องกลับไปเรียงลำดับเลขรูปใหม่ทั้งในเนื้อหาและสารบัญ

มาดูกันครับ ว่าเราจะทำให้ปัญหาต่างๆเหล่านี้ คลี่คลายไปด้วยวิธีใด

สมมติว่าเรามีโครงสร้างแบบ บทที่ ซึ่ง word ไม่มีมาให้ เราก็ต้องสร้างเองครับ โดยมีขั้นตอนดังนี้
1. สร้าง Multi-level list ใหม่ โดยเลือกเมนูตามรูปครับ

2. จะได้หน้าต่างสำหรับกำหนดค่าขึ้นมา คลิกเลือกปุ่ม More ที่อยู่ด้านล่างซ้ายด้วยครับ

3. ปรับแก้รายละเอียดของ list นี้ในระดับ 1 ให้เป็นบทที่ ตามรูปครับ

4. เมื่อคลิก OK ก็จะเกิดข้อความ "บทที่ 1" ในเอกสาร ตอนนี้เราก็ได้โครงสร้างของบทที่แล้ว ต่อไปเราจะทำให้รูปแบบการแสดงผลเป็นไปอย่างที่เราต้องการ
5. ทำการปรับแก้ Style ของ "บทที่" โดยคลิกขวาที่แถบเมนู Style หัวข้อ "บทที่ 1" (ซึ่งก็คือ Heading 1) ตามรูป

6. แล้วก็ปรับแก้รายละเอียด สมมติว่าผมจะใช้ฟอนต์และการจัดรูปแบบตามรูปนะครับ ข้อดีของการทำแบบนี้คือ ทุกข้อความที่เป็น Style นี้ก็จะมีรูปแบบเดียวกันทั้งหมดในเอกสารนี้ครับ

7. ถึงขั้นตอนนี้ก็จะได้ข้อความ "บทที่ 1" อยู่กลางหน้าจออย่างที่ต้องการ
8. ต่อไปเราลองพิมพ์ชื่อบทเข้าไปด้วย เช่น บทที่ 1 บทนำ ตรงนี้ผมอยากให้คำว่า "บทนำ" ลงไปอยู่อีกบรรทัดนึง มันจะมีกระบวนการที่สำคัญคือ เราไม่สามารถเคาะ Enter ได้โดยตรง เพราะถ้าทำอย่างนั้นแล้วตอนใส่เลขรูป หรือ ตาราง จะเกิดปัญหาได้ (ไม่รู้ว่าเพราะอะไรเหมือนกันนะครับ) เลยต้องกด Shift+Enter ก่อนคำว่า "บทนำ" ให้มันขึ้นบรรทัดใหม่ แต่ยังอยู่ในย่อหน้า (paragraph) เดียวกับคำว่า "บทที่ 1" ก็จะได้ผลดังนี้

9. ต่อไปเราก็จะกำหนดค่าหัวข้อแรก คือ 1.1 โดยจะกำหนดให้เป็น style Heading 2 ดังนี้
9.1 คลิกขวาที่คำว่า บทที่ 1 แล้วเลือก Adjust list indents
9.2 ในส่วน Click level to modify ให้เลือกค่า 2
9.3 เพื่อไม่ให้สับสน แก้ไขส่วนของ Number format ก่อนให้เป็นดังรูป

9.4 จากนั้นเลือก Include level number from: แล้วเลือก Level 1 จะได้ผลดังรูป
9.5 ในช่องที่มีเลข 1 อยู่ ให้พิมพ์ . (จุด) และ เลือกหัวข้อ Number style for  this level: ตามรูป
9.6 กำหนดค่าที่เหลือตามรูป

9.7 คลิกขวาที่ Style / Heading 2 แล้วเลือก Modify

9.8 แก้ไขดังตัวอย่างในรูป

9.9 พิมพ์ข้อความที่ต้องการลงไป แล้วเลือก Style ให้เป็น Heading 2 จะได้ผลดังรูป

หากตัวเลข 1.1 ไม่แสดง ให้คลิกที่ข้อความ จากนั้นเลือกเมนูดังรูป


10. หากมี level ที่ต่ำลงไปอีกเช่น 1.1.1 ก็ให้ทำเหมือนกับข้อ 9.1-9.9 แต่เลือก level 3 เป็นต้น
11. ส่วนที่เป็น Style ที่ใช้เป็นตัวปกติคือ Normal ก็สามารถกำหนดค่าให้ชนิดและขนาดของฟอนต์เป็นไปตามต้องการได้ ทุกครั้งที่มีการสร้างหัวข้อหรือพิมพ์ข้อความ พยายามใช้ Style เป็นตัวกำหนดแทนการแก้ไขทีละส่วนเอง
12. หากต้องการเพิ่มชื่อรูป เมื่อใส่รูปแล้ว ให้เลือกเมนูตามรูป

13. ถ้าในหัวข้อ Options: Label เมื่อคลิกดูแล้วยังไม่มีคำว่า "รูปที่" ตามต้องการ ให้เลือก New Label: แล้วพิมพ์คำว่า "รูปที่" ลงไป

14. จากนั้นหากต้องการเลขของรูปเป็น รูปที่ 1.1 โดยที่เลขตัวแรกเป็นชื่อบท ก็ให้เลือก Numbering แล้วกำหนดค่าต่างๆตามรูป

ก็จะเกิดคำว่า รูปที่ 1.1

15. จากนั้นกำหนดค่า Style ของรูป ซึ่งจะเป็น Style ชื่อว่า Caption ให้เป็นไปตามต้องการ


ผลลัพธ์ก็จะได้ประมาณนี้ครับ

16. หากมีตารางก็ทำเหมือนกับรูป

17. สามารถแทรกสารบัญ สารบัญตาราง สารบัญรูปได้



Tuesday, January 6, 2015

Java กับ Generic Class

เวลาสร้างคลาสในจาวา เราก็คงอยากให้คลาสของเรารองรับตัวแปรหลายๆประเภท แล้วจะทำได้อย่างไร ทางออกหนึ่งก็คือ Generic Class นี่ล่ะครับ เราสามารถกำหนดให้มันใช้ตัวแปรแบบกลางๆ (ไม่ต้องระบุว่าเป็น int, char, double ฯลฯ)

ลองดูตัวอย่างการสร้างตัวแปรของคลาสที่เป็นแบบ int และการ set กับ get ตามปกติกันก่อน

public class MyClass{
    private int value;
    public void set(int v){
        value = v;
    }
    public int get(){
        return value;
    }
    
    public static void main(String[] args){
        MyClass m = new MyClass();
        m.set(5);
        System.out.println(m.get());
    }
}
แน่นอนครับ ผลลัพธ์ที่ได้ก็คือเลข 5 นั่นเอง

คราวนี้ ถ้าเราต้องการส่งค่าที่ไม่ใช่ตัวเลข เช่น m.set("Hello"); ไป สิ่งที่เกิดขึ้นก็คือ compile ไม่ผ่าน เพราะชนิดของข้อมูลที่ส่งไป กับชนิดของข้อมูลที่เอาไปรับไม่ตรงกัน ก็จำเป็นจะต้องเขียน method ใหม่ แถมยังไม่พอ ต้องประกาศตัวแปรของคลาสใหม่เพื่อมารับข้อมูลชนิดนี้ด้วย

เพื่อที่จะลดความซับซ้อนตรงนี้ลง (แต่ไปเพิ่มความงงให้กับการเขียนโปรแกรม) ลองใช้ Generic class กันดูตามนี้ครับ

public class MyClass<T>{
    private T value;
    public void set(T v){
        value = v;
    }
    public T get(){
        return value;
    }
    
    public static void main(String[] args){
        //MyClass m = new MyClass();
        MyClass<Integer> m1 = new MyClass<Integer>();        
        //m.set(10);
        m1.set(new Integer(10));
        System.out.println(m1.get());
        
        MyClass<String> m2 = new MyClass<String>();
        m2.set(new String("Hello"));
        System.out.println(m2.get());
    }
}

ผลลัพธ์ที่ได้คือ
10
Hello

ซึ่งจะสังเกตเห็นว่า เราก็ยังมีคลาสเดียว แต่ตอนสร้าง Object เราสร้างมันสองตัวคือ m1 เป็นแบบ Integer และ m2 เป็นแบบ String แต่ทั้งสอง Object ก็ใช้ตัวแปรคลาสและ method ร่วมกันได้

ข้อสังเกต

  1. เราสร้างคลาสด้วย public class MyClass<T> ซึ่งหลังคลาสจะตามด้วย Generic type ที่ระบุด้วยเครื่องหมาย <T> และตัว T ก็เป็นชื่อชนิด (จะตั้งเป็นตัวอื่นก็ได้ แต่มักใช้ T แทน Type)
  2. จากนั้นเราก็ใช้ T เหมือนชนิดของตัวแปรทั่วไป เช่น private T valueก็คือการกำหนดให้ตัวแปร value เป็นชนิด T ซึ่งจะกลายเป็น reference type เช่น Integer, Double, String ในอนาคตได้
  3. ในส่วนของ main() เวลาสร้าง Object ต้องระบุชนิดตามหลังคลาสด้วย (สังเกตว่าสัญลักษณ์ ตามติดหลังชื่อคลาสตลอด) เช่น MyClass<Integer> m1 = new MyClass<Integer>(); ซึ่งในจาวารุ่น 7.0 ไป เราสามารถลดรูปให้เหลือแค่ MyClass<Integer> m1 = new MyClass<>(); ได้
  4. เวลาส่งค่าให้ method ของ Generic class ในกรณีนี้ เราก็ไม่สามารถส่งค่าตัวแปรแบบทั่วไปได้ ต้องส่งเป็น Object ของคลาสไป เช่น m1.set(new Integer(10)); แทน

Java กับ Generic method

เมื่อเราต้องการเขียนโปรแกรมให้สนับสนุนข้อมูลหลายๆประเภท เช่น เขียน method เดียวแต่รองรับทั้งข้อมูลที่เป็น integer และ String เราอาจจะคิดถึง Overloaded methods ซึ่งก็ต้องเขียน method แยกไปแต่ละประเภทของข้อมูล

อย่างไรก็ตาม หากเราต้องการเขียนเป็น method เดียว เพื่อให้โปรแกรมกระชับและมีประสิทธิภาพ รวมถึงตัว compiler สามารถตรวจสอบความถูกต้องของชนิดของข้อมูลให้ได้ วิธีการนึงคือการใช้งาน Generic method ซึ่งเริ่มมีมาตั้งแต่ Java รุ่น 5.0 ไปครับ

ลองดูตัวอย่างการเขียนโปรแกรมโดยใช้ method ปกติ เพื่อแสดงค่าของสมาชิกของตัวแปรชุด (Array)

//======= Normal method to print an integer array ==========
public class MyArray{
    public void printArray(int[] arr){
        for(int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }        
    }
    
    public static void main(String[] args){
        MyArray m = new MyArray();
        int[] a = {1,2,3};
        m.printArray(a);
    }
}
จะเห็นว่า method ชื่อ printArray() ก็จะใช้ได้เฉพาะ array แบบ integer เท่านั้น ถ้าต้องการใช้กับข้อมูลประเภทอื่น ก็ต้องเขียน method นี้ใหม่

คราวนี้ลองมาเปลี่ยน method นี้ให้เป็น generic method กันดูครับ

//======= Generic method to print any array ==========
public class MyArray{
    public <E> void printArray(E[] arr){
        for(int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }        
    }
    
    public static void main(String[] args){
        MyArray m = new MyArray();
        //int[] a = {1,2,3};
        //must create array object to be compatible with generic type
        Integer[] a = {1,2,3};
        String[] b = {"I","love","you"};    
        m.printArray(a);
        m.printArray(b);
    }
}
ก็จะเห็นว่า method ใหม่นี้รองรับทั้ง array หลายชนิด ทั้งแบบ Integer และ String ตามตัวอย่าง

ข้อสังเกตการสร้างและใช้งาน generic method คือ

  1. Generic method มี <Eหน้า return type ซึ่งสัญลักษณ์พิเศษนี้ก็คือตัวแทนของชนิดของข้อมูล นั่นคือ E ในที่นี้อาจจะแทน Integer, String, Double ฯลฯ (เป็น reference type ไม่ใช่ primitive type เช่น int, double, char)
  2. เราสามารถใช้ตัวอักษรอื่นแทน E ก็ได้ ซึ่งปกติจะมีรูปแบบแนะนำว่าควรใช้ตัวอักษรแบบไหนเพื่ออะไร เช่น E แทน Elements หรือ T แทน Types ดูเพิ่มเติมได้ที่นี่ครับ
  3. การใช้งานตัว E ใน method ก็เหมือนชนิดของข้อมูลทั่วไป เช่น เอาไว้หน้าตัวแปร
ข้อมูลอ้างอิง
http://www.tutorialspoint.com/java/java_generics.htm
http://docs.oracle.com/javase/tutorial/java/generics/