添加权限
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.yl.fecedetectdemo.R;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class MainActivity extends Activity {
private static void Log(String message) {
Log.i(MainActivity.class.getName(), message);
}
//为了使照片竖直显示
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private TextureView cView;//用于相机预览
private TextureView rView;//用于标注人脸
private ImageView imageView;//拍照照片显示
private TextView textView;
private Button btnFront;
private Button btnBack;
private Button btnClose;
private Button btnCapture;
private Surface previewSurface;//预览Surface
private ImageReader cImageReader;
private Surface captureSurface;//拍照Surface
HandlerThread cHandlerThread;//相机处理线程
Handler cHandler;//相机处理
CameraDevice cDevice;
CameraCaptureSession cSession;
CameraDevice.StateCallback cDeviceOpenCallback = null;//相机开启回调
CaptureRequest.Builder previewRequestBuilder;//预览请求构建
CaptureRequest previewRequest;//预览请求
CameraCaptureSession.CaptureCallback previewCallback;//预览回调
CaptureRequest.Builder captureRequestBuilder;
CaptureRequest captureRequest;
CameraCaptureSession.CaptureCallback captureCallback;
int[] faceDetectModes;
// Rect rRect;//相机成像矩形
Size cPixelSize;//相机成像尺寸
int cOrientation;
Size captureSize;
boolean isFront;
Paint pb;
Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_face);
//GlobalExceptionHandler catchHandler = GlobalExceptionHandler.getInstance();
//catchHandler.init(this.getApplication());
initVIew();
}
/**
* 初始化界面
*/
private void initVIew() {
cView = (TextureView) findViewById(R.id.cView);
rView = (TextureView) findViewById(R.id.rView);
imageView = (ImageView) findViewById(R.id.imageView);
textView = (TextView) findViewById(R.id.textView);
btnFront = (Button) findViewById(R.id.btnFront);
btnBack = (Button) findViewById(R.id.btnBack);
btnClose = (Button) findViewById(R.id.btnClose);
btnCapture = (Button) findViewById(R.id.btnCapture);
//隐藏背景色,以免标注人脸时挡住预览画面
rView.setAlpha(0.9f);
btnFront.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamera(true);
}
});
btnBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamera(false);
}
});
btnClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
closeCamera();
}
});
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
executeCapture();
}
});
//TODO 摄像头静音尝试
// try {
// Class> cClass = Class.forName("android.hardware.Camera");
// Method mOpen = cClass.getDeclaredMethod("open");
// Object nCamera = mOpen.invoke(null);
// Method mDisableShutterSound = cClass.getDeclaredMethod("disableShutterSound");
// mDisableShutterSound.invoke(nCamera);
// Method mRelease = cClass.getDeclaredMethod("release");
// mRelease.invoke(nCamera);
// } catch (ClassNotFoundException e) {
// Log(Log.getStackTraceString(e));
// } catch (NoSuchMethodException e) {
// Log(Log.getStackTraceString(e));
// } catch (IllegalAccessException e) {
// Log(Log.getStackTraceString(e));
// } catch (InvocationTargetException e) {
// Log(Log.getStackTraceString(e));
// }
}
@SuppressLint("NewApi")
private void openCamera(boolean isFront) {
closeCamera();
this.isFront = isFront;
String cId = null;
if (isFront) {
cId = CameraCharacteristics.LENS_FACING_BACK + "";
} else {
cId = CameraCharacteristics.LENS_FACING_FRONT + "";
}
CameraManager cManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
//获取开启相机的相关参数
CameraCharacteristics characteristics = cManager.getCameraCharacteristics(cId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);//获取预览尺寸
Size[] captureSizes = map.getOutputSizes(ImageFormat.JPEG);//获取拍照尺寸
cOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);//获取相机角度
Rect cRect = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);//获取成像区域
cPixelSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE);//获取成像尺寸,同上
//可用于判断是否支持人脸检测,以及支持到哪种程度
faceDetectModes = characteristics.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);//支持的人脸检测模式
int maxFaceCount = characteristics.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);//支持的最大检测人脸数量
//此处写死640*480,实际从预览尺寸列表选择
Size sSize = new Size(640,480);//previewSizes[0];
//设置预览尺寸(避免控件尺寸与预览画面尺寸不一致时画面变形)
cView.getSurfaceTexture().setDefaultBufferSize(sSize.getWidth(),sSize.getHeight());
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
Toast.makeText(this,"请授予摄像头权限",Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA}, 0);
return;
}
//根据摄像头ID,开启摄像头
try {
cManager.openCamera(cId, getCDeviceOpenCallback(), getCHandler());
} catch (CameraAccessException e) {
Log(Log.getStackTraceString(e));
}
} catch (CameraAccessException e) {
Log(Log.getStackTraceString(e));
}
}
@SuppressLint("NewApi")
private void closeCamera(){
if (cSession != null){
cSession.close();
cSession = null;
}
if (cDevice!=null){
cDevice.close();
cDevice = null;
}
if (cImageReader != null) {
cImageReader.close();
cImageReader = null;
captureRequestBuilder = null;
}
if(cHandlerThread!=null){
cHandlerThread.quitSafely();
try {
cHandlerThread.join();
cHandlerThread = null;
cHandler = null;
} catch (InterruptedException e) {
Log(Log.getStackTraceString(e));
}
}
}
/**
* 初始化并获取相机开启回调对象。当准备就绪后,发起预览请求
*/
@SuppressLint("NewApi")
private CameraDevice.StateCallback getCDeviceOpenCallback(){
if(cDeviceOpenCallback == null){
cDeviceOpenCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cDevice = camera;
try {
//创建Session,需先完成画面呈现目标(此处为预览和拍照Surface)的初始化
camera.createCaptureSession(Arrays.asList(getPreviewSurface(), getCaptureSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
cSession = session;
//构建预览请求,并发起请求
Log("[发出预览请求]");
try {
session.setRepeatingRequest(getPreviewRequest(), getPreviewCallback(), getCHandler());
} catch (CameraAccessException e) {
Log(Log.getStackTraceString(e));
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
session.close();
}
}, getCHandler());
} catch (CameraAccessException e) {
Log(Log.getStackTraceString(e));
}
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
camera.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
camera.close();
}
};
}
return cDeviceOpenCallback;
}
/**
* 初始化并获取相机线程处理
* @return
*/
private Handler getCHandler(){
if(cHandler==null){
//单独开一个线程给相机使用
cHandlerThread = new HandlerThread("cHandlerThread");
cHandlerThread.start();
cHandler = new Handler(cHandlerThread.getLooper());
}
return cHandler;
}
/**
* 获取支持的最高人脸检测级别
* @return
*/
private int getFaceDetectMode(){
if(faceDetectModes == null){
return CaptureRequest.STATISTICS_FACE_DETECT_MODE_FULL;
}else{
return faceDetectModes[faceDetectModes.length-1];
}
}
/*---------------------------------预览相关---------------------------------*/
/**
* 初始化并获取预览回调对象
* @return
*/
@SuppressLint("NewApi")
private CameraCaptureSession.CaptureCallback getPreviewCallback (){
if(previewCallback == null){
previewCallback = new CameraCaptureSession.CaptureCallback(){
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
MainActivity.this.onCameraImagePreviewed(result);
}
};
}
return previewCallback;
}
/**
* 生成并获取预览请求
* @return
*/
@SuppressLint("NewApi")
private CaptureRequest getPreviewRequest(){
previewRequest = getPreviewRequestBuilder().build();
return previewRequest;
}
/**
* 初始化并获取预览请求构建对象,进行通用配置,并每次获取时进行人脸检测级别配置
* @return
*/
@SuppressLint("NewApi")
private CaptureRequest.Builder getPreviewRequestBuilder(){
if(previewRequestBuilder == null){
try {
previewRequestBuilder = cSession.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(getPreviewSurface());
previewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);//自动曝光、白平衡、对焦
} catch (CameraAccessException e) {
Log(Log.getStackTraceString(e));
}
}
previewRequestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,getFaceDetectMode());//设置人脸检测级别
return previewRequestBuilder;
}
/**
* 获取预览Surface
* @return
*/
private Surface getPreviewSurface(){
if(previewSurface == null){
previewSurface = new Surface(cView.getSurfaceTexture());
}
return previewSurface;
}
/**
* 处理相机画面处理完成事件,获取检测到的人脸坐标,换算并绘制方框
* @param result
*/
@SuppressLint({"NewApi", "LocalSuppress"})
private void onCameraImagePreviewed(CaptureResult result){
Face faces[]=result.get(CaptureResult.STATISTICS_FACES);
showMessage(false,"人脸个数:["+faces.length+"]");
Canvas canvas = rView.lockCanvas();
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//旧画面清理覆盖
if(faces.length>0){
for(int i=0;i
界面代码