使用人脸检测Android的面部交换

时间:2013-08-30 07:36:36

标签: android android-canvas crop face-detection ondraw

我正在尝试使用facedetection进行Face swap应用程序。直到现在我得到位图中检测到的面孔并在检测到的面上绘制椭圆形。但现在我需要使用椭圆内的面,以便我可以交换两个面。可能吗。我需要一些关于此的建议。

我的活动课程如下

public class FaceDetectionActivity extends Activity 
{


public MyView faceview;
public ImageView gallery;
private Uri imageURI;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.main);
    setContentView(R.layout.main);

    faceview = (MyView)findViewById(R.id.faceview);

    gallery=(ImageView)findViewById(R.id.gallery);

    gallery.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            // TODO Auto-generated method stub

            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");
            startActivityForResult(intent, 0 );

        }
    });


}


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == Activity.RESULT_OK) {

        if(requestCode==0){

        imageURI = data.getData(); 


        try {
            Bitmap b = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), imageURI);

            faceview.myBitmap=b;


        } catch (FileNotFoundException e) {
 //              TODO Auto-generated catch block
                e.printStackTrace();
        } catch (IOException e) {
 //              TODO Auto-generated catch block  
            e.printStackTrace();
        }



        faceview.invalidate(); 

        }


        faceview.invalidate(); 
    } else {
        System.exit(0);
        Log.e("result", "BAD");
    }
}


}

和我的观点类

public class MyView extends ImageViewTouchBase {

public RectF rectF;
public Bitmap myBitmap;
private int width, height;
private FaceDetector.Face[] detectedFaces;
private int NUMBER_OF_FACES=10;
private FaceDetector faceDetector;
private int NUMBER_OF_FACE_DETECTED;
private float eyeDistance;
Matrix mImageMatrix;

public MyView(Context context, AttributeSet attrs) 
{
    super(context, attrs);
    BitmapFactory.Options bitmapFatoryOptions=new BitmapFactory.Options();
    bitmapFatoryOptions.inPreferredConfig=Bitmap.Config.RGB_565;
    myBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.familyportrait,bitmapFatoryOptions);
    width=myBitmap.getWidth();
    height=myBitmap.getHeight();
    detectedFaces=new FaceDetector.Face[NUMBER_OF_FACES];
    faceDetector=new FaceDetector(width,height,NUMBER_OF_FACES);
    NUMBER_OF_FACE_DETECTED=faceDetector.findFaces(myBitmap, detectedFaces);
}

@Override
protected void onDraw(Canvas canvas)
{
    if(myBitmap!=null)
    {


    canvas.drawBitmap(myBitmap, 0,0, null);

    }
    Paint myPaint = new Paint();
    myPaint.setColor(Color.GREEN);
    myPaint.setStyle(Paint.Style.STROKE); 
    myPaint.setStrokeWidth(3);

    for(int count=0;count<NUMBER_OF_FACE_DETECTED;count++)
    {
        Face face=detectedFaces[count];
        PointF midPoint=new PointF();
        face.getMidPoint(midPoint);

        eyeDistance=face.eyesDistance();

    float   left = midPoint.x - (float)(1.4 * eyeDistance);
    float   right = midPoint.x + (float)(1.4 * eyeDistance);
    float    top = midPoint.y - (float)(1.8 * eyeDistance);
    float    bottom = midPoint.y + (float)(1.8 * eyeDistance);

    Rect imageRect = new Rect(0, 0, width, height);
     rectF = new RectF();

    rectF.set(left,top,right,bottom);

    canvas.drawOval(rectF, myPaint);


    }
}

}

现在我想要选择椭圆内的内容。请给我一些想法。

2 个答案:

答案 0 :(得分:2)

我只是想通了。我正在创建另一个位图,其中包含上述代码中的变量Left,Right,Top和Bottom。然后我得到了face的正方形位图。我从方形位图面提取圆形位图。多数民众赞成。

答案 1 :(得分:0)

尝试以下代码:

公共类MainActivity扩展了ProgressA {

public static final String FACE_1 = "face_1";
public static final String FACE_2 = "face_2";

private ImageView mIvForDetect;
private ImageView mIvForDetect2;
private ImageView mIvForDetect3;
private ImageView mIvForDetect4;
//private Bitmap baseBTM;
private Bitmap face1BTM;
private Bitmap face2BTM;

boolean face1Done = false;
boolean face2Done = false;

private FirebaseVisionFaceDetector detector;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    mIvForDetect = findViewById(R.id.iv_main_for_detect);
    mIvForDetect2 = findViewById(R.id.iv_main_for_detect2);
    mIvForDetect3 = findViewById(R.id.iv_main_for_detect3);
    mIvForDetect4 = findViewById(R.id.iv_main_for_detect4);
    //baseBTM = BitmapFactory.decodeResource(getResources(), R.drawable.paj);
    mIvForDetect.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.jolie));
    mIvForDetect2.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.pitt));

    detector = FirebaseVision.getInstance().getVisionFaceDetector(buildCloudVisionOptions());

    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            showProgressDialog();
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    detectFace(mIvForDetect, FACE_1, null);
                    detectFace(mIvForDetect2,FACE_2, null);
                }
            });
            thread.start();
        }
    });
}

private void checkFaces() {
    if (face1Done && face2Done){
        swapFaces();
    }
}

private void swapFaces() {
    detectFace(mIvForDetect, FACE_1, face2BTM);
    detectFace(mIvForDetect2, FACE_2, face1BTM);
}

private void detectFace(final ImageView view, final String face, final Bitmap fakeFace) {

    final Bitmap baseBTM = ((BitmapDrawable) view.getDrawable()).getBitmap();
    FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(baseBTM);
    detector.detectInImage(image)
            .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionFace>>() {
                @Override
                public void onSuccess(List<FirebaseVisionFace> faces) {
                    if (fakeFace != null){
                        setFakeFace(view, faces.get(0), baseBTM, fakeFace);
                        hideProgressDialog();
                    }else {
                        switch (face){
                            case FACE_1:
                                face1BTM = createTrimmedBitmap(cutFaces(faces.get(0), baseBTM));
                                mIvForDetect3.setImageBitmap(face1BTM);
                                face1Done = true;
                                checkFaces();
                                break;
                            case FACE_2:
                                face2BTM = createTrimmedBitmap(cutFaces(faces.get(0), baseBTM));
                                mIvForDetect4.setImageBitmap(face2BTM);
                                face2Done = true;
                                checkFaces();
                                break;
                        }
                    }
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    hideProgressDialog();
                    Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
}

public FirebaseVisionFaceDetectorOptions buildCloudVisionOptions() {
    return new FirebaseVisionFaceDetectorOptions.Builder()
            .setPerformanceMode(FirebaseVisionFaceDetectorOptions.ACCURATE)
            .setLandmarkMode(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
            .setClassificationMode(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
            .setPerformanceMode(FirebaseVisionFaceDetectorOptions.FAST)
            .build();
}

public static Bitmap createTrimmedBitmap(Bitmap bmp) {
    int imgHeight = bmp.getHeight();
    int imgWidth = bmp.getWidth();
    int smallX = 0, largeX = imgWidth, smallY = 0, largeY = imgHeight;
    int left = imgWidth, right = imgWidth, top = imgHeight, bottom = imgHeight;
    for (int i = 0; i < imgWidth; i++) {
        for (int j = 0; j < imgHeight; j++) {
            if (bmp.getPixel(i, j) != Color.TRANSPARENT) {
                if ((i - smallX) < left) {
                    left = (i - smallX);
                }
                if ((largeX - i) < right) {
                    right = (largeX - i);
                }
                if ((j - smallY) < top) {
                    top = (j - smallY);
                }
                if ((largeY - j) < bottom) {
                    bottom = (largeY - j);
                }
            }
        }
    }
    bmp = Bitmap.createBitmap(bmp, left, top, imgWidth - left - right, imgHeight - top - bottom);
    return bmp;
}

public Bitmap cutFaces(FirebaseVisionFace face, Bitmap baseBTM) {
    Bitmap tempBitmap = Bitmap.createBitmap(baseBTM.getWidth(), baseBTM.getHeight(), Bitmap.Config.RGB_565);
    Canvas tempCanvas = new Canvas(tempBitmap);
    tempCanvas.drawBitmap(baseBTM, 0, 0, null);
    int top = face.getBoundingBox().top;
    int left = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR).getPosition().getX());
    int right = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.RIGHT_EAR).getPosition().getX());
    int bottom = face.getBoundingBox().bottom;
    Bitmap output = Bitmap.createBitmap(tempBitmap.getWidth(), tempBitmap.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final Paint paint = new Paint();
    canvas.drawOval(left, top, right, bottom, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(tempBitmap, new Matrix(), paint);
    return output;
}

public void setFakeFace(ImageView view, FirebaseVisionFace face, Bitmap baseBTM, Bitmap fakeFace) {

    Bitmap resultBitmap = Bitmap.createBitmap(baseBTM.getWidth(), baseBTM.getHeight(), baseBTM.getConfig());
    Canvas canvas = new Canvas(resultBitmap);
    final Paint paintSRC = new Paint();
    final Paint paintDST = new Paint();

    int top = face.getBoundingBox().top;
    int left = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR).getPosition().getX());
    int right = Math.round(face.getLandmark(FirebaseVisionFaceLandmark.RIGHT_EAR).getPosition().getX());
    int bottom = face.getBoundingBox().bottom;
    int weight = right - left;
    int height = bottom - top;

    canvas.drawOval(left, top, right, bottom, paintSRC);
    paintSRC.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
    paintDST.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
    Matrix matrix = new Matrix();
    matrix.postScale(face.getLandmark(FirebaseVisionFaceLandmark.LEFT_EAR).getPosition().getX(), face.getBoundingBox().top);

    canvas.drawBitmap(baseBTM, 0, 0, null);
    canvas.drawBitmap(Bitmap.createScaledBitmap(fakeFace, weight, height, false), left, top, paintDST);
    view.setImageBitmap(resultBitmap);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}