Windows Phone 8 Kamera Görüntü İşleme 2 - Gerçek zaman C++ Gri Filtre

Bu yazımızda Windows Phone 8 kamerası ile elde edilen canlı görüntünün gerçek zamanda gri filtre ile işlenmesini anlatacağız. Daha önceki yazılarımızda bahsettiğimiz C++ ile yerel kod yazmak ve telefon kamerasından görüntü almak konularını ön bilgi olarak kullanıp, gerçek zamanda işleyeceğimiz görüntüyü yeni uygulamamızın ana sayfasında göstereceğiz. Gerçek zamanda görüntü işlemek performans gerektiren bir işlem olup genellikle alt seviye programla dilleri ile yapılmaktadır. Bunun yanı sıra kullanıcı dostu uygulama arayüzü geliştirmek için ise üst seviye diller kullanılmaktadır. Bu konu başlığı altında geliştireceğimiz uygulamamız iki projeden oluşturacağız. Gerçek zamanlı işlemleri gerçekleştirmek için kodunu C++ dilinde yazacağımız "Windows Phone Runtime Component" bileşeni - filtre modülü geliştireceğiz. Kullanıcı arayüzü ve filtre modülü ile iletişimi sağlayacak birimleri ise ana projemiz içerisinde geliştireceğiz. Filtre modülü gönderilen RGBA formatındaki görüntü verisini işleyip gri filtre uygulayacak. Görüntü verisi her biri "8 bit unsigned Integer" tipinde olan RGBA (Red, Green, Blue, Alpha = Kırmızı, Yeşik, Mavi, Alpha olmak üzere 4 tane "8 bit unsigned int" = 1 tane 32 bit Integer) sıralamasında pixel değerlerinden oluşan tek boyutlu bir dizidir. Bu veri işleme süreci her bir kamera görüntüsü için gerçek zamanda yapılacağından işlenen veri sonucundaki yeni değerleri bir kopyasını oluşturmadan yine aynı değişken içerisinde saklıyor olacağız. Yine performans kriterlerini gözeterek, filtre modülüne işlenecek verinin kopyasını değil hafıza adresini referans olarak göndereceğiz. Böylelikle uygulamamız kameradan gelen her bir görüntü karesini, bir kopyasını oluşturmadan mevcut hafıza adresini direkt modüle işlenmek üzere gönderecek, filtre işlemi de yeni bir kopya üzerinde değil, aynı hafıza alanı üzerinde yapılıyor olacak.

  

Resim 1: Görüntü filtresi "Windows Phone Runtime Component", ana uygulama ve kamera birimlerinin iletişimi.

 

Uygulamanın genel işleyiş senaryosu Resim 1'de anlatılmaktadır. Yapılan işlemler resimde kullanılan rakamlar ile sırasıyla:

1) Ana uygulamamız kamerayı başlatır ve seri olarak kameradan görüntü alır. Kamera yeni bir kare yakalayınca (yeni görüntü karesi elde edince) ana uygulamayı uyarır.

2) Ana uygulama uyarıldığında, kameradan gelen yeni görüntüyü ekranda gösterir. Devamında görüntü işleme filtresinin bulunduğu modülü çağırır.

3) Bu modüle parametre olarak int [ ] tipinde (tek boyutlu, her bir elemanı integer tipinde olan bir dizi) bir değişkeni referans olarak gönderir (kopyasını değil, hafıza adresini). Filtre modülü, kameradan gelen görüntünün bir kopyasını bu değişkenin içerisine yazar ve bu veriye Gri filtre uygular.

4) Bu değişken içerisinde veri, daha sonra ana uygulama ekranında gösterilmek üzere Image görsel bileşeninin veri kaynağı olan WritableBitmap değişkenine kopyalanır.

 

3. maddede bahsedilen tek boyutlu integer tipindeki diziyi görüntü karesi gibi resmetmek için 2 boyutlu bir matris şeklinde çizildi. Bu matris'teki herbir eleman görüntü pixel'ini temsil etmektedir. Bu iki boyutlu matrisin tek boyuta dönüşümü, tek boyutlu dizinin her bir integer elemanının (her bir pixel in) 8bit unsigned integer (RGBA bileşenlerinden oluşan pixel renk değeri) olarak açılımı Resim 2'de gösterilmiştir.

 

 Resim 2: n x m boyutlarındaki 2 boyutlu renkli görüntü verisinin, RGBA formatında tek boyutlu bir dizi olarak gösterimi.

 

Ana uygulamamızda kamera uygulaması örneğinde kullandığımız VideoBrush bileşenine ek olarak Image bileşeni kullanıyoruz. VideoBrush bileşeni önceki örnekte olduğu gibi kameradan gelen orijinal görüntüyü yansıtacak. Image bileşeni ise kameradan gelen görüntünün Windows Phone Runtime gerçek zamanda işlenip, işlenmiş görüntünün yansıtılacağı bileşendir.

 

1) m_yaz_veri adında WriteableBitmap tipinde bir nesne yaratıyoruz. Bu nesne ile istediğimiz boyutta görüntüyü oluşturabilecek, pixel değerleri üzerinde değişiklik yapabileceğiz. Ana sayfamızda yer alan görsel Image bileşeninin veri kaynağını m_yaz_veri olarak atıyoruz.

 

 iImgFilter1.Source = m_yaz_veri;  // Image görsel bileşenine verdiğimiz ad iImgFilter1

bu kod ile m_yaz_veri değişkeni üzerinde yapacağımız değişiklik anında görsel olarak ekrana yansıtılacak.

 

2) m_kamera_filtre = new Filtre();

satırı ile yeni bir Windows Phone Runtime bileşeni yaratıyoruz. Bu bileşen, içerisinde Gri Filtreleme kodunu yazdığımız bileşenimiz.

 

3) Gri filtre modülümüze telefonun kamerasına erişim için kullandığımız m_kamera bileşenini parametre olarak verip başlatıyoruz.

    m_kamera_filtre.Baslat(m_kamera);

 

4) Kamera yeni bir görüntü karesi yakaladığında uygulamamızda belirttiğimiz fonksiyonu (m_kare_mevcut) çağırması için aşağıdaki tanımlamayı yapıyoruz.

    m_kamera.PreviewFrameAvailable += m_kare_mevcut;

 

 5) Yeni bir görüntü karesi geldiğinde m_kare_mevcut metodu çağırılıyor ve bu metod içerisinde filter modülü uyarılıyor, mevcut görüntünün işlenmesi sağlanıyor ve işlenen görüntünün ekranda gösterilebilmesi için m_yaz_veri değişkenine kopyalanıyor.

       m_kamera_filtre.YeniGoruntuKaresi(m_goruntu_kare_veri);

       ...
       m_goruntu_kare_veri.CopyTo(m_yaz_veri.Pixels, 0);

6) Kodlamasını C++ dilinde yaptığımız gri filtre modülü içerisinde yer alan YeniGoruntuKaresi adındaki metodumuz, parametre olarak aldığı hafıza adresinin (frameData) gösterdiği alan içerisine kameradan gelen görüntüyü kopyalar.

   m_kamera->GetPreviewBufferArgb(frameData);

 Kopyalama işlemi için GetPreviewBufferArgb metodu kullanılır. Bu komut kamera önbelleğinde yer alan o anki görüntüyü belirtilen int [] tipindeki tek boyutlu dizi değişkeni içerisine kopyalar.

 

Bahsedilen işlemlerin tamamının yer aldığı çalışan bir örnek projeyi, kaynak kodları ile birlikte https://aka.ms/goruntuisleme2 adresinden indirebilirsiniz.

 

Güncelleme ve yeni konular için https://twitter.com/mustafakasap adresini takip edebilirsiniz.