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>