Google Vision: Drawing mask on Face with animation

2019-09-14 21:27发布

I am using google vision library for face detection. Face detection is perfect and I get all the info like vertices, angles like eulerY, eulerZ.

I want to draw mask on face, drawing is ok but the face mask is not following the face position as it should, the position is not correct. Here is my edited code to draw face mask on googly eyes project.

Here is my source code:

package com.google.android.gms.samples.vision.face.googlyeyes;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.google.android.gms.samples.vision.face.googlyeyes.ui.camera.GraphicOverlay;
import com.google.android.gms.vision.face.Face;

import java.util.HashMap;

/**
 * Graphics class for rendering Googly Eyes on a graphic overlay given the current eye positions.
 */
class GooglyEyesGraphic extends GraphicOverlay.Graphic {

 private Paint mEyeWhitesPaint;
 private Paint mEyeIrisPaint;
 private Paint mEyeOutlinePaint;
 private Paint mEyeLidPaint;
 Paint mBoxPaint;


 Context mContext;
 private static final float BOX_STROKE_WIDTH = 20.0 f;
 FrameLayout frameLayout;
 ImageView imageView;


 //    Bitmap bmpOriginal;

 //==============================================================================================
 // Methods
 //==============================================================================================

 GooglyEyesGraphic(GraphicOverlay overlay, Context mContext) {
  super(overlay);

  this.mContext = mContext;
  mEyeWhitesPaint = new Paint();
  mEyeWhitesPaint.setColor(Color.WHITE);
  mEyeWhitesPaint.setStyle(Paint.Style.FILL);

  mEyeLidPaint = new Paint();
  mEyeLidPaint.setColor(Color.YELLOW);
  mEyeLidPaint.setStyle(Paint.Style.FILL);

  mEyeIrisPaint = new Paint();
  mEyeIrisPaint.setColor(Color.BLACK);
  mEyeIrisPaint.setStyle(Paint.Style.FILL);

  mEyeOutlinePaint = new Paint();
  mEyeOutlinePaint.setColor(Color.BLACK);
  mEyeOutlinePaint.setStyle(Paint.Style.STROKE);
  mEyeOutlinePaint.setStrokeWidth(5);


  mBoxPaint = new Paint();
  mBoxPaint.setColor(Color.MAGENTA);
  mBoxPaint.setStyle(Paint.Style.STROKE);
  mBoxPaint.setStrokeWidth(BOX_STROKE_WIDTH);
  mBoxPaint.setAlpha(40);

  LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  View view = li.inflate(R.layout.mask_layout, null);
  imageView = (ImageView) view.findViewById(R.id.flMaskIV);
  frameLayout = (FrameLayout) view.findViewById(R.id.frameLayout);

 }

 private volatile Face mFace;

 /**
  * Updates the eye positions and state from the detection of the most recent frame.  Invalidates
  * the relevant portions of the overlay to trigger a redraw.
  */
 void updateEyes(PointF leftPosition, boolean leftOpen,
  PointF rightPosition, boolean rightOpen, Face mFace) {

  if (facesList.containsKey(mFace.getId())) {
   PointF pointF1 = facesList.get(mFace.getId()).getPosition();
   PointF pointF2 = mFace.getPosition();

   double x = Math.sqrt(Math.pow(pointF2.x - pointF1.x, 2) - Math.pow(pointF2.y - pointF1.y, 2));
   if (x < 0)
    x = (-1 * x);
   if (x < 10)
    return;
   Log.e("face Called", "FaceCalled");

  }
  this.mFace = mFace;
  facesList.put(mFace.getId(), mFace);



  postInvalidate();
 }

 public HashMap < Integer, Face > facesList = new HashMap < > ();

 /**
  * Draws the current eye state to the supplied canvas.  This will draw the eyes at the last
  * reported position from the tracker, and the iris positions according to the physics
  * simulations for each iris given motion and other forces.
  */
 @Override
 public void draw(Canvas canvas) {
  if (mFace == null)
   return;
  //        if (facesList.containsKey(mFace.getId())) {
  //            PointF pointF1 = facesList.get(mFace.getId()).getPosition();
  //            PointF pointF2 = mFace.getPosition();
  //
  //            double x = Math.sqrt(Math.pow(pointF2.x - pointF1.x, 2) - Math.pow(pointF2.y - pointF1.y, 2));
  //            if (x < 0)
  //                x = (-1 * x);
  //            if (x < 10)
  //                return;
  //            Log.e("face Called", "FaceCalled");
  //
  //        }
  //
  //        facesList.put(mFace.getId(), mFace);

  if (this.canvas == null)
   this.canvas = canvas;
  applyMask();
 }

 Drawable drawable;
 Canvas canvas;

 private void applyMask() {

  if (canvas == null)
   return;
  //        Log.e("mFace.getEulerY()", "mFace.getEulerY()=> " + mFace.getEulerY());
  if (GooglyEyesActivity.maskImgView != null) {
   GooglyEyesActivity.maskImgView.setVisibility(View.GONE);
   GooglyEyesActivity.maskImgView.setImageResource(GooglyEyesActivity.currEmoticonID);
  }

  float x = translateX(mFace.getPosition().x + mFace.getWidth() / 2);
  float y = translateY(mFace.getPosition().y + mFace.getHeight() / 2);

  // Draws a bounding box around the face.
  float xOffset = scaleX(mFace.getWidth() / 2.0 f);
  float yOffset = scaleY(mFace.getHeight() / 2.0 f);
  float left = x - xOffset - 50;
  float top = y - (yOffset) - 50;
  float right = x + xOffset + 50;
  float bottom = y + (yOffset) + 50;


  //        canvas.drawRect((int) left, (int) top, (int) right, (int) bottom, mBoxPaint);


  drawable = GooglyEyesActivity.maskImgView.getDrawable();
  ///////////////////
  canvas.save();
  canvas.translate(left, top);
  //        frameLayout.setX(left);
  //        frameLayout.setY(top);
  Rect rect = new Rect((int) left, (int) top, (int) right, (int) bottom);
  frameLayout.measure(rect.width(), rect.height());
  frameLayout.setLayoutParams(new LinearLayout.LayoutParams(rect.width(), rect.height()));

  frameLayout.layout(0, 0, (int) right, (int) bottom);


  frameLayout.setClipBounds(rect);
  imageView.setLayoutParams(new FrameLayout.LayoutParams(rect.width(), rect.height()));
  imageView.setRotationY(mFace.getEulerY());
  imageView.setRotation(mFace.getEulerZ());
  imageView.setImageDrawable(drawable);
  frameLayout.draw(canvas);
  canvas.restore();

 }


}

Also i need to add animations so i tried using dlib library to get landmarks points and draw it using opengl but in opengl i dont have any function to populate the vertice array i am getting from dlib. As the dlib landmarks are in points but the array there is not in such a way. Any help will be appreciated for both scenarios.

Thank you in advance.

Thanks.

0条回答
登录 后发表回答