Русский
Русский
English
Статистика
Реклама

Как с помощью HUAWEI ML Kit интегрировать в приложения стикеры с изображением лица

Общая информация


Сейчас мы повсюду видим милые и смешные стикеры с изображением лица. Они используются не только в приложениях для камер, но и в социальных сетях и развлекательных приложениях. В этой статье я покажу вам, как создать 2D-стикеры с помощью инструмента HUAWEI ML Kit. Скоро мы также расскажем о процессе разработки 3D-стикеров, так что следите за обновлениями!

Сценарии


Приложения для съемки и редактирования фотографий, такие как селфи-камеры и социальные сети (TikTok, Weibo, WeChat и др.), часто предлагают набор стикеров для настройки изображений. С помощью этих стикеров пользователи могут создавать привлекательный и яркий контент и делиться им.

Подготовка


Добавьте репозиторий Maven Huawei в файл на уровне проекта build.gradle


Откройте файл build.gradle в корневом каталоге вашего проекта Android Studio.
image
Добавьте адрес репозитория Maven.
buildscript {    {              maven {url 'http://developer.huawei.com/repo/'}  }    }allprojects {  repositories {             maven { url 'http://developer.huawei.com/repo/'}  }}

Добавьте зависимости SDK в файл на уровне приложения build.gradle


image

// 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. Фильтр стикеров сможет использовать их позже.
@Overridepublic 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.
image

Определение данных стикера в формате 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, передайте путь стикера и запустите камеру.
@Overridepublic 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


@Overridepublic 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


@Overridepublic 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);  }}

Получилось! Ваш стикер с изображением лица готов.
Давайте проверим его в действии!
image
Для получения подробной информации перейдите на наш официальный сайт.
Вы также можете посмотреть пример кода.
Источник: habr.com
К списку статей
Опубликовано: 21.08.2020 06:20:10
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Обработка изображений

Машинное обучение

Разработка под arduino

Developing for arduino

Image processing

Machine learning

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru