Home TürkçeC# Kinect, Arka plan & Oyuncu Renklendirme

Kinect, Arka plan & Oyuncu Renklendirme

by Fatih Boy
0 comment

   Kinect makale serisinde en son derinlik ve video akışlarını beraber kullanmaya başlayarak oyuncu görüntüsünü farklı bir arka plan üzerine koyabilmiştik. İki farklı veri akışını birleştirdiğimiz bu işlem Kinect’i daha güçlü kullanabilmek adına önemli bir adım. Bu makalemde bunu bir adım daha ileri taşıyarak ayıkladığımız arka plan ve/veya oyuncu görüntüsü üzerinde resim işleme yöntemlerini kullanıyor olacağız.

   İlk örneğimde arka plan resmini gri tonlarda tutarken, oyuncuları normal renkleriyle bırakıyor olacağım.  Bu sayede oyuncularımızı daha vurgulamış olacağız. Hatırlarsanız Kinect ile Uzaya Çıkıyoruz başlıklı makalemde video akışını analiz ederek sadece oyuncuya ait olan piksellerin görüntülenmesini sağlamıştık, bir başka makalemde de renkli bir görüntüyü gri tonlanmış hale dönüştürmüştük. Makaleme bu iki makalemde paylaştıklarımı okuduğunuz varsayımıyla devam ediyor olacağım; bu yüzden, henüz bu iki makalemi okumadıysanız daha fazla devam etmeden önce okumanızın tam zamanı.

   Önceki kodumuzu hatırlayacak olursanız, her bir derinlik veri akışında gelen byte dizisini sonradan kullanmak üzere bir değişkende saklamıştık. Daha sonrasından da bu bilgisi her bir video veri akışından kullanmıştık. Aşağıdaki satırlar bize işlem yapmakta olduğumuz pikselin bir oyuncuya ait olup olmadığını kontrol etme şansı vermekteydi;

int oyuncu = derinlikVerisi[veriIndeksi] & 0x07;

  Oyuncu değişkeninin sıfırdan farklı bir değere sahip olması durumunda ilgili pikseller kullanılmakta, aksi durumlarda ise göz ardı etmekteydi;

int oyuncu = derinlikVerisi[veriIndeksi] & 0x07;
if (oyuncu > 0) {
    var pikselIndeksi = ((genislik - x - 1) + yukseklikOfseti) * 4;
 
    int xKordinati;
    int yKordinati;
 
    kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(e.ImageFrame.Resolution,
e.ImageFrame.ViewArea, x, y,
(short)(derinlikVerisi[veriIndeksi] | (derinlikVerisi[veriIndeksi + 1] << 8)),
out xKordinati,
out yKordinati);

    var videoPikselIndeksi = (xKordinati + (yKordinati * e.ImageFrame.Image.Width)) << 2; //(xKordinati + (yKordinati * e.ImageFrame.Image.Width)) * 4

    bitmap[pikselIndeksi] = videoGoruntusu[videoPikselIndeksi];
    bitmap[pikselIndeksi + 1] = videoGoruntusu[videoPikselIndeksi + 1];
    bitmap[pikselIndeksi + 2] = videoGoruntusu[videoPikselIndeksi + 2];
    bitmap[pikselIndeksi + 3] = (byte)255;
}

   Oyuncu görüntüsünün renkli, arka planın ise gri tonlanmasını istediğimiz yeni senaryomuzda ise yapacağımız şey; oyuncuya ait pikselleri yine aynı şekilde bitmap byte dizimizin ilgili indeksinde saklarken, arka plana ait piksellerin gri tonlama sonrasında ilgili indekste saklamak olmalı. Kullanacağımız gri ton’u ise aşağıdaki kadar basit bir kodla hesaplayabiliriz;

var griTon = (byte)(((int)videoGoruntusu[videoPikselIndeksi + 2] * .3) +
                    ((int)videoGoruntusu[videoPikselIndeksi + 1] * .59) +
                    ((int)videoGoruntusu[videoPikselIndeksi] * .11));

   Ardından da bu gri ton’u pikselin her bir renk kanalında kullanmalıyız;

bitmap[pikselIndeksi] = griTon;
bitmap[pikselIndeksi + 1] = griTon;
bitmap[pikselIndeksi + 2] = griTon;

   Bu kadar basit…

Derinlik bilgisi yardımıyla arka plan görüntüsü  gri tonlanabilir

   Kodun kalanı ise önceki makalemizle tamamen aynı kalacak. Nihai kodumuz ise aşağıdaki şekilde olacaktır;

namespace Com.Enterprisecoding.MerhabaKinect {
    public partial class MainWindow : Window {
private Runtime kinect;
private byte[] derinlikVerisi;

public MainWindow() {
InitializeComponent();
kinect = new Runtime();
}

private void Window_Loaded(object sender, RoutedEventArgs e) {
kinect.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);

kinect.VideoFrameReady += kinect_VideoFrameReady;
kinect.DepthFrameReady += kinect_DepthFrameReady;

kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
}

private void kinect_VideoFrameReady(object sender, ImageFrameReadyEventArgs e) {
if (derinlikVerisi == null) return;

var genislik = 320;
var yukseklik = 240;
var videoGoruntusu = e.ImageFrame.Image.Bits;

var bitmap = new byte[genislik * yukseklik << 2]; // genislik * yukseklik * 4

for (int y = 0, veriIndeksi = 0; y < yukseklik; y++) {
var yukseklikOfseti = y * genislik;

for (var x = 0; x < genislik; x++, veriIndeksi += 2) {
var pikselIndeksi = ((genislik - x - 1) + yukseklikOfseti) * 4;

int xKordinati;
int yKordinati;

kinect.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(e.ImageFrame.Resolution,
e.ImageFrame.ViewArea, x, y,
(short)(derinlikVerisi[veriIndeksi] | (derinlikVerisi[veriIndeksi + 1] << 8)),
out xKordinati,
out yKordinati);

var videoPikselIndeksi = (xKordinati + (yKordinati * e.ImageFrame.Image.Width)) << 2; //(xKordinati + (yKordinati * e.ImageFrame.Image.Width)) * 4
int oyuncu = derinlikVerisi[veriIndeksi] & 0x07;

if (oyuncu != 0) {
bitmap[pikselIndeksi] = videoGoruntusu[videoPikselIndeksi];
bitmap[pikselIndeksi + 1] = videoGoruntusu[videoPikselIndeksi + 1];
bitmap[pikselIndeksi + 2] = videoGoruntusu[videoPikselIndeksi + 2];
} else {
var griTon = (byte)(((int)videoGoruntusu[videoPikselIndeksi + 2] * .3) +
((int)videoGoruntusu[videoPikselIndeksi + 1] * .59) +
((int)videoGoruntusu[videoPikselIndeksi] * .11));

bitmap[pikselIndeksi] = griTon;
bitmap[pikselIndeksi + 1] = griTon;
bitmap[pikselIndeksi + 2] = griTon;
}

bitmap[pikselIndeksi + 3] = (byte)255;
}
}

derinlikVideo.Source = BitmapSource.Create(genislik, yukseklik, 96, 96, PixelFormats.Bgra32, null, bitmap, (genislik * PixelFormats.Bgra32.BitsPerPixel) >> 3);
}

private void kinect_DepthFrameReady(object sender, ImageFrameReadyEventArgs e) {
derinlikVerisi = e.ImageFrame.Image.Bits;
}

private void Window_Closed(object sender, System.EventArgs e) {
kinect.Uninitialize();
} 
}
}

   Uygulamamızın arka plan yerine oyuncumuzu gri tonlarda göstermesini istersek yapacağımız tek değişiklik ise if ifadesinde sıfıra eşit olma durumunu kontrol etmek olacak.

Derinlik bilgisi yardımıyla oyuncu görüntüsü  gri tonlanabilir

    Kinect derinlik ve video akışıyla arka plan görüntüsü ile oynamaya bir başka örnek de arka planı negatif olarak göstermek olacaktır. Bir görüntünün negatifinin nasıl alınabileceğini sizlerle paylaştığım makalemi yukarıdaki kod ile birleştirecek olursak kolaylıkla aşağıdaki görüntüyü elde edebiliriz;

Derinlik bilgisi yardımıyla arka plan görüntüsünün negatifi alınabilir

   Kodumuzu önceki makalemde de belirttiğim gibi TPL (Task Parallel Library) ile gelen Parallel.For yardımıyla daha performanslı hale getirebilmemiz de mümkün.

   Gördüğünüz gibi, Kinect derinlik ve video akışlarını görüntü işleme teknikleri ile birleştirdiğimizde ortaya oldukça yaratıcı uygulamalar çıkabilir.

Şu Yazıları da Sevebilirsiniz

Leave a Comment

* Bu formu kullanarak, verilerinizin bu web sitesi tarafından saklanması ve kullanılmasını kabul ediyorsunuz.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Bu web sitesi deneyiminizi geliştirmek için çerezleri kullanır. Bunu kabul ettiğinizi varsayacağız, ancak isterseniz vazgeçebilirsiniz. Kabul Et Daha Fazla Bilgi