[Обработка изображений, Машинное обучение, Разработка под Arduino] Как с помощью HUAWEI ML Kit интегрировать в приложения стикеры с изображением лица
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Общая информация
Сейчас мы повсюду видим милые и смешные стикеры с изображением лица. Они используются не только в приложениях для камер, но и в социальных сетях и развлекательных приложениях. В этой статье я покажу вам, как создать 2D-стикеры с помощью инструмента HUAWEI ML Kit. Скоро мы также расскажем о процессе разработки 3D-стикеров, так что следите за обновлениями!
Сценарии
Приложения для съемки и редактирования фотографий, такие как селфи-камеры и социальные сети (TikTok, Weibo, WeChat и др.), часто предлагают набор стикеров для настройки изображений. С помощью этих стикеров пользователи могут создавать привлекательный и яркий контент и делиться им.
Подготовка
Добавьте репозиторий Maven Huawei в файл на уровне проекта build.gradle
Откройте файл build.gradle в корневом каталоге вашего проекта Android Studio.
Добавьте адрес репозитория Maven.
buildscript {
{
maven {url 'http://developer.huawei.com/repo/'}
}
}
allprojects {
repositories {
maven { url 'http://developer.huawei.com/repo/'}
}
}
Добавьте зависимости SDK в файл на уровне приложения build.gradle
// Face detection SDK.
implementation 'com.huawei.hms:ml-computer-vision-face:2.0.1.300'
// Face detection model.
implementation 'com.huawei.hms:ml-computer-vision-face-shape-point-model:2.0.1.300'
Запросите права доступа к камере, сети и памяти в файле AndroidManifest.xml
<!--Camera permission-->
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<!--Write permission-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--Read permission-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Разработка кода
Настройте анализатор лица
MLFaceAnalyzerSetting detectorOptions;
detectorOptions = new MLFaceAnalyzerSetting.Factory()
.setFeatureType(MLFaceAnalyzerSetting.TYPE_UNSUPPORT_FEATURES)
.setShapeType(MLFaceAnalyzerSetting.TYPE_SHAPES)
.allowTracing(MLFaceAnalyzerSetting.MODE_TRACING_FAST)
.create();
detector = MLAnalyzerFactory.getInstance().getFaceAnalyzer(detectorOptions);
Получите точки контура лица и передайте их в FacePointEngine
С помощью обратного вызова камеры получите данные камеры, а затем вызовите анализатор лица, чтобы получить точки контура лица, и передайте эти точки в FacePointEngine. Фильтр стикеров сможет использовать их позже.
@Override
public void onPreviewFrame(final byte[] imgData, final Camera camera) {
int width = mPreviewWidth;
int height = mPreviewHeight;
long startTime = System.currentTimeMillis();
// Set the shooting directions of the front and rear cameras to be the same.
if (isFrontCamera()){
mOrientation = 0;
}else {
mOrientation = 2;
}
MLFrame.Property property =
new MLFrame.Property.Creator()
.setFormatType(ImageFormat.NV21)
.setWidth(width)
.setHeight(height)
.setQuadrant(mOrientation)
.create();
ByteBuffer data = ByteBuffer.wrap(imgData);
// Call the face analyzer API.
SparseArray<MLFace> faces = detector.analyseFrame(MLFrame.fromByteBuffer(data,property));
// Determine whether face information is obtained.
if(faces.size()>0){
MLFace mLFace = faces.get(0);
EGLFace EGLFace = FacePointEngine.getInstance().getOneFace(0);
EGLFace.pitch = mLFace.getRotationAngleX();
EGLFace.yaw = mLFace.getRotationAngleY();
EGLFace.roll = mLFace.getRotationAngleZ() - 90;
if (isFrontCamera())
EGLFace.roll = -EGLFace.roll;
if (EGLFace.vertexPoints == null) {
EGLFace.vertexPoints = new PointF[131];
}
int index = 0;
// Obtain the coordinates of a user's face contour points and convert them to the floating point numbers in normalized coordinate system of OpenGL.
for (MLFaceShape contour : mLFace.getFaceShapeList()) {
if (contour == null) {
continue;
}
List<MLPosition> points = contour.getPoints();
for (int i = 0; i < points.size(); i++) {
MLPosition point = points.get(i);
float x = ( point.getY() / height) * 2 - 1;
float y = ( point.getX() / width ) * 2 - 1;
if (isFrontCamera())
x = -x;
PointF Point = new PointF(x,y);
EGLFace.vertexPoints[index] = Point;
index++;
}
}
// Insert a face object.
FacePointEngine.getInstance().putOneFace(0, EGLFace);
// Set the number of faces.
FacePointEngine.getInstance().setFaceSize(faces!= null ? faces.size() : 0);
}else{
FacePointEngine.getInstance().clearAll();
}
long endTime = System.currentTimeMillis();
Log.d("TAG","Face detect time: " + String.valueOf(endTime - startTime));
}
На изображении ниже показано, как точки контура лица возвращаются с помощью API ML Kit.
Определение данных стикера в формате JSON
public class FaceStickerJson {
public int[] centerIndexList; // Center coordinate index list. If the list contains multiple indexes, these indexes are used to calculate the central point.
public float offsetX; // X-axis offset relative to the center coordinate of the sticker, in pixels.
public float offsetY; // Y-axis offset relative to the center coordinate of the sticker, in pixels.
public float baseScale; // Base scale factor of the sticker.
public int startIndex; // Face start index, which is used for computing the face width.
public int endIndex; // Face end index, which is used for computing the face width.
public int width; // Sticker width.
public int height; // Sticker height.
public int frames; // Number of sticker frames.
public int action; // Action. 0 indicates default display. This is used for processing the sticker action.
public String stickerName; // Sticker name, which is used for marking the folder or PNG file path.
public int duration; // Sticker frame displays interval.
public boolean stickerLooping; // Indicates whether to perform rendering in loops for the sticker.
public int maxCount; // Maximum number of rendering times.
...
}
Сделайте стикер с изображением кота
Создайте файл JSON для стикера с изображением кота и определите центральную точку между бровями (84) и кончиком носа (85) с помощью индекса лица. Вставьте уши и нос кота, а затем поместите файл JSON и изображение в папку assets.
{
"stickerList": [{
"type": "sticker",
"centerIndexList": [84],
"offsetX": 0.0,
"offsetY": 0.0,
"baseScale": 1.3024,
"startIndex": 11,
"endIndex": 28,
"width": 495,
"height": 120,
"frames": 2,
"action": 0,
"stickerName": "nose",
"duration": 100,
"stickerLooping": 1,
"maxcount": 5
}, {
"type": "sticker",
"centerIndexList": [83],
"offsetX": 0.0,
"offsetY": -1.1834,
"baseScale": 1.3453,
"startIndex": 11,
"endIndex": 28,
"width": 454,
"height": 150,
"frames": 2,
"action": 0,
"stickerName": "ear",
"duration": 100,
"stickerLooping": 1,
"maxcount": 5
}]
}
Рендеринг стикера в текстуру
Мы выполняем рендеринг стикера в текстуру с помощью класса GLSurfaceView — он проще, чем TextureView. Создайте экземпляр фильтра стикеров в onSurfaceChanged, передайте путь стикера и запустите камеру.
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mTextures = new int[1];
mTextures[0] = OpenGLUtils.createOESTexture();
mSurfaceTexture = new SurfaceTexture(mTextures[0]);
mSurfaceTexture.setOnFrameAvailableListener(this);
// Pass the samplerExternalOES into the texture.
cameraFilter = new CameraFilter(this.context);
// Set the face sticker path in the assets directory.
String folderPath ="cat";
stickerFilter = new FaceStickerFilter(this.context,folderPath);
// Create a screen filter object.
screenFilter = new BaseFilter(this.context);
facePointsFilter = new FacePointsFilter(this.context);
mEGLCamera.openCamera();
}
Инициализируйте фильтр стикеров в onSurfaceChanged
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.d(TAG, "onSurfaceChanged. width: " + width + ", height: " + height);
int previewWidth = mEGLCamera.getPreviewWidth();
int previewHeight = mEGLCamera.getPreviewHeight();
if (width > height) {
setAspectRatio(previewWidth, previewHeight);
} else {
setAspectRatio(previewHeight, previewWidth);
}
// Set the image size, create a FrameBuffer, and set the display size.
cameraFilter.onInputSizeChanged(previewWidth, previewHeight);
cameraFilter.initFrameBuffer(previewWidth, previewHeight);
cameraFilter.onDisplaySizeChanged(width, height);
stickerFilter.onInputSizeChanged(previewHeight, previewWidth);
stickerFilter.initFrameBuffer(previewHeight, previewWidth);
stickerFilter.onDisplaySizeChanged(width, height);
screenFilter.onInputSizeChanged(previewWidth, previewHeight);
screenFilter.initFrameBuffer(previewWidth, previewHeight);
screenFilter.onDisplaySizeChanged(width, height);
facePointsFilter.onInputSizeChanged(previewHeight, previewWidth);
facePointsFilter.onDisplaySizeChanged(width, height);
mEGLCamera.startPreview(mSurfaceTexture);
}
Нарисуйте на экране стикер с помощью onDrawFrame
@Override
public void onDrawFrame(GL10 gl) {
int textureId;
// Clear the screen and depth buffer.
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
// Update a texture image.
mSurfaceTexture.updateTexImage();
// Obtain the SurfaceTexture transform matrix.
mSurfaceTexture.getTransformMatrix(mMatrix);
// Set the camera display transform matrix.
cameraFilter.setTextureTransformMatrix(mMatrix);
// Draw the camera texture.
textureId = cameraFilter.drawFrameBuffer(mTextures[0],mVertexBuffer,mTextureBuffer);
// Draw the sticker texture.
textureId = stickerFilter.drawFrameBuffer(textureId,mVertexBuffer,mTextureBuffer);
// Draw on the screen.
screenFilter.drawFrame(textureId , mDisplayVertexBuffer, mDisplayTextureBuffer);
if(drawFacePoints){
facePointsFilter.drawFrame(textureId, mDisplayVertexBuffer, mDisplayTextureBuffer);
}
}
Получилось! Ваш стикер с изображением лица готов.
Давайте проверим его в действии!
Для получения подробной информации перейдите на наш официальный сайт.
Вы также можете посмотреть пример кода.
===========
Источник:
habr.com
===========
Похожие новости:
- [Big Data, Машинное обучение] Спасти рядового датасайнтиста. Как работать над компьютерным зрением, чтобы сделать проект и не потерять себя
- [Законодательство в IT, Искусственный интеллект] Юридические эксперименты в ИТ. Как кастомизировать закон под себя
- [Машинное обучение, Исследования и прогнозы в IT, Конференции, Искусственный интеллект] Чем нам запомнится CVPR 2020. Как конференция про компьютерное зрение переехала в онлайн
- [Машинное обучение, Компьютерное железо, История IT, Искусственный интеллект] Алан Тьюринг, отец современного компьютера (перевод)
- [Разработка под Arduino, История IT, Настольные компьютеры, DIY или Сделай сам] DIY-проект: аудиокассета на базе Arduino для хранения и загрузки программ и игр в ZX Spectrum
- [Алгоритмы, Обработка изображений, Математика, Машинное обучение] Рубрика «Читаем статьи за вас». Июнь 2020 года
- [Машинное обучение, Искусственный интеллект] Учёные научили нейросеть генерировать теннисные матчи и смоделировали Уимблдон
- [Обработка изображений, Биотехнологии, Искусственный интеллект] Анализ колоса пшеницы методами компьютерного зрения. Определение плоидности
- [Машинное обучение, Искусственный интеллект, Natural Language Processing] Искусственный интеллект в области юриспруденции. Статья 3
- [Big Data, Машинное обучение, Статистика в IT, Искусственный интеллект, Data Engineering] Обзор Gartner MQ 2020: Платформы Машинного Обучения и Искусственного Интеллекта
Теги для поиска: #_obrabotka_izobrazhenij (Обработка изображений), #_mashinnoe_obuchenie (Машинное обучение), #_razrabotka_pod_arduino (Разработка под Arduino), #_developing_for_arduino, #_image_processing, #_machine_learning, #_obrabotka_izobrazhenij (
Обработка изображений
), #_mashinnoe_obuchenie (
Машинное обучение
), #_razrabotka_pod_arduino (
Разработка под Arduino
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:27
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Общая информация Сейчас мы повсюду видим милые и смешные стикеры с изображением лица. Они используются не только в приложениях для камер, но и в социальных сетях и развлекательных приложениях. В этой статье я покажу вам, как создать 2D-стикеры с помощью инструмента HUAWEI ML Kit. Скоро мы также расскажем о процессе разработки 3D-стикеров, так что следите за обновлениями! Сценарии Приложения для съемки и редактирования фотографий, такие как селфи-камеры и социальные сети (TikTok, Weibo, WeChat и др.), часто предлагают набор стикеров для настройки изображений. С помощью этих стикеров пользователи могут создавать привлекательный и яркий контент и делиться им. Подготовка Добавьте репозиторий Maven Huawei в файл на уровне проекта build.gradle Откройте файл build.gradle в корневом каталоге вашего проекта Android Studio. Добавьте адрес репозитория Maven. buildscript {
{ maven {url 'http://developer.huawei.com/repo/'} } } allprojects { repositories { maven { url 'http://developer.huawei.com/repo/'} } } Добавьте зависимости SDK в файл на уровне приложения build.gradle // Face detection SDK.
implementation 'com.huawei.hms:ml-computer-vision-face:2.0.1.300' // Face detection model. implementation 'com.huawei.hms:ml-computer-vision-face-shape-point-model:2.0.1.300' Запросите права доступа к камере, сети и памяти в файле AndroidManifest.xml <!--Camera permission-->
<uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA" /> <!--Write permission--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!--Read permission--> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> Разработка кода Настройте анализатор лица MLFaceAnalyzerSetting detectorOptions;
detectorOptions = new MLFaceAnalyzerSetting.Factory() .setFeatureType(MLFaceAnalyzerSetting.TYPE_UNSUPPORT_FEATURES) .setShapeType(MLFaceAnalyzerSetting.TYPE_SHAPES) .allowTracing(MLFaceAnalyzerSetting.MODE_TRACING_FAST) .create(); detector = MLAnalyzerFactory.getInstance().getFaceAnalyzer(detectorOptions); Получите точки контура лица и передайте их в FacePointEngine С помощью обратного вызова камеры получите данные камеры, а затем вызовите анализатор лица, чтобы получить точки контура лица, и передайте эти точки в FacePointEngine. Фильтр стикеров сможет использовать их позже. @Override
public void onPreviewFrame(final byte[] imgData, final Camera camera) { int width = mPreviewWidth; int height = mPreviewHeight; long startTime = System.currentTimeMillis(); // Set the shooting directions of the front and rear cameras to be the same. if (isFrontCamera()){ mOrientation = 0; }else { mOrientation = 2; } MLFrame.Property property = new MLFrame.Property.Creator() .setFormatType(ImageFormat.NV21) .setWidth(width) .setHeight(height) .setQuadrant(mOrientation) .create(); ByteBuffer data = ByteBuffer.wrap(imgData); // Call the face analyzer API. SparseArray<MLFace> faces = detector.analyseFrame(MLFrame.fromByteBuffer(data,property)); // Determine whether face information is obtained. if(faces.size()>0){ MLFace mLFace = faces.get(0); EGLFace EGLFace = FacePointEngine.getInstance().getOneFace(0); EGLFace.pitch = mLFace.getRotationAngleX(); EGLFace.yaw = mLFace.getRotationAngleY(); EGLFace.roll = mLFace.getRotationAngleZ() - 90; if (isFrontCamera()) EGLFace.roll = -EGLFace.roll; if (EGLFace.vertexPoints == null) { EGLFace.vertexPoints = new PointF[131]; } int index = 0; // Obtain the coordinates of a user's face contour points and convert them to the floating point numbers in normalized coordinate system of OpenGL. for (MLFaceShape contour : mLFace.getFaceShapeList()) { if (contour == null) { continue; } List<MLPosition> points = contour.getPoints(); for (int i = 0; i < points.size(); i++) { MLPosition point = points.get(i); float x = ( point.getY() / height) * 2 - 1; float y = ( point.getX() / width ) * 2 - 1; if (isFrontCamera()) x = -x; PointF Point = new PointF(x,y); EGLFace.vertexPoints[index] = Point; index++; } } // Insert a face object. FacePointEngine.getInstance().putOneFace(0, EGLFace); // Set the number of faces. FacePointEngine.getInstance().setFaceSize(faces!= null ? faces.size() : 0); }else{ FacePointEngine.getInstance().clearAll(); } long endTime = System.currentTimeMillis(); Log.d("TAG","Face detect time: " + String.valueOf(endTime - startTime)); } На изображении ниже показано, как точки контура лица возвращаются с помощью API ML Kit. Определение данных стикера в формате JSON public class FaceStickerJson {
public int[] centerIndexList; // Center coordinate index list. If the list contains multiple indexes, these indexes are used to calculate the central point. public float offsetX; // X-axis offset relative to the center coordinate of the sticker, in pixels. public float offsetY; // Y-axis offset relative to the center coordinate of the sticker, in pixels. public float baseScale; // Base scale factor of the sticker. public int startIndex; // Face start index, which is used for computing the face width. public int endIndex; // Face end index, which is used for computing the face width. public int width; // Sticker width. public int height; // Sticker height. public int frames; // Number of sticker frames. public int action; // Action. 0 indicates default display. This is used for processing the sticker action. public String stickerName; // Sticker name, which is used for marking the folder or PNG file path. public int duration; // Sticker frame displays interval. public boolean stickerLooping; // Indicates whether to perform rendering in loops for the sticker. public int maxCount; // Maximum number of rendering times. ... } Сделайте стикер с изображением кота Создайте файл JSON для стикера с изображением кота и определите центральную точку между бровями (84) и кончиком носа (85) с помощью индекса лица. Вставьте уши и нос кота, а затем поместите файл JSON и изображение в папку assets. {
"stickerList": [{ "type": "sticker", "centerIndexList": [84], "offsetX": 0.0, "offsetY": 0.0, "baseScale": 1.3024, "startIndex": 11, "endIndex": 28, "width": 495, "height": 120, "frames": 2, "action": 0, "stickerName": "nose", "duration": 100, "stickerLooping": 1, "maxcount": 5 }, { "type": "sticker", "centerIndexList": [83], "offsetX": 0.0, "offsetY": -1.1834, "baseScale": 1.3453, "startIndex": 11, "endIndex": 28, "width": 454, "height": 150, "frames": 2, "action": 0, "stickerName": "ear", "duration": 100, "stickerLooping": 1, "maxcount": 5 }] } Рендеринг стикера в текстуру Мы выполняем рендеринг стикера в текстуру с помощью класса GLSurfaceView — он проще, чем TextureView. Создайте экземпляр фильтра стикеров в onSurfaceChanged, передайте путь стикера и запустите камеру. @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) { GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); mTextures = new int[1]; mTextures[0] = OpenGLUtils.createOESTexture(); mSurfaceTexture = new SurfaceTexture(mTextures[0]); mSurfaceTexture.setOnFrameAvailableListener(this); // Pass the samplerExternalOES into the texture. cameraFilter = new CameraFilter(this.context); // Set the face sticker path in the assets directory. String folderPath ="cat"; stickerFilter = new FaceStickerFilter(this.context,folderPath); // Create a screen filter object. screenFilter = new BaseFilter(this.context); facePointsFilter = new FacePointsFilter(this.context); mEGLCamera.openCamera(); } Инициализируйте фильтр стикеров в onSurfaceChanged @Override
public void onSurfaceChanged(GL10 gl, int width, int height) { Log.d(TAG, "onSurfaceChanged. width: " + width + ", height: " + height); int previewWidth = mEGLCamera.getPreviewWidth(); int previewHeight = mEGLCamera.getPreviewHeight(); if (width > height) { setAspectRatio(previewWidth, previewHeight); } else { setAspectRatio(previewHeight, previewWidth); } // Set the image size, create a FrameBuffer, and set the display size. cameraFilter.onInputSizeChanged(previewWidth, previewHeight); cameraFilter.initFrameBuffer(previewWidth, previewHeight); cameraFilter.onDisplaySizeChanged(width, height); stickerFilter.onInputSizeChanged(previewHeight, previewWidth); stickerFilter.initFrameBuffer(previewHeight, previewWidth); stickerFilter.onDisplaySizeChanged(width, height); screenFilter.onInputSizeChanged(previewWidth, previewHeight); screenFilter.initFrameBuffer(previewWidth, previewHeight); screenFilter.onDisplaySizeChanged(width, height); facePointsFilter.onInputSizeChanged(previewHeight, previewWidth); facePointsFilter.onDisplaySizeChanged(width, height); mEGLCamera.startPreview(mSurfaceTexture); } Нарисуйте на экране стикер с помощью onDrawFrame @Override
public void onDrawFrame(GL10 gl) { int textureId; // Clear the screen and depth buffer. GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT); // Update a texture image. mSurfaceTexture.updateTexImage(); // Obtain the SurfaceTexture transform matrix. mSurfaceTexture.getTransformMatrix(mMatrix); // Set the camera display transform matrix. cameraFilter.setTextureTransformMatrix(mMatrix); // Draw the camera texture. textureId = cameraFilter.drawFrameBuffer(mTextures[0],mVertexBuffer,mTextureBuffer); // Draw the sticker texture. textureId = stickerFilter.drawFrameBuffer(textureId,mVertexBuffer,mTextureBuffer); // Draw on the screen. screenFilter.drawFrame(textureId , mDisplayVertexBuffer, mDisplayTextureBuffer); if(drawFacePoints){ facePointsFilter.drawFrame(textureId, mDisplayVertexBuffer, mDisplayTextureBuffer); } } Получилось! Ваш стикер с изображением лица готов. Давайте проверим его в действии! Для получения подробной информации перейдите на наш официальный сайт. Вы также можете посмотреть пример кода. =========== Источник: habr.com =========== Похожие новости:
Обработка изображений ), #_mashinnoe_obuchenie ( Машинное обучение ), #_razrabotka_pod_arduino ( Разработка под Arduino ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:27
Часовой пояс: UTC + 5