Android人脸检测1(静态图片)

时间:2022-04-23 14:24:38

搭建Android人脸识别环境花了很长时间(可以查看之前的文章),解决Android开发中的杂七杂八小问题也耗时不少.

今天记录一下,点击选择照片或者拍照上传照片进行人脸检测的小demo.

(android.media.FaceDetector;方法)

先看效果图:

手机在电脑拍摄的图片:

Android人脸检测1(静态图片)

要点说明:

参考:  http://blog.csdn.net/zhandoushi1982/article/details/8613916

1,  必须要把bitmap转换RGB_565才能检测

bitmap565 = bitmap.copy(Bitmap.Config.RGB_565, true);

2, 给bitmap画框

Canvas canvas = new Canvas(bitmap565);

参考:  https://*.com/questions/4918079/android-drawing-a-canvas-to-an-imageview

3, 调用系统相册相机需要配置权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

4, 调用 FaceDetector 感觉很慢,而且会识别多余人脸,最后附图.

5, 后续做动态人脸检测.

代码:

package com.***.facedetection;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File; public class MainActivity extends AppCompatActivity { private static String CAMERAIMAGENAME = "image.jpg";
private customImageButton imageButton;
private TextView textView;
private Bitmap bitmap;
private Bitmap resizeBitmap;
private int numberOfFaceDetected;
private FaceDetector.Face[] myFace;
private Bitmap bitmap565;
private Toast toast; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.tv_face);
imageButton = (customImageButton) findViewById(R.id.iv_face);
imageButton.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL); } /**
* 点击添加照片事件
*
* @param v
*/
public void onClick(View v) { int bt_id = v.getId();
switch (bt_id) {
case R.id.addPic:
// 添加照片
// 打开本地相册
Intent intent1 = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent1, 101);
break; case R.id.takePhoto:
// 拍照
// 打开本地相机
Intent intent2 = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), CAMERAIMAGENAME));
intent2.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent2, 102); break; default:
break;
} } @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 加判断 不选择照片或者不拍照时不闪退
//Log.e("data", String.valueOf(data));
//if (data == null)
//return; bitmap = null;
switch (requestCode) {
// 选择图片库的图片
case 101:
if (resultCode == RESULT_OK) {
try {
Uri uri = data.getData();
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri); } catch (Exception e) {
e.printStackTrace();
}
}
break; // 表示调用本地照相机拍照
case 102:
if (resultCode == RESULT_OK) {
//Bundle bundle = data.getExtras();
//bm = (Bitmap) bundle.get("data");
bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/" + CAMERAIMAGENAME); }
break;
default:
break;
} Log.e("bitmap", String.valueOf(bitmap)); if (bitmap == null) {
toast = Toast.makeText(MainActivity.this, "未选择图像", Toast.LENGTH_SHORT);
toast.show();
return;
} // 转换 释放
bitmap565 = bitmap.copy(Bitmap.Config.RGB_565, true); if (!bitmap.isRecycled())
bitmap.recycle(); // 识别图片
detectFace(); // 画框
drawFace(); // 将照片剪裁 bitmap将被释放重新赋值
int ibWidth = imageButton.getWidth();
int ibHeight = imageButton.getHeight();
resizeBitmap = imageButton.cropBitmap(bitmap565, ibWidth, ibHeight); imageButton.setBitmap(resizeBitmap); } private void detectFace() {
int numberOfFace = 12;
FaceDetector myFaceDetect; int imageWidth = bitmap565.getWidth();
int imageHeight = bitmap565.getHeight();
myFace = new FaceDetector.Face[numberOfFace];
myFaceDetect = new FaceDetector(imageWidth, imageHeight, numberOfFace);
numberOfFaceDetected = myFaceDetect.findFaces(bitmap565, myFace); textView.setText(String.format("检测到%1$d个人脸", numberOfFaceDetected)); } private void drawFace() {
Canvas canvas = new Canvas(bitmap565);
// canvas.drawBitmap(bitmap565, 0, 0, null);
Paint myPaint = new Paint();
myPaint.setColor(Color.GREEN);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(3);
for (int i = 0; i < numberOfFaceDetected; i++) {
FaceDetector.Face face = myFace[i];
PointF myMidPoint = new PointF();
face.getMidPoint(myMidPoint);
float myEyesDistance = face.eyesDistance();
canvas.drawRect((int) (myMidPoint.x - myEyesDistance * 1.5),
(int) (myMidPoint.y - myEyesDistance * 1.5),
(int) (myMidPoint.x + myEyesDistance * 1.5),
(int) (myMidPoint.y + myEyesDistance * 1.8), myPaint);
} } }

自定义ImageButton类,可以按比例缩放bitmap适应ImageButton居中显示:

package com.***.facedetection;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; public class customImageButton extends LinearLayout {
private TextView _textView;
private ImageView _imageView; public customImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
_imageView = new ImageView(context, attrs);
_imageView.setPadding(2, 2, 2, 2); _textView = new TextView(context, attrs);
_textView.setBackgroundColor(Color.TRANSPARENT);
_textView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
_textView.setPadding(0, 0, 0, 0); setClickable(true);
setFocusable(true);
setOrientation(LinearLayout.VERTICAL);
addView(_textView);
addView(_imageView);
} public void setText(String text) {
_textView.setText(text);
} public void setButtonEnable(Boolean bool) {
_imageView.setEnabled(bool);
} public void clearnImage() {
_textView.setVisibility(View.VISIBLE);
_imageView.setImageDrawable(null);
} public void setBitmap(Bitmap bm) {
_textView.setVisibility(View.GONE);
_imageView.setImageDrawable(null);
_imageView.setImageBitmap(bm); } public Bitmap cropBitmap(Bitmap bm, int ivbWidth, int ivbHeight) {
Bitmap resizeBmp = null;
try { Matrix matrix = new Matrix(); float scale;
if (ivbWidth <= ivbHeight) {
scale = (float) ivbWidth / bm.getWidth();
matrix.postScale(scale, scale); //长和宽放大缩小的比例
resizeBmp = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} else {
scale = (float) ivbHeight / bm.getHeight();
matrix.postScale(scale, scale);
resizeBmp = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} Log.e("scale", scale + ""); if (!bm.isRecycled())
bm.recycle(); } catch (Exception e) {
e.printStackTrace(); }
return resizeBmp;
} }

布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.***.facedetection.MainActivity"> <com.***.facedetection.customImageButton
android:id="@+id/iv_face"
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" /> <TextView
android:id="@+id/tv_face"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="未检测到人脸"
android:textColor="@color/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/takePhoto"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" /> <Button
android:id="@+id/takePhoto"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:onClick="onClick"
android:text="拍照"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/addPic"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" /> <Button
android:id="@+id/addPic"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="选择图片"
android:textSize="16sp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout>

检测多余人脸:

Android人脸检测1(静态图片)