كيفية دمج ملصقات الوجه في التطبيقات باستخدام HUAWEI ML Kit

معلومات عامة



في الوقت الحاضر نرى ملصقات وجه لطيفة ومضحكة في كل مكان. يتم استخدامها ليس فقط في تطبيقات الكاميرا ولكن أيضًا في وسائل التواصل الاجتماعي وتطبيقات الترفيه. في هذه المقالة ، سأوضح لك كيفية إنشاء ملصقات ثنائية الأبعاد باستخدام أداة HUAWEI ML Kit. سنغطي أيضًا عملية تطوير الملصقات ثلاثية الأبعاد قريبًا ، لذا ابق على اتصال!



نصوص



غالبًا ما تقدم تطبيقات التقاط الصور وتحريرها مثل كاميرات الصور الشخصية والوسائط الاجتماعية (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));
}


توضح الصورة أدناه كيفية إرجاع نقاط محيط الوجه باستخدام ML Kit API.



صورة



تحديد بيانات الملصق بتنسيق 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 وصورة في مجلد الأصول .



{
  "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);
  }
}


حدث! ملصق وجهك جاهز.



دعونا نراه في العمل!



صورة



يرجى زيارة موقعنا الرسمي للحصول على التفاصيل .

يمكنك أيضًا إلقاء نظرة على نموذج التعليمات البرمجية .



All Articles