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.
(Test resmini TÜBİTAK projesinde de kullandığım Caltech face database adlı yüz veritabanından aldım.)
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:
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.
Ş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.
Ş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.