Android人脸检测1(静态图片)
搭建Android人脸识别环境花了很长时间(可以查看之前的文章),解决Android开发中的杂七杂八小问题也耗时不少.
今天记录一下,点击选择照片或者拍照上传照片进行人脸检测的小demo.
(android.media.FaceDetector;方法)
先看效果图:
手机在电脑拍摄的图片:
要点说明:
参考: 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://stackoverflow.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(静态图片)的更多相关文章
- Android+openCV人脸检测2(静态图片)
前几篇文章中有提到对openCV环境配置,这里再重新梳理导入和使用openCV进行简单的人脸检测(包括使用级联分类器) 一 首先导入openCVLibrary320 二 设置gradle的sdk版本号 ...
- android 人脸检测你一定会遇到的坑
笔者今年做了一个和人脸有关的android产品,主要是获取摄像头返回的预览数据流,判断该数据流是否包含了人脸,有人脸时显示摄像头预览框,无人脸时摄像头预览框隐藏,看上去这个功能并不复杂,其实在开发过程 ...
- OpenCV人脸检测并把图片写成avi视频
读出某一个文件夹下“jpg”后缀的全部图片后,用的OpenCV自带的人脸检测检测图片中的人脸,调整图片的大小写成一个avi视频. 主要是要记录一下CvVideoWriter的用法和如何从文件夹中读取某 ...
- 虹软 Android 人脸检测与人脸识别集成分享
目前我们的应用内使用了 ArcFace 的人脸检测功能,其他的我们并不了解,所以这里就和大家分享一下我们的集成过程和一些使用心得 集成ArcFace FD 的集成过程非常简单 在 ArcFace FD ...
- ArcFace Android 人脸检测与人脸识别集成分享
目前我们的应用内使用了 ArcFace 的人脸检测功能,其他的我们并不了解,所以这里就和大家分享一下我们的集成过程和一些使用心得集成ArcFace FD 的集成过程非常简单在 ArcFace FD 的 ...
- OpenCV神技——人脸检测,猫脸检测
简介 OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效--由一系列 C 函数和少量 ...
- OpenCV + Python 人脸检测
必备知识 Haar-like opencv api 读取图片 灰度转换 画图 显示图像 获取人脸识别训练数据 探测人脸 处理人脸探测的结果 实例 图片素材 人脸检测代码 人脸检测结果 总结 下午的时候 ...
- Android中显示gif动态图片
在android中显示一个静态图片比如png jpg等等都很方便,但是如果要显示一个gif 动态图片就需要进行一些处理. 本文是采用自定义view 然后进行重新onDraw方法来实现 首先自定义Vie ...
- OpenCV + python 实现人脸检测(基于照片和视频进行检测)
OpenCV + python 实现人脸检测(基于照片和视频进行检测) Haar-like 通俗的来讲,就是作为人脸特征即可. Haar特征值反映了图像的灰度变化情况.例如:脸部的一些特征能由矩形特征 ...
随机推荐
- Spring MVC 使用介绍(九)—— 异常处理
一.概述 Spring MVC异常处理功能的作用为:捕捉处理器的异常,并映射到相应视图 有4种方式: SimpleMappingExceptionResolver:通过配置的方式实现异常处理,该方式简 ...
- 【LR9】【LOJ561】CommonAnts 的调和数 数论 筛法
题目大意 有一个长度为 \(n\) 的序列. 有 \(m\) 次修改,每次给你 \(x,y\),令 \(\forall 1\leq i\leq \lfloor\frac{n}{x}\rfloor,a_ ...
- bzoj3527: [Zjoi2014]力 卷积+FFT
先写个简要题解:本来去桂林前就想速成一下FFT的,结果一直没有速成成功,然后这几天断断续续看了下,感觉可以写一个简单一点的题了,于是就拿这个题来写,之前式子看着别人的题解都不太推的对,然后早上6点多推 ...
- jenkins系列之jenkins job
第一步:在 jenkins 左边栏点击 "新建", 输入 job 名称,选择 "构建一个自由风格的软件项目" 一项.点击 "OK" . 第二 ...
- Dubbo2.6.5入门——简单的HelloWorld
建立父工程 打开idea,新建一个空的maven工程,作为整个项目的父工程. <?xml version="1.0" encoding="UTF-8"?& ...
- 20175221 实验一《Java开发环境的熟悉》实验报告
20175221 实验一<Java开发环境的熟悉>实验报告 (一)Linux运行结果 (二)IDEA下Java程序开发.调试:学会通过调试(Debug)来定位逻辑错误 试验IDEA是否 ...
- 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)
[GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...
- NSE: known a priori estimate
1. Leray-Hopf $u\in L^\infty(0,T;L^2(\bbR^3))\cap L^2(0,T;H^1(\bbR^3))$. See [Leray, Jean. Sur le mo ...
- javascript通过navigator.userAgent识别各种浏览器
识别各种浏览器的实现原理是根据navigator.userAgent返回值识别: 实现: unction validBrowser(){ var u_agent = navigator.userAge ...
- Linux文件权限命令及配置
http://www.cnblogs.com/CgenJ/archive/2011/07/28/2119454.html