Facebook RSS Feed
 
Kinect & Leap Motion: Piksel Derinlik Ölçümü
Tarih: 22.09.2012, Platform: .NET 4.5, IDE: Visual Studio 2012, Level: 200

Kinect, derinlik ve iskelet algılaması için kızılötesi tarama yapar. Bu tarama sonrasında her bir pikselin sensörden uzaklığını mm olarak bilgisayara iletir. Piksellerin derinlik bilgisi 3 boyutlu ortam haritası çıkarılması gibi amaçlarla kullanılabilir. Diğer yandan, tek bir pikselin yada yatay bir çizginin derinliği elde edilerek robotik projelerde yüksek maliyetli lazer sensörlerin yerine alternatif olarak Kinect yerleştirilebilir. Bu çalışmamızda, istenilen pikselin sensöre olan uzaklığını elde etmeyi göreceğiz.

Öngereksinimler

Kinect ile uygulama geliştirmek için, www.kinectforwindows.com adresinden Kinect SDK'yı indirip kurmanız gerekiyor. Derinlik verisi kullanımı konusunda deneyim sahibi değilseniz, Kinect 104: Derinlik Görüntüsü yazısını inceleyebilirsiniz.

Çalışma Mantığı

Derinlik bilgisi, 47° dikey ve 57° yatay aralıkta 640x480, 320x240 veya 80x60 çözünürlüğünde, saniyede 30 kare olarak elde edilir. Bu veri, çözünürlüğe göre boyutu değişen bir short dizisinde saklanır. Her yeni kare yakalandığında, dizi elemanlarının değerleri yeni mesafe bilgisine göre güncellenir.

Bir piksele ait bilgi, 2x8 bit, toplamda 16 bit short üzerinden aktarılır. 16 bit'in 13 bitlik kısmı uzaklığa, 3 bitlik kısmı da player index'ine aittir.

15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
D12 D11 D10 D09 D08 D07 D06 D05 D04 D03 D02 D01 D00 P02 P01 P00

Player index, o pikselde bir iskelet tanımlanmışsa 1'den 6'ya kadar tanımlanan kişinin index'ini belirtir. Piksel herhangi bir kişiye ait değilse, 0 değerini alır.

Derinlik bilgisi ise, geriye kalan 13 bitin 3 bit sağa kaydırılmasıyla hesaplanır ve  piksele ait milimetre değerini verir. Uygulamamızda, dizinin 40x30. pikseline ait elemanlarından uzaklık bilgisini elde edeceğiz.

Uygulama

Visual Studio ile oluşturacağımız "KinectNoktaDerinlikOlcumu" isimli WPF uygulamasının referanslarına "Microsoft.Kinect.dll" dosyasını ekleyelim. Uygulamamızın tasarımı ve kodları aşağıdaki gibi olacak.

-

[XAML] MainWindow.xaml 

<Window x:Class="KinectNoktaDerinlikOlcumu.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Kinect Derinlik Ölçümü" Height="200" Width="525" WindowStartupLocation="CenterScreen"
        Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <TextBlock HorizontalAlignment="Left" Margin="10,30,0,0" TextWrapping="Wrap"
                   Text="Derinlik:" VerticalAlignment="Top" FontSize="20"/>
        <TextBlock x:Name="tbPixelDistance" HorizontalAlignment="Left" Margin="100,30,0,0"
                   TextWrapping="Wrap" Text="00m 00cm 0mm" VerticalAlignment="Top" FontSize="20"/>
        <ProgressBar x:Name="pbPixelDistance" Height="10" Margin="10,80,10,0"
                     VerticalAlignment="Top" Maximum="4000"/>
    </Grid>
</Window>

 [C#] MainWindow.xaml.cs

using System;
using System.Windows;
using Microsoft.Kinect;
 
namespace KinectNoktaDerinlikOlcumu
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private KinectSensor kinect;
        private short[] depthPixelData;
        private DepthImageFormat lastDepthFormat = DepthImageFormat.Undefined;
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Kinect bağlıysa, belirtilen parametrelere göre ilk Kinect'i yapılandır ve başlat
            if (KinectSensor.KinectSensors.Count > 0)
            {
                kinect = KinectSensor.KinectSensors[0];
 
                // Kinect'i başlat
                kinect.Start();
 
                // Derinlik algılamasında yakın modu etkinleştir
                // (Xbox için Kinect kullanıyorsanız yakın modu kullanmayın)
                kinect.DepthStream.Range = DepthRange.Near;
 
                // Derinlik bilgisi akışını 80x60 30fps biçiminde başlat
                kinect.DepthStream.Enable(DepthImageFormat.Resolution80x60Fps30);
 
                // Yeni görüntü geldiğinde tetiklenecek event handler'ı oluştur
                kinect.DepthFrameReady
                    += new EventHandler<DepthImageFrameReadyEventArgs>(Kinect_DepthFrameReady);
            }
        }
 
        private void Kinect_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            // Derinlik bilgisini açıp depthFrame'e aktar
            using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
            {
                // Derinlik bilgisi boş değilse işle
                if (depthFrame != null)
                {
                    // Önceki derinlik biçimi ile yeni gelen derinlik biçimi farklı mı?
                    bool haveNewFormat = lastDepthFormat != depthFrame.Format;
 
                    // Derinlik biçimi değiştiyse
                    if (haveNewFormat)
                    {
                        // Yeni derinlik bilgisi boyutuna göre diziyi boyutlandır
                        depthPixelData = new short[depthFrame.PixelDataLength];
                    }
 
                    // Derinlik bilgisini depthPixelData dizisine aktar
                    depthFrame.CopyPixelDataTo(depthPixelData);
 
                    // Derinlik bilgisi dizisinden x:40, y:30 noktasının uzaklığını hesapla
                    // Her noktanın derinlik bilgisi, 13 bit mm ve 3 bit player index içerir
                    // Yalnızca mm kullanacağımız için, hesaplanan veriyi 3 bit sağa kaydıracağız
                    int d = (ushort)depthPixelData[40 + 30 * depthFrame.Width] >> 3;
 
                    // Uzaklık değeri algılanmamışsa (en yüksek değerdeyse)
                    if ((kinect.DepthStream.Range == DepthRange.Default && d == 8191)
                        || (kinect.DepthStream.Range == DepthRange.Near && d == 4095))
                    {
                        // Mesafeyi 0 olarak göster
                        tbPixelDistance.Text = "00m 00cm 0mm";
                        pbPixelDistance.Value = pbPixelDistance.Minimum;
                    }
 
                    // Uzaklık değeri algılanmışsa
                    else
                    {
                        // Uzaklık değerini metre, cm, mm olarak göster
                        tbPixelDistance.Text = d.ToString("00m 00cm 0mm");
 
                        // Uzaklık değerini progress bar üzerinde göster
                        pbPixelDistance.Value = d;
                    }
 
                    // Bir sonraki derinlik biçimi karşılaştırması için, yeni derinlik
                    // biçimini kaydet
                    lastDepthFormat = depthFrame.Format;
                }
            }
        }
 
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Kinect çalışıyorsa durdur
            if (kinect.IsRunning)
                kinect.Stop();
        }
    }
}

Uygulamayı çalıştırdığınızda, Kinect'in ortasında bulunan nesnenin uzaklığını göreceksiniz.

Bu noktanın mesafesi algılanamamışsa, near mode'da 4095 (4 metre), normal modda 8191 (8 metre) değerini alacaktır. Geliştirdiğimiz uygulama, bu değerlerin alınması durumunda mesafeyi 0 olarak gösterir.

İpucu: Yalnızca bir noktanın uzaklık değerini ölçecekseniz, depth image çözünürlüğünü 80x60 olarak ayarlamanız performans açısından avantaj sağlayacaktır.


Ek Dosya: Uygulama Kodları
Okunma Sayısı: 2080

comments powered by Disqus
 
Hoşgeldiniz!
Son güncelleme: 25.12.2016
-
Yeni Teknik Yazılar
Latte Panda İncelemesi
Turta IoT HAT İncelemesi
USB Gamepad Kullanımı
GPIO Kullanımı
VEML6075 UV Sensör Kullan...
-
İlgili Gruplar
.NET MF ve Gadgeteer FB Grubu
İst. IoT & Wearables Meet-up
-
 

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.Copyright © 1999 - 2017, Umut Erkal. Bu materyal, "Creative Commons Public Licence" ile sunulmuştur.
Kaynak göstererek ve ücretsiz olarak, aynı şartlar altında paylaşabilir ve kullanabilirsiniz. | Kullanım Sözleşmesi