Chủ Nhật, 2 tháng 12, 2012

Kinect và ứng dụng trong mobile robot (Phần 2)


2.Tìm hiểu và sử dụng thư viện Kinect


Thư viện Kinect là thư viện do Microsoft tạo ra để tạo môi trường cho người dùng có thể dễ dàng xây dựng những ứng dụng một cách nhanh chóng trên cả PC lẫn dòng máy chơi game Xbox 360. Thư viện này hỗ trợ cho cả 3 ngôn ngữ thông dụng là C#, C++ và VB đồng thời cũng tương thích với win7 và 8. Hiện tại, phiên bản mới nhất là SDK for Kinect version 1.6 đã cải tiến nhiều tính năng nên dễ sử dụng và tỏ ra là một lựa chọn hiệu quả hơn so với các thư viện mã nguồn mở. Tuy nhiên để sử dụng thư viện này cho các ứng dụng thương mại thì cần trả tiền bản quyền cho Microsoft.
Yêu cầu hệ thống :
·        Microsoft Kinect SDK – Các bạn có thể download tại đây .
·        Visual Studio 2010 .
·        Kinect
Để bắt đầu với tìm hiểu, ở đây sẽ sử dụng C#.

2.1 Tạo project:

Bước đầu tiên cần thực hiện là tạo một project mới, có thể là dạng Windows Forms hay dạng WPF.
Bước tiếp theo là thực hiện add reference để có thể thao tác với Kinect SDK. Bấm chuột phải vào phần References ở cửa sổ bên trái  và chọn Add reference sau đó tìm file Microsoft.Kinect.dll trong tab .Net
Chú ý rằng nếu sử dụng các phiên bản beta thì file cần add là Microsoft.Research.Kinect.

 2.2Thiết lập cho Kinect

Hầu như tất cả các chương trình Kinect đều bắt đầu như nhau.
Đầu tiên là tìm kiếm các senser đã kết nối với máy tính và kiểm tra tình trạng của chúng. (Chú ý rằng các phiên bản trước thì code sẽ hơi khác so với bản 1.6)
       Để làm việc này chúng ta khai báo một đối tượng thuộc lớp KinectSenser
Khai báo thêm  thư viện kinect       using Microsoft.Kinect;
Trong sự kiện  WindowLoaded chúng ta sử dụng lệnh foreach để kiểm tra tất cả các sensor đc kết nối.

          foreach (var SensorKetNoi in KinectSensor.KinectSensors)
            {
                if (SensorKetNoi.Status == KinectStatus.Connected)
                {
                    this.sensor = SensorKetNoi;
                    break;
                }
            }

Khi tất cả các senser đã được kết nối, ta tiến hành cho phép nhận các dòng dữ liệu cần thiết cho ứng dụng như độ sâu, âm thanh hoặc ảnh màu từ cảm biến sau đó khởi động cảm biến và viết các hàm để xử lý dữ liệu nhận được (Có thể là xuất ảnh ra màn hình, tính toán khoảng cách, nhận dạng…)
if (null != this.sensor)
     {
                this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
                this.sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
this.sensor.SkeletonStream.Enable();
            // Khởi động sensor!
      }

2.3 Nhận và hiển thị dữ liệu từ cảm biến.

            Dữ liệu gửi về dưới dạng data stream. NUI API cho phép lập trình kiểm soát và truy nhập dữ liệu.
Các bước làm bao gồm:
1.      Xác định dòng dữ liệu cần thiết.
2.      Cho phép mở dòng dữ liệu (Enable Data Streaming)
3.      Tạo bộ đệm để lưu trữ dữ liệu sensor.
4.      Giải phóng bộ đệm để có thể sử dụng trong khung hình tiếp theo.
Trong việc hiển thị dữ liệu, các hàm hỗ trợ trong SDK rất phức tạp, các bạn có thể down Coding4Fun.Kinect.Toolkit về sau đó add reference đến file coding4Fun.Kinect.winForm.dll hoặc coding4Fun.Kinect hoặc coding.4Fun.kinect.Wpf.dll
(bằng cách chuột phải lên refeference -> chọn thẻ browse-> dẫn đến thư mục  Coding4Fun.Kinect.Toolkit)
Khi sử dụng bạn chú ý thêm  using Coding4Fun.Kinect.WinForm;

2.3.1  ColorStream:

ColorStream có nhiều độ phân giải và định dạng tùy thuộc vào các lựa chọn colorStream là RGB, YUV hay Bayer.
SDK cung cấp một số tùy chọn cho phép tối ưu hóa camera ứng với các tác động môi trường như:
-         Tăng giảm độ sáng
-         Thay đổi màu sắc, độ tương phản
Tất cả được hỗ trợ trong class ColorCameraSetting.
Để hiển thị các thành phần dữ liệu mầu sắc bằng C# chúng ta cần tiến hành các công việc sau:
-         Khởi tạo cảm biến để tạo dữ liệu màu (đã đề cập ở trên)
-         Xử lý sự kiện và hiển thị lên Forms.
a.      Tạo sự kiện báo dữ liệu đã sẵn sàng:
if (this.sensor != null)
          {
            this.sensor.ColorFrameReady += this.SensorColorFrameReady;
          }

b.      Xử lý sự kiện và hiển thị lên Forms.
Ví dụ bên dưới được thực hiện với windows Forms với sự hỗ trợ của công cụ Coding4Fun.Kinect.Toolkit . Để hiển thị với WPF các bạn có thể tham khảo thêm ở địa chỉ.
private void SensorColorFrameReady(object sender,                                         
                                     ColorImageFrameReadyEventArgs e)
          {
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
              if (colorFrame != null)
              {
                  colorImage.Image = colorFrame.ToBitmap();
             
              }
            } 
          }


2.3.2 Depth Stream

Mỗi khung hình của dữ liệu Depth Stream được tạo thành từ các pixels chứa khoảng cách (bằng mm) từ mặt phẳng camera đến đối tượng.
Các ứng dụng có thể sử dụng depth data để bám theo chuyển động hoặc nhận dạng đối tượng.
            Dữ liệu về khoảng cách tính bằng mm là bộ số (x,y) chứa tọa độ trong field of view của sensor.

 Có 3 tùy chọn độ phân giải là 640x480 (mặc định), 320x240 vào 80x60. Tất cả được quy định trong DepthImageFormat Enumeration.
            Việc hiển thị dữ liệu cho DepthStream hoàn toàn tương tự ColorStream.
if (this.sensor != null)
          {
            this.sensor.DepthFrameReady += this.SensorDepthFrameReady;
          }
private void SensorDepthFrameReady (object sender,                                         
                                     ColorImageFrameReadyEventArgs e)
          {
            using (DepthImageFrame DepthFrame = e.OpenColorImageFrame())
            {
              if (DepthFrame != null)
              {
                  DepthImage.Image = DepthFrame.ToBitmap();
             
              }
            } 
          }

2.4 Điều khiển góc nghiêng sensor

            Góc nghiêng của sensor trong kinect có giá trị từ -27 đến 27, giá trị này tính theo phương vuông góc với trọng lực, tức là nếu góc bằng 0 thì phương của camera sẽ vuông góc với trọng lực.
Để điều khiển góc nghiên của sensor ta sử dụng thuộc tính sensor.ElevationAngle
Thuộc tính này cho phép ta có thể get hoặc set giá trị cho góc sensor.
Ví dụ sau mô tả việc hiển thị góc và đặt giá trị góc nghiêng bằng một thanh cuộn ngang kết hợp với 1 nút bấm và hiển thị giá trị đó lên một label.
private void hScr_dieuChinhGoc_ValueChanged(object sender, EventArgs e)
        {
            lbl_gocnghieng.Text = hScr_dieuChinhGoc.Value.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            sensor.ElevationAngle = hScr_dieuChinhGoc.Value;
        }

2.5 Demo sử dụng Kinect với WindowsForms

Demo này tổng hợp lại các ví dụ ở trên trong đó sử dụng các thành phần sau:
-         2 PictureBox là colorImage và DepthImage để hiển thị dữ liệu ảnh mầu và dữ liệu độ sâu.
-         1 HscrollBar là hScr_dieuChinhGoc kết hợp với 1 Button để đặt giá trị góc quay.
-         Các lable lbl_HienThiGocNghieng và lbl_gocnghieng để hiển thị giá trị đo góc.
v Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Kinect;
using Coding4Fun.Kinect.WinForm;

namespace DemoWinForm2
{
    public partial class Form1 : Form
    {
        private KinectSensor sensor;// Khai báo sensor
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {  
            //Kiểm tra các sensor được kết nối
            foreach(var sensorKetnoi in KinectSensor.KinectSensors)
            {
                if(sensorKetnoi.Status==KinectStatus.Connected)
                {
                    this.sensor = sensorKetnoi;
                    break;
                }
            }
            if(this.sensor!=null)
            {  
 // Enable dòng dữ liệu và thiết lập các tùy chọn cho dữ liệu ảnh
                this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
// Enable dòng dữ liệu và thiết lập các tùy chọn cho dữ liệu độ sâu
                this.sensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
                // Khởi động sensor
                this.sensor.Start();

                // Hiển thị góc nghiêng ban đầu của sensor.
                lbl_gocnghieng.Text = sensor.ElevationAngle.ToString();

                // Các sự kiện thông báo dữ liệu đã sẵn sàng.
                this.sensor.ColorFrameReady += this.SensorColorFrameReady;
                this.sensor.DepthFrameReady += this.SensorDepthFrameReady;
             
            }
        }
       
        // Xử lý các sự kiện.
         private void SensorColorFrameReady(object sender,                                             
                                             ColorImageFrameReadyEventArgs e)
          {
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
              if (colorFrame != null)
              {
                  colorImage.Image = colorFrame.ToBitmap();
             
              }
            } 
          }
         private void SensorDepthFrameReady(object sender,
                                              DepthImageFrameReadyEventArgs e)
         {
             using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
             {
                 if (depthFrame != null)
                 {
                     depthImage.Image= depthFrame.ToBitmap();
                 }
                
             }
         }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (sensor != null)
            {
// Đưa góc nghiêng về 0 trước khi tắt sensor.

                sensor.ElevationAngle = 0;
                sensor.Stop();

            }
        }
       
        // Các hàm xử lý sự kiện để điều chỉnh góc nghiêng.
        private void hScr_dieuChinhGoc_ValueChanged(object sender, EventArgs e)
        {
            lbl_gocnghieng.Text = hScr_dieuChinhGoc.Value.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            sensor.ElevationAngle = hScr_dieuChinhGoc.Value;
        }
                    
    }
}

v Kết quả:
Trên đây là những tìm hiểu mang tính chất tổng hợp kiến thức, tuy rằng vẫn đang còn sơ lược nhưng có thể sẽ hữu ích với những bạn mới bắt đầu tiếp cận với Kinect.

Kinect và ứng dụng trong mobile robot (Phần 1)


1.Giới thiệu cơ bản về Kinect






Kinect là sản phẩm của Microsoft  dựa trên công nghệ  camera được phát triển bởi PrimeSense,  những  sản phẩm đầu tiên được bán tại  Bắc  Mỹ  vào  ngày 4  tháng 11 năm 2010 .
 Kinect được coi như là một thiết bị  ngoại vi cho Xbox 360, cho phép giao tiếp với con người thông qua các cử chỉ, đem lại những cảm giác thú vị cho người chơi game trên Xbox. Khả  năng hiểu được cử  chỉ  con người của Kinect dựa trên hai đặc tính chính  sau: thông tin về  độ  sâu  ảnh (depth map), khả  năng phát hiện và bám theo đặc tính cơ thể người (body skeleton tracking).
Bên cạnh phục vụ  cho mục đích chơi game,  sản phẩm Kinect còn được dùng vào  mục đích  nghiên cứu xử  lý  ảnh 3D, phát hiện cử  chỉ  (gesture recognition),  bám theo  người  (body tracking)  và nhiều mục đích khác. Lý do chính cho sự  thành công của sản phẩm Kinect là giá cả  khá rẻ  (khoảng 140$ trên 1 sản phẩm) cho thiết bị  có khả  năng cung cấp các thông tin 3D với chất lượng chấp nhận được.

1.1  cấu trúc phần cứng.

Bên trong Kinect bao gồm 1 camera RGB, cảm biến độ sâu , một dãy các microphone và 1 động cơ điều khiển góc nâng.

1.1.1       Camera RGB

Là một camera có 3 kênh dữ liệu có độ phân giải 1280x960. Camera này có khả năng chụp lại ảnh ảnh mầu.

1.1.2       Cảm biến độ sâu

Độ sâu thu về nhờ sự kết hợp của 2 bộ phận là bộ phát hồng ngoại IR và camera hồng ngoại đọc các tín hiệu phản hồi về từ đó tính toán ra bản đồ độ sâu.

1.1.3       DãyMicrophone

Dãy Micro bao gồm 4 micro được bố trí dọc theo thân Kinect có khả năng thu lại âm thanh đồng thời xác định hướng của âm thanh. Dãy Microphone này được dùng trong các ứng dụng điều khiển bằng giọng nói.
Ngoài ra Kinect còn có 1 cảm biến đo gia tốc để xác định hướng và 1 động cơ dùng để điều khiển góc ngẩng camera.
Trong số những cảm biến kể trên của Kinect, cảm biến độ sâu có khả năng ứng  dụng cao trong đề tài robot tránh mục tiêu.

1.2  Nguyên lý các cảm biến độ sâu.

Cặp cảm biến IR camera và IR projector sẽ phối hợp với nhau để tạo ra giá trị độ sâu bằng công nghệ Light Coding của PrimeSense.

Kĩ thuật Light Coding dùng nguồn sáng hồng ngoại chiếu liên tục kết hợp với một camera hồng ngoại để tính khoảng cách. Việc tính toán này được thực hiện bằng chip PS1080 Soc của PrimeSen.
Projector sẽ  chiếu một chùm sáng hồng ngoại, tạo nên những đốm sáng ở  không gian phía trước Kinect, tập hợp đốm sáng  được phát ra  này  là cố  định.  Những đốm sáng này được tạo ra nhờ  một nguồn sáng truyền qua lưới nhiễu xạ  (diffraction gratings). Tập hợp các đốm sáng này được IR camera chụp lại, thông qua giải thuật đặc biệt được tích hợp trong  PS1080 SoC  cho ra bản đồ độ sâu.  Bản chất của giải thuật này là các phép toán hình học dựa trên  quan hệ  giữa hai cảm biến IR camera và Projector.

 1.3  Các dữ liệu đo được từ cảm biến.


Các cảm biến của Kinect được điều khiển đồng thời thu thập và xử lý dữ liệu thông qua chip PS1080 có tần số 12MHz, sau đó được lưu trữ vào bộ nhớ Flash. Các dữ liệu này có thể truyền vào máy tính thông qua cổng USB 2.0.

Các tín hiệu thu thập bao gồm dữ liệu về độ sâu, màu sắc và âm thanh trong đó tín hiệu về độ sâu là dữ liệu quan trọng có nhiều dụng.
Sở dĩ dữ liệu về chiều độ sâu có tầm quan trọng như vậy bởi nó giúp việc nhận dạng các vật thể đơn giản hơn nhiều so với xử lý ảnh thông thường.  Các thuật toán xử lý ảnh thông thường dựa vào sự tương đồng về mầu sắc, tuy nhiên, có thể những vật có mầu sắc tương tự nhau nhưng không cùng một vật thể  hoặc các phần của cùng một đối tượng nhưng có mầu khác nhau,do vậy gây khó khăn trong quá trình nhận dạng. Trong khi đó, với thông tin về độ sâu,  các vật thể được phân biệt với nhau thông qua vị trí. Những điểm có khoảng cách gần nhau có xu hướng cùng một đối tượng mà không phân biệt mầu sắc.  Chỉ khi độ sâu giảm đột ngột như ở cạnh và ở một số phần nhỏ của đối tượng thì khi đó, hình ảnh trên bản đồ độ sâu mới có sự thay đổi.
Một ưu điểm nữa của bản đồ độ sau đó là dữ liệu có thể được nén cao hơn so với  ảnh mầu thông thường do đó thích hợp trong việc truyền dẫn nhanh tín hiệu.
Các thuật toán nhận dạng đối với ảnh độ sâu đơn giản hơn và thậm chí có thể tái tạo lại vật thể 3D.
Từ những phân tích trên ta có thể thấy được những ưu điểm của bản đồ độ sâu và nó rất thích hợp để ứng dụng trong các đề tài về robot tự hành.