- 1. Обзор
- 2. FaceDetector API
- 3. Предварительные условия
- 4. Создание приложения
- Обновление build.gradle
- Обновление Google Play Services
- Создаем базовый пользовательский интерфейс
- Отредактируйте ваш AndroidManifest.xml
- Добавление распознавания лиц к вашему приложению
- 5. Написание кода приложения
- Загрузим изображение
- Создадим объект Paint
- Создадим объект Canvas
- Создадим Face Detector
- Рисование прямоугольников на лицах
- Результаты
- <<<Предыдущий урок Следующий урок>>>
1. Обзор
2. FaceDetector API
3. Предварительные условия
- Среда разработки Android Studio
- Android устройство, которое работает на Android 4.2.2 или более поздней версии — или — эмулятор Android (это доступно в Android Studio)
- Последняя версия Android SDK, включая компонент средств SDK. Вы можете получить это от Android SDK Manager в Android Studio.
- Google Play services SDK. Вы можете получить это в Android SDK Manager в Android Studio.
4. Создание приложения
Обновление build.gradle
dependencies { compile fileTree(dir: 'libs', include: ['*.jar'])}
Теперь нам нужно добавить сюда библиотеку Play services самой новой версии. Узнать последние версии всех библиотек можно по ссылке на нашем сайте fandroid.info. Найдите пункт «Gradle, please! Актуальные версии популярных библиотек».
Сейчас самая свежая версия библиотеки Play services 9.4. Копируем и вставляем в секцию зависимостей файла сборки нашего проекта.
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.0' compile 'com.google.android.gms:play-services:9.4.0' }
Обновление Google Play Services
Google Play services часто обновляется, чтобы получить последнюю версию, нажмите в Android Studio Tools > Android > SDK Manager:
Затем найдите запись для Google Play Services и убедитесь, что у вас стоит 26 или более поздней версии:
Создаем базовый пользовательский интерфейс
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="info.fandroid.facedetect.MainActivity"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/image"/> </RelativeLayout>
Отредактируйте ваш AndroidManifest.xml
Вы должны отредактировать файл AndroidManifest.xml, добавив такие строки:
<meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="face" />
Это гарантирует, что библиотеки для распознавания лиц будут доступны приложению.
Общий вид манифеста приложения:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.fandroid.facedetect"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" android:name="android.support.multidex.MultiDexApplication"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="face"/> </application> </manifest>
Добавление распознавания лиц к вашему приложению
Обычно в приложениях делают снимки с камеры устройства, или обрабатывают превью, полученное из камеры устройства. В конце статьи есть ссылка на проекты Google, с образцами такого кода.
Назовите его test1.jpg и добавьте в каталог res/drawable в файловой системе. Android Studio делает файл доступным в качестве ресурса, с идентификатором: R.drawable.test1
5. Написание кода приложения
Вот полный набор импортов классов, используемых в главном активити:
import android.app.Activity; import android.app.AlertDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.util.SparseArray; import android.view.View; import android.widget.Button; import android.widget.ImageView; import com.google.android.gms.vision.Frame; import com.google.android.gms.vision.face.Face; import com.google.android.gms.vision.face.FaceDetector;
Весь код пишем в методе onCreate. Это не совсем правильно с точки зрения архитектуры приложения, но для нашего упрощенного примера опустим эти условности.
Загрузим изображение
Начнем с загрузки изображения. Мы будем рисовать поверх изображения красный прямоугольник на любых обнаруженных лицах, поэтому мы должны убедиться, что растровое изображение является изменяемым. Сначала мы получаем дескриптор элемента ImageView для использования позже. Затем мы используем BitMapFactory для загрузки растрового изображения. Обратите внимание, что ресурс доступен с помощью ссылки R.drawable.test1. Если используется другое имя для изображения, нужно заменить test1 вашим именем.
ImageView myImageView = (ImageView) findViewById(R.id.imgview); BitmapFactory.Options options = new BitmapFactory.Options(); options.inMutable=true;Bitmap myBitmap = BitmapFactory.decodeResource( getApplicationContext().getResources(), R.drawable.test1, options);
Создадим объект Paint
myRectPaint
класса Paint, который мы будем использовать для рисования на изображении.Paint myRectPaint = new Paint(); myRectPaint.setStrokeWidth(5); myRectPaint.setColor(Color.RED); myRectPaint.setStyle(Paint.Style.STROKE);
Создадим объект Canvas
Далее создадим объект tempBitmap из оригинальной картинки, которую мы используем. Из этого мы можем создать объект класса Canvas и нарисовать Bitmap на нем.
Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565); Canvas tempCanvas = new Canvas(tempBitmap); tempCanvas.drawBitmap(myBitmap, 0, 0, null);
Создадим Face Detector
FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext()).setTrackingEnabled(false).build(); if(!faceDetector.isOperational()){ new AlertDialog.Builder(v.getContext()).setMessage("Could not set up the face detector!").show(); return;}
Frame frame = new Frame.Builder().setBitmap(myBitmap).build(); SparseArray<Face> faces = faceDetector.detect(frame);
Рисование прямоугольников на лицах
Таким образом, мы получаем массив лиц SparseArray. Можно выполнить итерацию массива для получения координаты ограничивающего прямоугольника для лица. API возвращает x, y координаты левого верхнего угла, а также ширину и высоту. Для отрисовки прямоугольника требуется x, y верхнего левого и нижнего правого углов, получаем их в результате несложных вычислений.
for (int i = 0; i < faces.size(); i++) { Face thisFace = faces.valueAt(i); float x1 = thisFace.getPosition().x; float y1 = thisFace.getPosition().y; float x2 = x1 + thisFace.getWidth(); float y2 = y1 + thisFace.getHeight(); tempCanvas.drawRoundRect(new RectF(x1, y1, x2, y2), 2, 2, myRectPaint); }
И наконец, загружаем изображение в макет:
myImageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));
Результаты
Теперь все, что вам нужно сделать, это запустить приложение. На экране видим, что обнаружено лицо женщины, при этом морда собаки не определяется.
В качестве домашнего задания поэкспериментируйте, попробуйте загрузить другие изображения, там где больше лиц, или там где лица повернуты под разными углами, и осмотрите, как Face Detection API справится с задачей.
Исходный код этого приложения полностью:
package info.fandroid.facedetect; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.SparseArray; import android.widget.ImageView; import android.widget.Toast; import com.google.android.gms.vision.Frame; import com.google.android.gms.vision.face.Face; import com.google.android.gms.vision.face.FaceDetector; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView myImageView = (ImageView) findViewById(R.id.image); BitmapFactory.Options options = new BitmapFactory.Options(); options.inMutable = true; Bitmap myBitmap = BitmapFactory.decodeResource( getApplicationContext().getResources(), R.drawable.test1, options); Paint myRectPaint = new Paint(); myRectPaint.setStrokeWidth(5); myRectPaint.setColor(Color.RED); myRectPaint.setStyle(Paint.Style.STROKE); Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565); Canvas tempCanvas = new Canvas(tempBitmap); tempCanvas.drawBitmap(myBitmap, 0, 0, null); FaceDetector faceDetector = new FaceDetector.Builder(getApplicationContext()).setTrackingEnabled(false).build(); if (!faceDetector.isOperational()) { Toast.makeText(this, "Cold not set up the Face Detector!", Toast.LENGTH_LONG).show(); return; } Frame frame = new Frame.Builder().setBitmap(myBitmap).build(); SparseArray <Face> faces = faceDetector.detect(frame); for (int i = 0; i < faces.size(); i++) { Face thisFace = faces.valueAt(i); float x1 = thisFace.getPosition().x; float y1 = thisFace.getPosition().y; float x2 = x1 + thisFace.getWidth(); float y2 = y1 + thisFace.getHeight(); tempCanvas.drawRoundRect(new RectF(x1, y1, x2, y2), 2, 2, myRectPaint); } myImageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap)); } }
Дополнительно:
- Watch the Google Play services Dev Byte
- Read the Documentation
- Download the Android Vision API sample