Статьи

Android распознает лицо

В этом посте я хочу описать, как распознавать лица на изображении с помощью Android. Я использую камеру, чтобы получить изображение, а затем приложение нарисует прямоугольник вокруг лиц, обнаруженных на изображении. Для этого мы просто используем Android API, например:

  • FaceDetector используется для обнаружения лица в растровом изображении
  • Объект Face , содержащий информацию об обнаруженном лице

Поэтому мы должны сделать три шага в наших приложениях:

  • Сделай снимок
  • Определить лица на картинке
  • Рисует прямоугольники вокруг обнаруженных лиц

Android эмулируемая камера [4]

Сделайте снимок на камеру с помощью Android

Этот шаг довольно прост, потому что мы должны просто вызвать намерение и подготовиться к получению результата. Намерение очень простое:

1
2
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_RETURN_CODE);

Чтобы получить результат (снимок сделан), мы должны переопределить метод в нашей деятельности:

1
2
3
4
5
6
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAMERA_RETURN_CODE) {
        Bitmap cameraBmp = (Bitmap) data.getExtras().get("data");       
    }
}

В строке 4 мы получаем наше изображение, используя дополнительные с ключом данных.

Определить лица на картинке

На этом этапе мы используем API, поставляемый с Android SDK начиная с уровня 1. Для реализации нашей логики мы создаем пользовательский компонент, который расширяет
ImageView , мы называем это FaceImageView .

1
2
3
public class FaceImageView extends ImageView {
...
}

Чтобы обнаружить лица, сначала нужно преобразовать изображение в растровое изображение в формат 556, иначе мы не сможем использовать изображение, как указано в API, поэтому имеем:

1
Bitmap tmpBmp = image.copy(Config.RGB_565, true);

Теперь у нас есть изображение в правильном формате, мы создаем экземпляр FaceDetector:

1
FaceDetector faceDet = new FaceDetector(tmpBmp.getWidth(), tmpBmp.getHeight(), MAX_FACES);

передавая ширину и высоту изображения, а также количество лиц, которые мы хотим обнаружить (в нашем случае это просто константа). Теперь мы вызываем метод findFaces для обнаружения лиц, в результате чего мы ожидаем массив экземпляра Face, который должен иметь длину, равную количеству лиц, которые мы хотим обнаружить:

1
faceDet.findFaces(tmpBmp, faceList);

где faceList — это наш массив.

Теперь мы должны проанализировать каждый элемент в нашем массиве и получить результат. Мы просто хотим получить среднюю точку лица и расстояние между глазами . Мы используем эти две информации, чтобы нарисовать прямоугольник для каждого обнаруженного лица:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
for (int i=0; i < faceList.length; i++) {
    Face face = faceList[i];
    Log.d("FaceDet", "Face ["+face+"]");
    if (face != null) {
        Log.d("FaceDet", "Face ["+i+"] - Confidence ["+face.confidence()+"]");
        PointF pf = new PointF();
        face.getMidPoint(pf);
        Log.d("FaceDet", "\t Eyes distance ["+face.eyesDistance()+"] - Face midpoint ["+pf+"]");
        RectF r = new RectF();
        r.left = pf.x - face.eyesDistance() / 2;
        r.right = pf.x + face.eyesDistance() / 2;
        r.top = pf.y - face.eyesDistance() / 2;
        r.bottom = pf.y + face.eyesDistance() / 2;
        rects[i] = r;
    }
}

В строке (9-13) мы вычисляем вершину прямоугольника и сохраняем их в объекте RectF. Если мы хотим запустить приложение, мы можем использовать реальный смартфон или AVD, настроенный в нашей среде разработки. В этом случае убедитесь, что вы настроили камеру для использования:

Immagine2 [4]

Запустив пример и посмотрев журнал, мы имеем: Immagine [4]

Мы замечаем, что приложение обнаружило одно лицо, в то время как другие равны нулю, поскольку на картинке больше нет лиц.

Нарисуйте прямоугольники вокруг обнаруженных лиц

Последний шаг — рисование прямоугольников вокруг обнаруженных лиц. В этом случае мы можем использовать полученную ранее информацию следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Override
protected void onDraw(Canvas canvas) {       
    super.onDraw(canvas);
    Paint p = new Paint();
 
    canvas.drawBitmap(image, 0, 0, p);
    Paint rectPaint = new Paint();
    rectPaint.setStrokeWidth(2);
    rectPaint.setColor(Color.BLUE);
    rectPaint.setStyle(Style.STROKE);
 
    for (int i=0; i < MAX_FACES; i++) {
        RectF r = rects[i];
        if (r != null)
            canvas.drawRect(r, rectPaint);
    }
}
  • Доступен исходный код @ github

Справка: Android Detect Face от нашего партнера JCG Франческо Аццолы в блоге Surviving с Android .