Crop Image with face detection in android

2019-01-10 23:27发布

问题:

I needed a demo where any image can be cropped with the face detection function.

FIXED

But after few surfing hours I didn't come to a single demo, so I prepared a single demo with conjunction of few demos that I found online.

I have prepared a demo to crop the image.

My demo crops the image rectangle, and circular as well.

Also it detects the face and crops the image according to the face detection.

I am using the following image to crop it.

And the screenshot of the crop result is :

The xml for the example is :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity" >

<View
    android:id="@+id/part1"
    android:layout_width="fill_parent"
    android:layout_height="100dp" >
</View>

<View
    android:id="@+id/part2"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_marginTop="30dp" >
</View>

</LinearLayout>

The java code for the Activity :

public class MainActivity extends Activity {
public View part1, part2;
int viewHeight, viewWidth;
private FaceDetector myFaceDetect;
private FaceDetector.Face[] myFace;
float myEyesDistance;

@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    part1 = findViewById(R.id.part1);
    part2 = findViewById(R.id.part2);
    part1.post(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            viewHeight = part1.getMeasuredHeight();
            viewWidth = part1.getMeasuredWidth();
            try {

                Paint paint = new Paint();
                paint.setFilterBitmap(true);
                Bitmap bitmapOrg = BitmapFactory.decodeResource(
                        getResources(),
                        R.drawable.sachin_tendulkar_10102013);

                int targetWidth = bitmapOrg.getWidth();
                int targetHeight = bitmapOrg.getHeight();

                Bitmap targetBitmap = Bitmap.createBitmap(targetWidth,
                        targetHeight, Bitmap.Config.ARGB_8888);

                RectF rectf = new RectF(0, 0, viewWidth, viewHeight);

                Canvas canvas = new Canvas(targetBitmap);
                Path path = new Path();

                path.addRect(rectf, Path.Direction.CW);
                canvas.clipPath(path);

                canvas.drawBitmap(
                        bitmapOrg,
                        new Rect(0, 0, bitmapOrg.getWidth(), bitmapOrg
                                .getHeight()), new Rect(0, 0, targetWidth,
                                targetHeight), paint);

                Matrix matrix = new Matrix();
                matrix.postScale(1f, 1f);

                BitmapFactory.Options bitmapFatoryOptions = new BitmapFactory.Options();
                bitmapFatoryOptions.inPreferredConfig = Bitmap.Config.RGB_565;

                bitmapOrg = BitmapFactory.decodeResource(getResources(),
                        R.drawable.sachin_tendulkar_10102013,
                        bitmapFatoryOptions);

                myFace = new FaceDetector.Face[5];
                myFaceDetect = new FaceDetector(targetWidth, targetHeight,
                        5);
                int numberOfFaceDetected = myFaceDetect.findFaces(
                        bitmapOrg, myFace);
                Bitmap resizedBitmap = null;
                if (numberOfFaceDetected > 0) {
                    PointF myMidPoint = null;
                    Face face = myFace[0];
                    myMidPoint = new PointF();
                    face.getMidPoint(myMidPoint);
                    myEyesDistance = face.eyesDistance();

                    if (myMidPoint.x + viewWidth > targetWidth) {
                        while (myMidPoint.x + viewWidth > targetWidth) {
                            myMidPoint.x--;
                        }
                    }
                    if (myMidPoint.y + viewHeight > targetHeight) {
                        while (myMidPoint.y + viewHeight > targetHeight) {
                            myMidPoint.y--;
                        }
                    }
                    resizedBitmap = Bitmap.createBitmap(bitmapOrg,
                            (int) (myMidPoint.x - myEyesDistance),
                            (int) (myMidPoint.y - myEyesDistance),
                            viewWidth, viewHeight, matrix, true);
                } else {
                    resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
                            viewWidth, viewHeight, matrix, true);
                }
                /* convert Bitmap to resource */
                // Bitmap resizedBitmap = Bitmap.createBitmap(targetBitmap,
                // 0,
                // 0, viewWidth, viewHeight, matrix, true);
                BitmapDrawable bd = new BitmapDrawable(resizedBitmap);

                part1.setBackgroundDrawable(bd);

            } catch (Exception e) {
                System.out.println("Error1 : " + e.getMessage()
                        + e.toString());
            }
        }
    });
    part2.post(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            viewHeight = part2.getMeasuredHeight();
            viewWidth = part2.getMeasuredWidth();
            try {

                Paint paint = new Paint();
                paint.setFilterBitmap(true);
                Bitmap bitmapOrg = BitmapFactory.decodeResource(
                        getResources(),
                        R.drawable.sachin_tendulkar_10102013);

                int targetWidth = bitmapOrg.getWidth();
                int targetHeight = bitmapOrg.getHeight();

                Bitmap targetBitmap = Bitmap.createBitmap(targetWidth,
                        targetHeight, Bitmap.Config.ARGB_8888);

                RectF rectf = new RectF(0, 0, viewWidth, viewHeight);

                Canvas canvas = new Canvas(targetBitmap);
                Path path = new Path();

                path.addRect(rectf, Path.Direction.CW);
                canvas.clipPath(path);

                canvas.drawBitmap(
                        bitmapOrg,
                        new Rect(0, 0, bitmapOrg.getWidth(), bitmapOrg
                                .getHeight()), new Rect(0, 0, targetWidth,
                                targetHeight), paint);

                Matrix matrix = new Matrix();
                matrix.postScale(1f, 1f);

                BitmapFactory.Options bitmapFatoryOptions = new BitmapFactory.Options();
                bitmapFatoryOptions.inPreferredConfig = Bitmap.Config.RGB_565;

                bitmapOrg = BitmapFactory.decodeResource(getResources(),
                        R.drawable.sachin_tendulkar_10102013,
                        bitmapFatoryOptions);

                myFace = new FaceDetector.Face[5];
                myFaceDetect = new FaceDetector(targetWidth, targetHeight,
                        5);
                int numberOfFaceDetected = myFaceDetect.findFaces(
                        bitmapOrg, myFace);
                Bitmap resizedBitmap = null;
                if (numberOfFaceDetected > 0) {
                    PointF myMidPoint = null;
                    Face face = myFace[0];
                    myMidPoint = new PointF();
                    face.getMidPoint(myMidPoint);
                    myEyesDistance = face.eyesDistance() + 20;

                    if (myMidPoint.x + viewWidth > targetWidth) {
                        while (myMidPoint.x + viewWidth > targetWidth) {
                            myMidPoint.x--;
                        }
                    }
                    if (myMidPoint.y + viewHeight > targetHeight) {
                        while (myMidPoint.y + viewHeight > targetHeight) {
                            myMidPoint.y--;
                        }
                    }
                    resizedBitmap = Bitmap.createBitmap(bitmapOrg,
                            (int) (myMidPoint.x - myEyesDistance),
                            (int) (myMidPoint.y - myEyesDistance),
                            viewWidth, viewHeight, matrix, true);
                } else {
                    resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
                            viewWidth, viewHeight, matrix, true);
                }
                /* convert Bitmap to resource */
                // Bitmap resizedBitmap = Bitmap.createBitmap(targetBitmap,
                // 0,
                // 0, viewWidth, viewHeight, matrix, true);
                BitmapDrawable bd = new  BitmapDrawable(resizedBitmap);

                part2.setBackgroundDrawable(new BitmapDrawable(
                        getCroppedBitmap(bd.getBitmap())));

            } catch (Exception e) {
                System.out.println("Error1 : " + e.getMessage()
                        + e.toString());
            }
        }
    });
}

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

public Bitmap getCroppedBitmap(Bitmap bitmap) {
    // Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
    // bitmap.getHeight(), Config.ARGB_8888);
    // Canvas canvas = new Canvas(output);
    //
    // final int color = 0xff424242;
    // final Paint paint = new Paint();
    // final Rect rect = new Rect(0, 0, bitmap.getWidth(),
    // bitmap.getHeight());
    //
    // paint.setAntiAlias(true);
    // canvas.drawARGB(0, 0, 0, 0);
    // paint.setColor(color);
    // // canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
    // canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
    // bitmap.getWidth() / 2, paint);
    // paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    // canvas.drawBitmap(bitmap, rect, rect, paint);
    // // Bitmap _bmp = Bitmap.createScaledBitmap(output, 60, 60, false);
    // // return _bmp;
    // return output;

    int targetWidth = bitmap.getWidth();
    int targetHeight = bitmap.getHeight();
    Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,
            Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(targetBitmap);
    Path path = new Path();
    path.addCircle(((float) targetWidth - 1) / 2,
            ((float) targetHeight - 1) / 2,
            (Math.min(((float) targetWidth), ((float) targetHeight)) /    2),
            Path.Direction.CCW);

    canvas.clipPath(path);
    Bitmap sourceBitmap = bitmap;
    canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(),
            sourceBitmap.getHeight()), new Rect(0, 0, targetWidth,
            targetHeight), null);
    return targetBitmap;

}

}

回答1:

The demo works for any image put in the drawable folder,

But if you want to crop any dynamic image, for example any image which is downloaded or chosen from gallery, make few changes in the code :

See the line :

Bitmap bitmapOrg = BitmapFactory.decodeResource(
                    getResources(),
                    R.drawable.sachin_tendulkar_10102013);

Here I am taking the image from the drawable folder, now for any downloaded image, you just need to save that image in the bitmapOrg variable, so just change the above line twice, one for part1 for rectangle and part2 for ciculart with your downloaded image saving to bitmapOrg as bitmap, and use the demo, it will crop your image in rectangle and circular way.