package com.;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
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.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
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.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.iflytek.yl.R;
import com.iflytek.yl.common.base.BaseTitleActivity;
import com.iflytek.yl.common.util.YlLogger;
import com.iflytek.yl.common.volley.YLVolleyUtil;
import com.iflytek.yl.common.widget.BaseToast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.UUID;
public class DetectFaceActivity extends BaseTitleActivity implements View.OnClickListener {
private CameraManager cManager;
private static String TAG = "DetectFaceActivity";
//爲了使照片豎直顯示
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 RelativeLayout capture_crop_layout;
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;
private ImageView scan;
private YLVolleyUtil volleyUtil;
private Handler mHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_faceverify);
initVIew();
}
/**
* 初始化界面
*/
private void initVIew() {
mHandler = new InnerHandler(this);
// volleyUtil = new YLVolleyUtil(this, mHandler);
cView = (TextureView) findViewById(R.id.sfv_preview);
scan = (ImageView) findViewById(R.id.capture_scan_line);
capture_crop_layout = (RelativeLayout) findViewById(R.id.capture_crop_layout);
findViewById(R.id.face_photo).setOnClickListener(this);
ViewGroup.LayoutParams params = capture_crop_layout.getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 4 * 3;
params.height = getResources().getDisplayMetrics().widthPixels / 4 * 3;
capture_crop_layout.setLayoutParams(params);
}
private void startCamera() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
openCamera(true);
}
}, 100);
}
@SuppressLint("NewApi")
private void openCamera(boolean isFront) {
this.isFront = isFront;
//前置攝像頭
String cId = "";
if (isFront) {
cId = CameraCharacteristics.LENS_FACING_BACK + "";
} else {
cId = CameraCharacteristics.LENS_FACING_FRONT + "";
}
cManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "請授予攝像頭權限", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 0);
} else {
//根據攝像頭ID,開啓攝像頭
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);//獲取成像尺寸,同上
YlLogger.i(TAG, "獲取相機角度 : " + cOrientation);
//可用於判斷是否支持人臉檢測,以及支持到哪一種程度
faceDetectModes = characteristics.get(CameraCharacteristics
.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);//支持的人臉檢測模式
int maxFaceCount = characteristics.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);
//支持的最大檢測人臉數量
//此處寫死640*480,實際從預覽尺寸列表選擇
//previewSizes[2];
Size sSize = new Size(640, 480);
//設置預覽尺寸(避免控件尺寸與預覽畫面尺寸不一致時畫面變形)
cView.getSurfaceTexture().setDefaultBufferSize(sSize.getWidth(), sSize.getHeight());
cManager.openCamera(cId, getCDeviceOpenCallback(), getCHandler());
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0
, Animation.RELATIVE_TO_SELF, -1, Animation.RELATIVE_TO_SELF, 0);
translateAnimation.setDuration(1300);
translateAnimation.setRepeatCount(-1);
translateAnimation.setRepeatMode(Animation.RESTART);
scan.startAnimation(translateAnimation);
} catch (CameraAccessException e) {
YlLogger.i(TAG, 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;
//構建預覽請求,併發起請求
YlLogger.i(TAG, "[發出預覽請求]");
try {
session.setRepeatingRequest(getPreviewRequest(), getPreviewCallback(),
getCHandler());
} catch (CameraAccessException e) {
YlLogger.i(TAG, Log.getStackTraceString(e));
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
session.close();
}
}, getCHandler());
} catch (CameraAccessException e) {
YlLogger.i(TAG, 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() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest
request, @NonNull TotalCaptureResult result) {
// 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) {
YlLogger.i(TAG, Log.getStackTraceString(e));
}
}
previewRequestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, getFaceDetectMode());//設置人臉檢測級別
previewRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, 0);
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);
YlLogger.i(TAG, "檢測到有人臉,進行拍照操做:faceLength=" + faces.length);
if (faces.length > 0) {
//檢測到有人臉,控制相機進行拍照操做
executeCapture();
}
}
/**
* 初始化拍照相關
*/
@SuppressLint("NewApi")
private Surface getCaptureSurface() {
if (cImageReader == null) {
cImageReader = ImageReader.newInstance(getCaptureSize().getWidth(), getCaptureSize().getHeight(),
ImageFormat.JPEG, 2);
cImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
//拍照最終回調
onCaptureFinished(reader);
}
}, getCHandler());
captureSurface = cImageReader.getSurface();
}
return captureSurface;
}
/**
* 獲取拍照尺寸
*
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private Size getCaptureSize() {
if (captureSize != null) {
return captureSize;
} else {
return new Size(cView.getWidth(), cView.getHeight());
}
}
/**
* 執行拍照
*/
@SuppressLint("NewApi")
private void executeCapture() {
try {
YlLogger.i(TAG, "發出請求");
cSession.capture(getCaptureRequest(), getCaptureCallback(), getCHandler());
} catch (CameraAccessException e) {
YlLogger.i(TAG, Log.getStackTraceString(e));
}
}
@SuppressLint("NewApi")
private CaptureRequest getCaptureRequest() {
captureRequest = getCaptureRequestBuilder().build();
return captureRequest;
}
@SuppressLint("NewApi")
private CaptureRequest.Builder getCaptureRequestBuilder() {
if (captureRequestBuilder == null) {
try {
captureRequestBuilder = cSession.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//設置拍照回調接口
captureRequestBuilder.addTarget(getCaptureSurface());
//TODO 1 照片旋轉
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int rotationTo = getOrientation(rotation);
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, rotationTo);
} catch (CameraAccessException e) {
YlLogger.i(TAG, Log.getStackTraceString(e));
}
}
return captureRequestBuilder;
}
@SuppressLint("NewApi")
private CameraCaptureSession.CaptureCallback getCaptureCallback() {
if (captureCallback == null) {
captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest
request, @NonNull TotalCaptureResult result) {
}
};
}
return captureCallback;
}
/**
* Retrieves the JPEG orientation from the specified screen rotation.
*
* @param rotation The screen rotation.
* @return The JPEG orientation (one of 0, 90, 270, and 360)
*/
private int getOrientation(int rotation) {
return (ORIENTATIONS.get(rotation) + cOrientation + 270) % 360;
}
/**
* 處理相機拍照完成的數據
*
* @param reader
*/
@SuppressLint("NewApi")
private void onCaptureFinished(ImageReader reader) {
Image image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
image.close();
buffer.clear();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
showImage(bitmap);
Runtime.getRuntime().gc();
}
/**
* 保存照片,調用人臉識別接口
*
* @param image
*/
private void showImage(final Bitmap image) {
mHandler.post(new Runnable() {
@Override
public void run() {
upload(image);
}
});
}
private void upload(Bitmap face) {
if (face == null) {
BaseToast.showToast(getApplicationContext(), "拍照出錯,請重試!");
return;
}
try {
final File file = File.createTempFile(UUID.randomUUID().toString() + "", ".jpg");
int minWidth = Math.min(face.getWidth(), face.getHeight());
int x = (face.getWidth() - minWidth) / 2;
int y = (face.getHeight() - minWidth) / 2;
Bitmap bitmap = Bitmap.createBitmap(face, x, y, minWidth, minWidth);
resize(bitmap, file, 480, 480);
Intent intent = new Intent();
intent.putExtra("filePath", file.getAbsolutePath());
setResult(RESULT_OK, intent);
finish();
} catch (IOException e) {
e.printStackTrace();
}
}
private void deleteFace(File file) {
if (file != null && file.exists()) {
file.delete();
}
}
@SuppressLint("NewApi")
private void closeCamera() {
if (cSession != null) {
try {
cSession.stopRepeating();
} catch (CameraAccessException e) {
e.printStackTrace();
}
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) {
YlLogger.i(TAG, Log.getStackTraceString(e));
}
}
if (captureRequestBuilder != null) {
captureRequestBuilder.removeTarget(captureSurface);
captureRequestBuilder = null;
}
if (captureSurface != null) {
captureSurface.release();
captureSurface = null;
}
if (previewRequestBuilder != null) {
previewRequestBuilder.removeTarget(previewSurface);
previewRequestBuilder = null;
}
if (previewSurface != null) {
previewSurface.release();
previewSurface = null;
}
}
@Override
protected void onResume() {
super.onResume();
startCamera();
}
@Override
protected void onPause() {
super.onPause();
closeCamera();
}
private static class InnerHandler extends Handler {
private WeakReference<DetectFaceActivity> mWeakReference;
public InnerHandler(DetectFaceActivity activity) {
super();
this.mWeakReference = new WeakReference<DetectFaceActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
if (mWeakReference == null || mWeakReference.get() == null) {
return;
}
DetectFaceActivity activity = mWeakReference.get();
if (activity == null) {
return;
}
if (msg == null) {
return;
}
switch (msg.what) {
default:
break;
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.face_photo:
executeCapture();
break;
default:
break;
}
}
private void resize(Bitmap bitmap, File outputFile, int maxWidth, int maxHeight) {
try {
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();
// 圖片大於最大高寬,按大的值縮放
if (bitmapWidth > maxHeight || bitmapHeight > maxWidth) {
float widthScale = maxWidth * 1.0f / bitmapWidth;
float heightScale = maxHeight * 1.0f / bitmapHeight;
float scale = Math.min(widthScale, heightScale);
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);
}
FileOutputStream out = new FileOutputStream(outputFile);
try {
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
複製代碼