Facebook RSS Feed
 
Kinect & Leap Motion: Kinect 104: Derinlik Görüntüsü
Tarih: 27.07.2012, Platform: .NET 4.0, IDE: Visual Studio 2010, Level: 100



Renkli görüntü ve eklem pozisyonlarının yanısıra, Kinect ile her bir pikselin derinlik değerine de ulaşabiliyoruz. Bu özellik ile Kinect, 3 boyutlu objelerin taranması gibi senaryolarda da kullanım alanı buluyor. Kinect 104 çalışmamızda, derinlik bilgisinin gri tonlamaya çevrilerek görselleştirilmesinin üzerinde duracağız.

Öngereksinimler

Kinect ile uygulama geliştirmek için, www.kinectforwindows.com adresinden Kinect SDK'yı indirip kurmanız gerekiyor. Temel bilgiler için önce Kinect 101 yazımıza göz atabilirsiniz.

Çalışma Mantığı

Derinlik görüntüsü almanın mantığı, temelde -Kinect 102 çalışmamızda üzerinde durduğumuz- RGB görüntüsü almak ile aynı şekilde işler. Kinect'in solunda bulunan lazer projektörü, 47° dikey, 57° yatay alanda tarama yapar. Derinlik sensörü ise, her bir piksel için ışığın yansıma süresini hesaplayarak obje ile arasındaki uzaklığı belirler. Bu bilgi 640x480 piksele kadar, saniyede 30 defa uygulamamıza raporlanır.

Uygulamamızda derinlik verisini kullanmak için izleyeceğimiz yol aşağıdaki gibidir:
- Kinect başlatılır.
- İstenilen çözünürlükte derinlik akışı başlatılır.
- Derinlik bilgisine erişeceğimiz event handler oluşturulur.
- Kinect tarafından saniyede 30 defa derinlik bilgisini raporlayan event tetiklenir.
- Event argümanları aracılığıyla derinlik bilgisine ulaşılır.

Desteklenen Görüntü Biçimleri

Derinlik verisini 3 farklı çözünürlükte elde edebiliyoruz:
- 80x60 piksel, saniyede 30 kare
- 320x240 piksel, saniyede 30 kare
- 640x480 piksel, saniyede 30 kare

Uygulama

Geliştireceğimiz uygulamada, derinlik bilgisini 640x480 çözünürlüğünde bitmap'e dönüştürerek göstereceğiz. Öncelikle bir WPF uygulaması oluşturacağız ve proje referanslarına "C:\Program Files\Microsoft SDKs\Kinect\v1.5\Assemblies" klasöründe yer alan "Microsoft.Kinect.dll" dosyasını ekleyeceğiz. Bu referans ile uygulamamız Kinect'e ait özelliklere ulaşabilecek.

Arayüz tasarımı aşamasında, MainWindow'un tasarımına derinlik görüntüsünü gösterecek "imgDepthFrame" isminde bir image elementi ekleyeceğiz. MainWindow'un tasarım kodları örnekteki gibi olacak:

[XAML] MainWindow.xaml

<Window x:Class="Kinect104_Depth.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Kinect 104: Derinlik Görüntüsü" Height="522" Width="660"
        WindowStartupLocation="CenterScreen"
        Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <Image Name="imgDepthFrame" Stretch="Uniform" />
    </Grid>
</Window>

Bu tasarım bize aşağıdaki görüntüyü verecek:

-

Şimdi derinlik bilgisini görüntüye çevirecek kodları ekleyeceğiz. Uygulamamız çalıştırıldığında sisteme bağlı ilk Kinect'i başlatacak, derinlik akışını belirlediğimiz çözünürlükte almak üzere yapılandıracak ve "Kinect_DepthFrameReady" eventi her tetiklendiğinde derinlik görüntüsünü güncelleyecek. Uygulama kapanırken de sisteme bağlı Kinect'leri durduracak. Bu işlemleri gerçekleştirecek kodlarımız aşağıdaki gibi olacak:

[C#] MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Kinect;
 
namespace Kinect104_Depth
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        // Her bir noktanın derinlik değerini tutacak short dizisi:
        private short[] depthPixelData;
 
        // Image elementinin kaynağı olarak atanacak görüntü:
        private WriteableBitmap outputImage;
 
        // Görüntü biçimi değiştirilirse, depthPixelData ve outputImage boyutlarını da
        // değiştirmemiz gerekiyor. Performans açısından, her frame için boyutları
        // yeniden belirlemek yerine, son görüntü biçimiyle yeni görüntü biçimini
        // karşılaştırıyoruz. Yalnızca aralarında fark varsa boyutları değiştiriyoruz.
 
        // Karşılaştırmayı yapacağımız derinlik görüntüsü biçimi:
        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:
            if (KinectSensor.KinectSensors.Count > 0)
            {
                // Sisteme bağlı Kinect'lere, KinectSensors dizisinden ulaşıyoruz.
                // İlk Kinect'i başlat:
                KinectSensor.KinectSensors[0].Start();
 
                // Derinlik bilgisi akışını 640x480 30fps biçiminde başlat:
                KinectSensor.KinectSensors[0].DepthStream.Enable(
                    DepthImageFormat.Resolution640x480Fps30);
 
                // Yeni görüntü geldiğinde tetiklenecek event handler'ı oluştur:
                KinectSensor.KinectSensors[0].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 biçimi değiştiyse:
                    if (haveNewFormat)
                    {
                        // outputImage'ın özelliklerini değiştir:
                        outputImage = new WriteableBitmap(
                            depthFrame.Width, // Genişlik
                            depthFrame.Height, // Yükseklik
                            96, // Yatay DPI
                            96, // Dikey DPI
                            PixelFormats.Gray16, // Piksel biçimi
                            null); // Bitmap paleti
 
                        // Image elementinin kaynağını outputImage olarak belirle:
                        imgDepthFrame.Source = outputImage;
                    }
 
                    // outputImage'ın içeriğini güncelle:
                    outputImage.WritePixels(
                        new Int32Rect(0, 0, depthFrame.Width, depthFrame.Height),
                        depthPixelData,
                        depthFrame.Width * depthFrame.BytesPerPixel,
                        0);
 
                    // 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(ler) sisteme bağlıysa:
            if (KinectSensor.KinectSensors.Count > 0)
            {
                // Tüm Kinect'leri durdur:
                foreach (KinectSensor sensor in KinectSensor.KinectSensors)
                    sensor.Stop();
            }
        }
    }
}

Uygulamayı çalıştırdığınızda, sensöre yakın noktaların koyu, uzak noktaların da açık renk aldığını göreceksiniz.

-

Sensöre çok yakın noktalar siyah, algılanamayan noktalar ise beyaz renk ile temsil edilir.

Geliştirdiğimiz uygulama ile derinlik verisinin nasıl renge çevrildiğini özetledik. Derinlik konusunda daha detaylı uygulamalara ilerleyen yazılarımızda değineceğiz...


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

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