В этом посте я хочу описать, как распознавать лица на изображении с помощью Android. Я использую камеру, чтобы получить изображение, а затем приложение нарисует прямоугольник вокруг лиц, обнаруженных на изображении. Для этого мы просто используем Android API, например:
- FaceDetector используется для обнаружения лица в растровом изображении
- Объект Face , содержащий информацию об обнаруженном лице
Поэтому мы должны сделать три шага в наших приложениях:
- Сделай снимок
- Определить лица на картинке
- Рисует прямоугольники вокруг обнаруженных лиц
Сделайте снимок на камеру с помощью Android
Этот шаг довольно прост, потому что мы должны просто вызвать намерение и подготовиться к получению результата. Намерение очень простое:
|
1
2
|
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(cameraIntent, CAMERA_RETURN_CODE); |
Чтобы получить результат (снимок сделан), мы должны переопределить метод в нашей деятельности:
|
1
2
3
4
5
6
|
@Overrideprotected 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, настроенный в нашей среде разработки. В этом случае убедитесь, что вы настроили камеру для использования:
Запустив пример и посмотрев журнал, мы имеем: ![Immagine [4]](/wp-content/uploads/images/jcg/c7b39a509e831b6678685fa0160689fa.png)
Мы замечаем, что приложение обнаружило одно лицо, в то время как другие равны нулю, поскольку на картинке больше нет лиц.
Нарисуйте прямоугольники вокруг обнаруженных лиц
Последний шаг — рисование прямоугольников вокруг обнаруженных лиц. В этом случае мы можем использовать полученную ранее информацию следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@Overrideprotected 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 эмулируемая камера [4]](/wp-content/uploads/images/jcg/f7745339bbc95c0dbd3c89ce9749bed1.png)
![Immagine2 [4]](/wp-content/uploads/images/jcg/660f5c0a46c9988578ddc337e33c7a3c.png)