MAY
8

Android ile Resimlerdeki Yüzlerin Bulunması

2 yorum | Kategori: Mobil Programlama | 08 Mayıs 2010 Cumartesi

Son 2 aydır yüksek lisans derslerine ek olarak, 2 ay önce başlayan ve benim de bir parçası olduğum TÜBİTAK tarafından desteklenen yüz tanıma konulu bir proje üzerinde yoğun olarak çalıştığım için burayla yine fazla ilgilenemedim. Projenin ilk aşaması olan resimlerdeki yüzlerin yerinin tespit edilmesi üzerine yaptığımız çalışmalardan esinlenerek Android'deki yüz bulma sınıfına bir göz atayım dedim ve basit bir uygulama yazdım. Bu yazımda da Android SDK ile birlikte gelen yüz bulma sınıfının bir resim üzerinde nasıl kullanılacağını aşağıdaki resimde çıktısını gördüğünüz bu uygulama üzerinde göstereceğim.smiley (Test resmini TÜBİTAK projesinde de kullandığım Caltech face database adlı yüz veritabanından aldım.)

Android ile yüz yanıma uygulamasının çıktısı

Uygulamanın amacı verilen resimdeki yüzlerin yerini bulup hepsinin üzerine resimde gördüğünüz kırmızı gözlükten oturtmak. İşe temiz bir Android projesi yaratarak başlıyoruz. Projeyi yaratırken istediğiniz SDK'yı hedefleyebilirsiniz. Ben şu anki en gücel SDK olan 2.1'i hedefleyecek şekilde yarattım. Projede varsayılan olarak eklenen şeylere ek olarak 2 şeye ihtiyacımız olacak. Bunlardan biri test amacıyla kullanacağımız resim, diğeri ise resimdeki yüzlerin üzerine oturtacağımız şeyin (bu örnekte gözlüğün) resmi. Benim kullandığım gözlük resimler şunlar:

test resmi

Gözlük resmi

Her iki resmi de  resources (res) klasörü altında yaratacağınız raw adlı klasöre koyulması gerekiyor. Bu işlem doğru bir şekilde yapılmışsa Eclipse içerisinde Package Explorer bölmesi aşağıdaki hali alacaktır.

Package Explorer

Şimdi sıra geldi kod yazmaya. Öncelikle gözlük işini bir kenara bırakıp resimdeki yüzlerin yerini bulup dikdörtgen içine alan Java kodunu veriyorum. Gerekli açıklamaları kod içerisinde yaptım, o yüzden ayrıca açıklama yapmayacağım.

package org.example;

import android.app.Activity;
import android.graphics.*;
import android.os.Bundle;
import android.widget.ImageView;
import android.media.FaceDetector;
import android.media.FaceDetector.Face;

public class FaceDet extends Activity {
    ImageView view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // İçerisinde yüz aranacak olan test resmini aç
        Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.raw.test).copy(Bitmap.Config.RGB_565, true);
        // Bitmap'ın üzerine çizebilmek için bir çizim yüzeyi oluştur
        Canvas canvas = new Canvas(bmp);
        // Çizim yaparken kullanılacak boyayı oluştur
        Paint paint = new Paint();
        paint.setARGB(255, 0, 255, 0);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        // Yüz bulma objesi yarat. Test resminin tamamında arama yapması için ilk 2 parametre olarak
        // resmin genişlik ve yüksekliğini verdik. Üçüncü parametre ise en fazla kaç tane yüz bulacağı
        FaceDetector detector = new FaceDetector(bmp.getWidth(), bmp.getHeight(), 10);
        // Bulunacak yüzleri tutacak olan diziyi yarat
        Face faces[] = new Face[10];
        // Yüzleri bul
        int facesFound = detector.findFaces(bmp, faces);
        // Bulunmuş olan her yüz için
        for (int i = 0; i < facesFound; i++)
        {
            // Bulunan yüzün orta noktasını (İki gözün orta noktası) bul
            PointF point = new PointF();
            faces[i].getMidPoint(point);
            // Yüzü 80x90'lık bir dikdörtgen içerisine al
            canvas.drawRect(new RectF(point.x - 40, point.y - 30, point.x + 40, point.y + 60), paint);
        }
        // Üzerine dikdörtgen(ler) çizilmiş olan resmi ekranda göster
        view = new ImageView(this);
        view.setImageBitmap(bmp);
        setContentView(view);
    }
}

Bu kod sonucunda üretilecek olan resim aşağıdaki gibi olacaktır.

Dikdörtgen içerisine alınmış yüz

Şimdi de resmin üzerine gözlük oturtan final versiyonun Java kodunu vereyim.

package org.example;

import android.app.Activity;
import android.graphics.*;
import android.os.Bundle;
import android.widget.ImageView;
import android.media.FaceDetector;
import android.media.FaceDetector.Face;

public class FaceDet extends Activity {
    ImageView view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // İçerisinde yüz aranacak olan test resmini aç
        Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.raw.test).copy(Bitmap.Config.RGB_565, true);
        // Gözlük resmini aç
        Bitmap glasses = BitmapFactory.decodeResource(this.getResources(), R.raw.glasses);
        // Bitmap'ın üzerine çizebilmek için bir çizim yüzeyi oluştur
        Canvas canvas = new Canvas(bmp);
        // Çizim yaparken kullanılacak boyayı oluştur
        Paint paint = new Paint();
        paint.setARGB(255, 0, 255, 0);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        // Yüz bulma objesi yarat. Test resminin tamamında arama yapması için ilk 2 parametre olarak
        // resmin genişlik ve yüksekliğini verdik. Üçüncü parametre ise en fazla kaç tane yüz bulacağı
        FaceDetector detector = new FaceDetector(bmp.getWidth(), bmp.getHeight(), 10);
        // Bulunacak yüzleri tutacak olan diziyi yarat
        Face faces[] = new Face[10];
        // Yüzleri bul
        int facesFound = detector.findFaces(bmp, faces);
        // Bulunmuş olan her yüz için
        for (int i = 0; i < facesFound; i++)
        {
            // Bulunan yüzün orta noktasını (İki gözün orta noktası) bul
            PointF point = new PointF();
            faces[i].getMidPoint(point);
            // Gözlük resminin ne kadar küçültüleceğini iki göz arasındaki mesafeye bakarak hesapla
            float scale = faces[i].eyesDistance() / 210.0f;
            // Gözlük resminin test resminde nerede çizilmesi gerektiğini hesapla
            float targetLeft = point.x - glasses.getWidth() / 2.0f * scale;
            float targetTop = point.y - glasses.getHeight() / 2.0f * scale;
            // Boyutu küçültülmüş gözlük resmini test resmi üzerinde olması gereken yere çiz
            canvas.drawBitmap(glasses, new Rect(0,0, glasses.getWidth(), glasses.getHeight()), new RectF(targetLeft, targetTop, targetLeft + glasses.getWidth() * scale, targetTop + glasses.getHeight() * scale), paint);
        }
        // Üzerine gözlük(ler) çizilmiş olan resmi ekranda göster
        view = new ImageView(this);
        view.setImageBitmap(bmp);
        setContentView(view);
    }
}

Eğer bu kodu benim kullandığım test resmi üzerinde çalıştırırsanız aşağıdaki sonuca ulaşacaksınız. Aynı kodu 10 veya daha fazla yüz içeren herhangi bir resim üzerinde kullanabilirsiniz. Daha fazlası için kodda gördüğünüz 10'ları değiştirmeniz gerekli. Son bir not olarak da fazla büyük test resimleri kullanmamanız gerektiğini, kullanmanız halinde işlemin oldukça uzun sürebileceğini ekleyeyim.

Android ile yüz bulup üzerine gözlük oturtmanın sonucu

Yorumlar

Bu yazı hakkında toplam 2 yorum bulunmaktadır. Siz de yorum ekleyebilirsiniz.
Yorum Cihan Tek | 29 Temmuz 2010 Perşembe 09:11:12
Sadece gözlerin koordinatlarını kullanarak burun ve dudağın koordinatlarını bulmak mümkün değil. Çünkü herkesin burun ve dudağı ile gözleri arasındaki mesafe farklı. Gözler arasındaki mesafeyi deneyerek (ya da internette araştırarak) bulacağınız bazı katsayılar ile çarparak belki yaklaşık koordinatlar bulmanız mümkün ancak o da her zaman doğru sonuç vermeyecektir.
Yorum burak cagatay alkan | 29 Temmuz 2010 Perşembe 09:00:52
Öncelikle calısmlarınızdan oturu tebrık edrım benım bır problemın var yapmıs oldugunuz kodlarda degısıklık yapık burun ve dedak ekledım ama gozun kodlarını benzer yapmama ragmen her resımde burun ve agız oturmuyor yardımlarınızı beklıyorum sımdıden tsk ederım

Yorum Yazın

İsim ve soyadınız : E-Posta adresiniz : Güvenlik kodu : Güvenlik Kodu Yorumunuz : Gönder