Facebook RSS Feed
 
Kinect & Leap Motion: Kinect ile Fotoğraf Kaydı
Tarih: 12.08.2012, Platform: .NET 4.5, IDE: Visual Studio 2012, Level: 200



Yazı dizimizin ilk 4 çalışmasında Kinect'in görüntü ve iskelet akışlarını inceledikten sonra, birkaç demo ile bu akışların kullanım senaryolarına göz atacağız. İlk demomuz renkli görüntü akışını kaydetmek üzerine olacak. Bazı Xbox oyunlarının heyecanlı noktalarda fotoğrafımızı çekip oyun sonunda gösterdiği gibi, biz de sağ elimizi kaldırdığımızda fotoğrafımızı çeken bir uygulama geliştireceğiz.

Öngereksinimler

Uygulamayı geliştirmek için, Kinect sensörüne ve www.kinectforwindows.com adresinden indirebileceğiniz Kinect SDK'ya gereksiniminiz olacak. Başlamadan önce, Kinect 102: Renkli Görüntüye Ulaşım ve Kinect 103: İskelet Yapısına Ulaşım başlıklarına göz atmanız faydalı olacaktır.

Uygulama

Örnek uygulamamızı iki aşamada geliştireceğiz. İlk aşamada, butona tıklandığında renkli görüntünün kaydedilmesini ele alacağız. İkinci aşamada ise, yazdığımız kodu geliştirerek iskelet algılaması ile el kaldırınca görüntüyü kaydettireceğiz...

Adım 1: Buton ile Fotoğraf Çekimi

Başlamak için, Visual Studio ile WPF uygulaması oluşturduktan sonra, proje referanslarına "Microsoft.Kinect.dll" dosyasını ekleyelim. İlk adımda ana penceremizin tasarımına "imgColorFrame" adında bir Image ve "btnSnapshot" adında bir buton ekleyeceğiz...

[XAML] MainWindow.xaml

<Window x:Class="KinectFotograf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Kinect Fotoğraf" Height="548" Width="640"
        WindowStartupLocation="CenterScreen"
        Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <Image Name="imgColorFrame" Stretch="Uniform" Margin="0,0,0,42" />
        <Button Name="btnSnapshot" Content="Fotoğraf Kaydet" HorizontalAlignment="Left"
                Margin="10,0,0,10" VerticalAlignment="Bottom" Width="115"
                Click="btnSnapshot_Click"/>
    </Grid>
</Window>

Bu tasarım bize Kinect'in gözünden renkli görüntüyü gösterecek ve butona tıkladığımızda fotoğraf çekmemize aracı olacak.

Uygulamamızın işleyişi sırasında saniyede 30 defa Kinect_ColorFrameReady eventi tetiklenecek. Event Arguments'dan elde edeceğimiz renkli görüntü dizisini, Kinect 102: Renkli Görüntüye Ulaşım uygulamasındaki mantıkla WritableBitmap'e çevireceğiz ve Image üzerinde göstereceğiz.

Fotoğraf Kaydet butonuna tıkladığımızda, savePictureFrame değişkenine true değeri atanacak. Kinect_ColorFrameReady eventi her tetiklendiğinde, görüntü bilgisini işledikten sonra savePictureFrame'i kontrol edeceğiz. True değerini almışsa, o anki görüntüyü BitmapEncoder ile istediğimiz biçimde (BMP, JPEG, PNG…) işleyeceğiz ve FileStream kullanarak diske kaydedeceğiz...

[C#] MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Kinect;
 
namespace KinectFotograf
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private byte[] pixelData;
        private WriteableBitmap outputImage;
        private ColorImageFormat lastImageFormat = ColorImageFormat.Undefined;
        private bool savePictureFrame = false;
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Sisteme Kinect bağlıysa, ilk Kinect'i yapılandır
            if (KinectSensor.KinectSensors.Count > 0)
            {
                KinectSensor.KinectSensors[0].Start();
                KinectSensor.KinectSensors[0].ColorStream.Enable
                    (ColorImageFormat.RgbResolution1280x960Fps12);
                KinectSensor.KinectSensors[0].ColorFrameReady
                    += new EventHandler<ColorImageFrameReadyEventArgs>(Kinect_ColorFrameReady);
            }
        }
 
        private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            // Gelen görüntü bilgisini açıp imageFrame'e aktar
            using (ColorImageFrame imageFrame = e.OpenColorImageFrame())
            {
                // Görüntü varsa...
                if (imageFrame != null)
                {
                    // Önceki görüntü biçimi ile yeni gelen görüntü biçimi farklı mı?
                    bool haveNewFormat = lastImageFormat != imageFrame.Format;
 
                    // Görüntü biçimi değiştiyse...
                    if (haveNewFormat)
                    {
                        // Yeni görüntü boyutuna göre pixelData dizisini boyutlandır
                        pixelData = new byte[imageFrame.PixelDataLength];
                    }
 
                    // Görüntüyü pixelData dizisine aktar
                    imageFrame.CopyPixelDataTo(pixelData);
 
                    // Görüntü biçimi değiştiyse...
                    if (haveNewFormat)
                    {
                        // Image elementinin kaynağı olarak gösterilen outputImage'ın
                        // özelliklerini değiştir
                        outputImage = new WriteableBitmap(
                            imageFrame.Width,
                            imageFrame.Height,
                            96,
                            96,
                            PixelFormats.Bgr32,
                            null);
 
                        // Image elementinin kaynağını outputImage olarak belirle
                        imgColorFrame.Source = outputImage;
                    }
 
                    // outputImage'ın içeriğini güncelle
                    outputImage.WritePixels(
                        new Int32Rect(0, 0, imageFrame.Width, imageFrame.Height),
                        pixelData,
                        imageFrame.Width * 4,
                        0);
 
                    // (İstenmişse) görüntüyü kaydet...
                    if (savePictureFrame)
                    {
                        // Görüntüyü kaydet
                        SavePicture();
 
                        // Tetikleyici değişkeni pasifleştir
                        savePictureFrame = false;
                    }
 
                    // Bir sonraki görüntü biçimi karşılaştırması için, yeni görüntü
                    // biçimini kaydet
                    lastImageFormat = imageFrame.Format;
                }
            }
        }
 
        private void SavePicture()
        {
            // Görüntü dosyasını diske yazacak FileStream oluştur
            using (FileStream stream = new FileStream(@"C:\Temp\KinectPicture.bmp"FileMode.Create))
            {
                // Görüntüyü farklı biçimlerde kaydedebiliyoruz. (BMP, JPEG, PNG...)
                // Kaydedilmek istenen görüntü türüne göre Bitmap Encoder oluştur
                BmpBitmapEncoder encoder = new BmpBitmapEncoder();
                //JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                //PngBitmapEncoder encoder = new PngBitmapEncoder();
 
                // outputImage'ı Bitmap olarak çöz ve encoder'a aktar
                encoder.Frames.Add(BitmapFrame.Create(outputImage));
 
                // Görüntü dosyasını kaydet
                encoder.Save(stream);
 
                // FileStream'i sonlandır
                stream.Close();
            }
        }
 
        private void btnSnapshot_Click(object sender, RoutedEventArgs e)
        {
            // Fotoğrag çekmek için tetikleyici değişkeni etkinleştir
            savePictureFrame = true;
        }
 
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Uygulama kapanırken tüm Kinect'leri durdur...
            if (KinectSensor.KinectSensors.Count > 0)
            {
                foreach (KinectSensor sensor in KinectSensor.KinectSensors)
                    sensor.Stop();
            }
        }
    }
}

Geliştirdiğimiz bu uygulamayı çalıştırdığınızda, Fotoğraf Kaydet butonu ile Kinect’den gelen renkli görüntüyü kaydedebileceksiniz. Görüntü biçimini değiştirmek isterseniz, SavePicture metodunda encoder'ların oluşturulduğu satırlardaki istenilen encoder'a ait satırı uncomment yapın.

Adım 2: Hareket ile Fotoğraf Çekimi

İkinci adımda Kinect'in iskelet tanıma yeteneğini kullanacağız: Sağ elimizi kaldırdığımızda o anki görüntüyü kaydettireceğiz. Önceki adımda geliştirdiğimiz tasarıma "chkNui" isimli bir CheckBox ekleyelim. Bu CheckBox seçili olduğunda hareket ile fotoğraf çekimi etkinleşecek.

-

[XAML] MainWindow.xaml

<Window x:Class="KinectFotograf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Kinect Fotoğraf" Height="548" Width="640"
        WindowStartupLocation="CenterScreen"
        Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <Image Name="imgColorFrame" Stretch="Uniform" Margin="0,0,0,42" />
        <Button Name="btnSnapshot" Content="Fotoğraf Kaydet" HorizontalAlignment="Left"
                Margin="10,0,0,10" VerticalAlignment="Bottom" Width="115"
                Click="btnSnapshot_Click"/>
        <CheckBox Name="chkNui" Content="NUI" HorizontalAlignment="Left"
                  Margin="140,0,0,13" Height="16" VerticalAlignment="Bottom"/>
    </Grid>
</Window>

Uygulama kodlarımıza, detaylarına Kinect 103: İskelet Yapısına Ulaşım yazısından ulaşabileceğiniz iskelet tanıma fonksiyonunu ekleyeceğiz. Kinect_SkeletonFrameReady eventi her tetiklendiğinde, CheckBox seçiliyse ve sağ el pozisyonu baş pozisyonundan yüksekse SavePicture metodu ile görüntü kaydedilecek.

Sağ el ile baş pozisyonlarının karşılaştırmasını, her iki eklemin Y pozisyonunu karşılaştırarak gerçekleştiriyoruz. Basitçe, sağ elin Y pozisyonu başın Y pozisyonundan büyükse, elin havaya kaldırıldığını anlıyoruz.

[C#] MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Kinect;
 
namespace KinectFotograf
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private Skeleton[] skeletons = new Skeleton[6];
        private Skeleton skeleton;
        private byte[] pixelData;
        private WriteableBitmap outputImage;
        private ColorImageFormat lastImageFormat = ColorImageFormat.Undefined;
        private bool savePictureFrame = false;
 
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Sisteme Kinect bağlıysa, ilk Kinect'i yapılandır
            if (KinectSensor.KinectSensors.Count > 0)
            {
                KinectSensor.KinectSensors[0].Start();
 
                // Renkli görüntü
                KinectSensor.KinectSensors[0].ColorStream.Enable
                    (ColorImageFormat.RgbResolution1280x960Fps12);
                KinectSensor.KinectSensors[0].ColorFrameReady
                    += new EventHandler<ColorImageFrameReadyEventArgs>(Kinect_ColorFrameReady);
 
                // İskelet verisi
                TransformSmoothParameters tsp = new TransformSmoothParameters();
                tsp.Smoothing = 0.55f;
                tsp.Correction = 0.1f;
                tsp.Prediction = 0.1f;
                tsp.JitterRadius = 0.4f;
                tsp.MaxDeviationRadius = 0.4f;
 
                KinectSensor.KinectSensors[0].SkeletonStream.Enable(tsp);
                KinectSensor.KinectSensors[0].SkeletonFrameReady
                    += new EventHandler<SkeletonFrameReadyEventArgs>(Kinect_SkeletonFrameReady);
            }
        }
 
        private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            // Gelen görüntü bilgisini açıp imageFrame'e aktar
            using (ColorImageFrame imageFrame = e.OpenColorImageFrame())
            {
                // Görüntü varsa...
                if (imageFrame != null)
                {
                    // Önceki görüntü biçimi ile yeni gelen görüntü biçimi farklı mı?
                    bool haveNewFormat = lastImageFormat != imageFrame.Format;
 
                    // Görüntü biçimi değiştiyse...
                    if (haveNewFormat)
                    {
                        // Yeni görüntü boyutuna göre pixelData dizisini boyutlandır
                        pixelData = new byte[imageFrame.PixelDataLength];
                    }
 
                    // Görüntüyü pixelData dizisine aktar
                    imageFrame.CopyPixelDataTo(pixelData);
 
                    // Görüntü biçimi değiştiyse...
                    if (haveNewFormat)
                    {
                        // Image elementinin kaynağı olarak gösterilen outputImage'ın
                        // özelliklerini değiştir
                        outputImage = new WriteableBitmap(
                            imageFrame.Width,
                            imageFrame.Height,
                            96,
                            96,
                            PixelFormats.Bgr32,
                            null);
 
                        // Image elementinin kaynağını outputImage olarak belirle
                        imgColorFrame.Source = outputImage;
                    }
 
                    // outputImage'ın içeriğini güncelle
                    outputImage.WritePixels(
                        new Int32Rect(0, 0, imageFrame.Width, imageFrame.Height),
                        pixelData,
                        imageFrame.Width * 4,
                        0);
 
                    // (İstenmişse) görüntüyü kaydet...
                    if (savePictureFrame)
                    {
                        // Görüntüyü kaydet
                        SavePicture();
 
                        // Tetikleyici değişkeni pasifleştir
                        savePictureFrame = false;
                    }
 
                    // Bir sonraki görüntü biçimi karşılaştırması için, yeni görüntü
                    // biçimini kaydet
                    lastImageFormat = imageFrame.Format;
                }
            }
        }
 
        private void Kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            try
            {
                // Gelen iskelet verisini skeletons dizisine kopyala
                if (e.OpenSkeletonFrame() != null) e.OpenSkeletonFrame().CopySkeletonDataTo(skeletons);
 
                // İlk algılanan iskeleti seç
                skeleton = (from s in skeletons
                            where s.TrackingState == SkeletonTrackingState.Tracked
                            select s).FirstOrDefault();
            }
            catch (Exception)
            {
                // Hata oluşursa skeleton'un parametrelerini temizle.
                // Bu frame'de veri işlemesi yapmayacağız.
                skeleton = null;
            }
 
            // İskelet algılanmışsa...
            if (skeleton != null)
            {
                // NUI Checkbox'ı seçiliyse ve
                // Sağ elin dikey pozisyonu, baş seviyesinden yukarıdaysa...
                if (chkNui.IsChecked == true &&
                    skeleton.Joints[JointType.HandRight].Position.Y >
                    skeleton.Joints[JointType.Head].Position.Y)
                {
                    // Tek fotoğraf çekilmesi için NUI Checkbox'ın seçili özelliğini kaldır
                    chkNui.IsChecked = false;
 
                    // Fotoğraf çekmek için tetikleyici değişkeni etkinleştir
                    savePictureFrame = true;
                }
            }
        }
 
        private void SavePicture()
        {
            // Görüntü dosyasını diske yazacak FileStream oluştur
            using (FileStream stream = new FileStream(@"C:\Temp\KinectPicture.bmp"FileMode.Create))
            {
                // Görüntüyü farklı biçimlerde kaydedebiliyoruz. (BMP, JPEG, PNG...)
                // Kaydedilmek istenen görüntü türüne göre Bitmap Encoder oluştur
                BmpBitmapEncoder encoder = new BmpBitmapEncoder();
                //JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                //PngBitmapEncoder encoder = new PngBitmapEncoder();
 
                // outputImage'ı Bitmap olarak çöz ve encoder'a aktar
                encoder.Frames.Add(BitmapFrame.Create(outputImage));
 
                // Görüntü dosyasını kaydet
                encoder.Save(stream);
 
                // FileStream'i sonlandır
                stream.Close();
            }
        }
 
        private void btnSnapshot_Click(object sender, RoutedEventArgs e)
        {
            // Fotoğraf çekmek için tetikleyici değişkeni etkinleştir
            savePictureFrame = true;
        }
 
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Uygulama kapanırken tüm Kinect'leri durdur...
            if (KinectSensor.KinectSensors.Count > 0)
            {
                foreach (KinectSensor sensor in KinectSensor.KinectSensors)
                    sensor.Stop();
            }
        }
    }
}

Eklediğimiz kodlar ile uygulamayı çalıştırdığınızda -NUI CheckBox'ı seçiliyse- sağ elinizi kaldırdığınızda o anki görüntü kaydedilecek. Peşpeşe kaydı önlemek için kayıt sırasında CheckBox'ın IsChecked özelliğini false olarak değiştiriyoruz.

Geliştirdiğimiz bu uygulama, Kinect'in farklı 2 özelliğini birlikte kullandığımız temel bir başlangıç niteliğindeydi. Başlangıç çalışmalarımıza benzer uygulamalar ile devam edeceğiz...


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

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