【问题标题】:Face Swap Using Face Detection Android使用人脸检测 Android 进行人脸交换
【发布时间】:2013-09-02 20:38:26
【问题描述】:

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

我的活动课如下

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);


    }
}

}

现在我希望选择椭圆内的内容。请给我一些建议。

【问题讨论】:

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


    【解决方案1】:

    试试这个代码:

    public class MainActivity extends 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);
        } }
    

    【讨论】:

      【解决方案2】:

      我刚刚想通了。我正在使用上面代码中的变量 Left、Right、Top 和 Bottom 创建另一个位图。然后我得到一个正方形的面位图。我从正方形的位图面中提取圆形位图。就是这样。

      【讨论】:

      • 代码有点繁琐。我会写一个教程并在一周内分享。
      • 嘿@Sandeep,我喜欢你的想法,如果可能的话,我很想看看代码。
      • 嗨,你能通过提供一些代码来解释你的意思吗?
      • @SandeepR 你能分享一下你的实现吗??
      猜你喜欢
      • 2013-09-24
      • 2019-02-27
      • 1970-01-01
      • 2019-03-20
      • 2012-05-18
      • 2019-11-18
      • 2021-11-25
      • 2013-03-23
      • 2017-10-02
      相关资源
      最近更新 更多