andrordstudio 使用自带相机拍照与人脸识别

本文介绍了一个基于Android Studio的项目,实现了使用设备自带相机拍照并进行人脸识别的功能。通过自定义的FaceView类,项目能够检测并绘制出照片中的人脸位置。同时,提供了图片处理、压缩及保存至SD卡的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

andrordstudio 使用自带相机拍照与人脸识别

不说多,直接撸代码

源码地址andrordstudio 使用自带相机拍照与人脸识别

FaceView 人脸检测类

package com.example.administrator.rlsb.util.RLJC;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

import com.example.administrator.rlsb.R;
import com.example.administrator.rlsb.util.SetImagaType;

/**
 * Created by Administrator on 2019/1/24 0024.
 */
public class FaceView extends ImageView {
    public static final String TAG = "FaceView";
    public String path;
    /**
     * 识别图片的宽高
     */
    private int imageWidth, imageHeight;

    private FaceDetector mFaceDetector;

    /**
     * 一次可识别的最大数
     */
    private int maxFace = 3;

    private Bitmap mFaceImage;

    /**
     * 存储识别的脸
     */
    private FaceDetector.Face[] mFaces = new FaceDetector.Face[maxFace];

    /**
     * 真实检测到的人脸数
     */
    private int mFactFaces;

    private float myEyesDistance;

    public FaceView(Context context) {
        super(context);
        init();
    }

    public FaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        BitmapFactory.Options mOptions = new BitmapFactory.Options();
        mOptions.inPreferredConfig = Bitmap.Config.RGB_565;//一定是 565,其他识别不了。
//拿到需要识别的图片
     //   mFaceImage = BitmapFactory.decodeResource(getResources(), R.mipmap.tx, mOptions);
        mFaceImage=new SetImagaType().getFileBitmap("rlsb.jpg");
        imageWidth = mFaceImage.getWidth();
        imageHeight = mFaceImage.getHeight();
        //创建FaceDetector
        mFaceDetector = new FaceDetector(imageWidth, imageHeight, maxFace);
        //开始检测,并将检测到的人脸存到mFaces数组中
        mFactFaces = mFaceDetector.findFaces(mFaceImage, mFaces);
        Log.i("Flog", "检测到人脸数:" + mFactFaces);
    }

    /**
     * 对每个人脸进行画框
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint mPaint = new Paint();
        mPaint.setColor(Color.GREEN);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        //对每个人脸开始画框
        for (int i = 0; i < mFactFaces; i++) {
            FaceDetector.Face face = mFaces[i];
            PointF mPoint = new PointF();
            face.getMidPoint(mPoint);
            myEyesDistance = face.eyesDistance();//得到人脸中心点和眼间距离参数
            canvas.drawRect(
                    mPoint.x - myEyesDistance,
                    mPoint.y - myEyesDistance,
                    mPoint.x + myEyesDistance,
                    (float) (mPoint.y + myEyesDistance * 1.5),
                    mPaint);
        }
    }




}

SetImagaType 图片处理类

package com.example.administrator.rlsb.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.FaceDetector;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by Administrator on 2019/1/25 0025.
 */
public class SetImagaType {

    /**
     * 图片旋转
     * @param bm
     * @param orientationDegree
     * @return
     */
    public static Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {

        Matrix m = new Matrix();
        m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
        float targetX, targetY;
        if (orientationDegree == 90) {
            targetX = bm.getHeight();
            targetY = 0;
        } else {
            targetX = bm.getHeight();
            targetY = bm.getWidth();
        }

        final float[] values = new float[9];
        m.getValues(values);

        float x1 = values[Matrix.MTRANS_X];
        float y1 = values[Matrix.MTRANS_Y];

        m.postTranslate(targetX - x1, targetY - y1);

        Bitmap bm1 = Bitmap.createBitmap(bm.getHeight(), bm.getWidth(), Bitmap.Config.RGB_565);

        Paint paint = new Paint();
        Canvas canvas = new Canvas(bm1);
        canvas.drawBitmap(bm, m, paint);


        return bm1;
    }


    /**
     * 图片压缩 100一下
     * @param image
     * @return
     */
    public static Bitmap comp(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        if( baos.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
            baos.reset();//重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片,此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
        float hh = 800f;//这里设置高度为800f
        float ww = 480f;//这里设置宽度为480f
        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        int be = 1;//be=1表示不缩放
        if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;//设置缩放比例
        //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
        isBm = new ByteArrayInputStream(baos.toByteArray());
        bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
    }
    /**
     * 质量压缩
     * @param image
     * @return
     */
    private static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 100;
        while ( baos.toByteArray().length / 1024>100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();//重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
            options -= 10;//每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
    }


    /**将bitmap对象保存成图片到sd卡中*/
    public static void saveBitmapToSDCard(Bitmap bitmap, String path) {

        File file = new File(Environment.getExternalStorageDirectory()+"/"+path);
        if(file.exists()) {
            file.delete();
        }
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, ((OutputStream)fileOutputStream));//设置PNG的话,透明区域不会变成黑色
            fileOutputStream.close();
         //   System.out.println("----------save success-------------------");
        }
        catch(Exception v0) {
            v0.printStackTrace();
        }

    }


    /**
     * byte[] → Bitmap
     * @param b
     * @return
     */
    public static Bitmap Bytes2Bimap(byte[] b){
        if(b.length!=0){
            return BitmapFactory.decodeByteArray(b, 0, b.length);
        }
        else {
            return null;
        }
    }

    /**
     * 获取 sdk bitmap
     * @param path
     * @return
     */
    public static Bitmap getFileBitmap(String path){
        BitmapFactory.Options mOptions = new BitmapFactory.Options();
        mOptions.inPreferredConfig = Bitmap.Config.RGB_565;//一定是 565,其他识别不了。
        return BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/"+path,mOptions);
    }


    /**
     * bitmap转为base64
     * @param bitmap
     * @return
     */
    public static String bitmapToBase64(Bitmap bitmap) {
        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

                baos.flush();
                baos.close();

                byte[] bitmapBytes = baos.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    /**
     * base64转为bitmap
     * @return
     */
    public static Bitmap base64ToBitmap(String base64Data) {
        byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }


    /**
     *  人脸检测
     * @param mFaceImage
     * @return
     */
    public static boolean RLJC(Bitmap mFaceImage) {

        int maxFace = 3;
        FaceDetector.Face[] mFaces = new FaceDetector.Face[maxFace]; //存储识别的脸
//        BitmapFactory.Options mOptions = new BitmapFactory.Options();
//        mOptions.inPreferredConfig = Bitmap.Config.RGB_565;//一定是 565,其他识别不了。
       //拿到需要识别的图片
        //   mFaceImage = BitmapFactory.decodeResource(getResources(), R.mipmap.tx, mOptions);
//        Bitmap mFaceImage=new SetImagaType().getFileBitmap(ImgName);
        int imageWidth = mFaceImage.getWidth();
        int imageHeight = mFaceImage.getHeight();
        //创建FaceDetector
        FaceDetector mFaceDetector = new FaceDetector(imageWidth, imageHeight, maxFace);
        //开始检测,并将检测到的人脸存到mFaces数组中
        int mFactFaces = mFaceDetector.findFaces(mFaceImage, mFaces);
        Log.i("Flog", "检测到人脸数:" + mFactFaces);
        if (mFactFaces>0){
            return true;
        }else {
            return false;
        }

    }

}

StaticActivity 识别展示类

package com.example.administrator.rlsb.util.RLJC;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.example.administrator.rlsb.R;
import com.example.administrator.rlsb.util.SetImagaType;

import java.io.File;

public class StaticActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_static);
        FaceView mFaceView=(FaceView)findViewById(R.id.FaceView_id);
        Bitmap mFaceImage= SetImagaType.getFileBitmap("rlsb.jpg");
        mFaceView.setImageBitmap(mFaceImage);


    }



}

Main2Activity 类

package com.example.administrator.rlsb.util.MyCarema;

import android.content.Intent;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.administrator.rlsb.R;
import com.example.administrator.rlsb.util.RLJC.StaticActivity;
import com.example.administrator.rlsb.util.SetImagaType;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main2Activity extends AppCompatActivity {

    private SurfaceView sfv_preview;
    private Button btn_take;
    private Camera camera = null;
    private SurfaceHolder.Callback cpHolderCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            startPreview();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            stopPreview();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        bindViews();
        Log.i("Flog","新建拍照-1");
    }

    private void bindViews() {
        sfv_preview = (SurfaceView) findViewById(R.id.sfv_preview);
        btn_take = (Button) findViewById(R.id.btn_take);
        sfv_preview.getHolder().addCallback(cpHolderCallback);

        btn_take.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                camera.takePicture(null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {

                        //拍照处理
                        Bitmap bitmap=SetImagaType.Bytes2Bimap(data);//转Bitmap
                        bitmap=SetImagaType.comp(bitmap);//压缩
                        bitmap=SetImagaType.adjustPhotoRotation(bitmap,90);//旋转
                        SetImagaType.saveBitmapToSDCard(bitmap,"rlsb.jpg");//保存
                        boolean b= SetImagaType.RLJC(bitmap);//人脸检测
                        Log.i("Flog","是否有人脸-"+b);
                        String path = "";
                        if ((path = saveFile(data)) != null) {
                          //  Intent it = new Intent(Main2Activity.this, PreviewActivity.class);
                            Intent it = new Intent(Main2Activity.this, StaticActivity.class);
                            it.putExtra("path", path);
                            startActivity(it);
                        } else {
                            Toast.makeText(Main2Activity.this, "保存照片失败", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
    }

    //保存临时文件的方法
    private String saveFile(byte[] bytes){
        try {
            File file = File.createTempFile("img","");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bytes);
            fos.flush();
            fos.close();
            return file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    //开始预览
    private void startPreview(){
        camera = Camera.open();
        try {
            camera.setPreviewDisplay(sfv_preview.getHolder());
            camera.setDisplayOrientation(90);   //让相机旋转90度
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //停止预览
    private void stopPreview() {
        camera.stopPreview();
        camera.release();
        camera = null;
    }



}



Main2Activity 布局

<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.administrator.rlsb.util.MyCarema.Main2Activity">

    <SurfaceView
        android:id="@+id/sfv_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <Button
        android:id="@+id/btn_take"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用系统照相机" />
</LinearLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值