faceRectList) {
Bitmap bitmap = Nv21Util.nv21ToBitmap(data, width, height);
if (!faceRectList.isEmpty()) {
Rect rect = faceRectList.get(0);
//剪裁人脸
Bitmap cropBitmap = Nv21Util.cropNv21ToBitmap(data, width, height, rect);
}
}
/**
* 首次检测到有人时调用一次
*/
@MainThread
@Override
public void somebody() {
}
/**
* 首次检测到无人时调用一次
*/
@MainThread
@Override
public void nobody() {
}
});
//设置相机预览分辨率
fdv.setPreviewStreamSize(source -> Collections.singletonList(new Size(1280, 720)));
//设置摄像头
fdv.setCameraFacing(Facing.BACK);
//设置是否只保留最大人脸
fdv.setKeepMaxFace(true);
//是否镜像预览
fdv.setPreviewMirror(false);
//设置是否检测区域限制,注意:目前限制的区域是人脸是否完整在预览View显示的画面里
fdv.setDetectAreaLimited(true);
//是否绘制人脸框
fdv.setDrawFaceRect(true);
//设置人脸框颜色
fdv.setFaceRectStrokeColor(Color.GREEN);
//设置人脸框的宽度
fdv.setFaceRectStrokeWidth(2f);
//重试操作
fdv.needRetry();
//延迟重试操作
fdv.needRetryDelay(1000L);
//设置目标检测的级联分类器
fdv.loadClassifierCascade(R.raw.haarcascade_eye, new LoadClassifierCallback() {
@Override
public void onSuccess() {
}
@Override
public void onError(Exception e) {
}
});
fdv.setLifecycleOwner(this);
//fdv.open();
//fdv.close();
//fdv.destroy();
```
- FaceDetectRequestDialog
> 代码示例
```java
FaceDetectRequestDialog requestDialog = FaceDetectRequestDialog.builder(this,
new RequestDialogLayoutCallback() {
/**
* 设置{@link FaceDetectRequestDialog#setContentView(int)}
*
* @return
*/
@Override
public int getLayoutId() {
return R.layout.dialog_face_detect_request;
}
/**
* 设置{@link RequestDialogLayoutCallback#getLayoutId()} 中 {@link FaceDetectCameraView}的id
*
* @return
*/
@Override
public int getFaceDetectCameraViewId() {
return R.id.detectCameraView;
}
/**
* init view
* (e.g. {@code dialog.findViewById(id)}).
*
* @param dialog FaceDetectRequestDialog
*/
@Override
public void initView(FaceDetectRequestDialog dialog) {
// Button btnClose = dialog.findViewById(R.id.btnClose);
}
/**
* Called when the dialog is starting.
*
* @param dialog FaceDetectRequestDialog
*/
@Override
public void onStart(FaceDetectRequestDialog dialog) {
}
/**
* Called when the dialog is starting.
*
* @param dialog FaceDetectRequestDialog
*/
@Override
public void onStop(FaceDetectRequestDialog dialog) {
}
/**
* @param dialog FaceDetectRequestDialog
* @see FaceDetectRequestDialog#destroy()
*/
@Override
public void onDestroy(FaceDetectRequestDialog dialog) {
}
},
new RequestCallback() {
/**
* 生成用于网络请求的{@link OkHttpClient}
* 自动调用{@link OkHttpClient.Builder#build()}
*
* @param builder
* @return
*/
@Override
@NonNull
public OkHttpClient.Builder generateOkhttpClient(OkHttpClient.Builder builder) {
return builder;
}
/**
* 生成网络请求的{@link Request}
* 自行根据人脸照片数据进行二次封装
*
* 自动调用{@link Request.Builder#build()}
*
* @param builder
* @return
*/
@NonNull
@Override
public Request.Builder generateRequest(Request.Builder builder, byte[] data, int width, int height, List faceRectList) {
Bitmap bitmap = Nv21Util.nv21ToBitmap(data, width, height);
// Bitmap bitmap = Nv21Util.cropNv21ToBitmap(data, width, height, faceRectList.get(0));
if (bitmap != null) {
String base64 = BitmapUtil.bitmapToBase64(bitmap, 100);
RequestFaceBean bean = new RequestFaceBean("cmd", base64);
RequestBody body = RequestBody.create(MediaType.parse("application/json"), GsonUtil.toJson(bean));
builder.url("http://xxx:8080")
.post(body);
}
return builder;
}
/**
* 网络请求开始
*
* @param dialog FaceDetectRequestDialog
*/
@Override
public void onRequestStart(FaceDetectRequestDialog dialog) {
}
/**
* 网络请求失败
*
* @param e error
* @param dialog FaceDetectRequestDialog
*/
@Override
public void onRequestFailure(Exception e, FaceDetectRequestDialog dialog) {
Toast.makeText(MainActivity.this, "人脸识别Error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
dialog.needRetryDelay(2000L);
}
/**
* 网络请求成功
*
* @param bodyStr 网络请求返回的String字符串
* @param dialog FaceDetectRequestDialog
*/
@Override
public void onRequestSuccess(String bodyStr, FaceDetectRequestDialog dialog) {
ResultBean resultBean = GsonUtil.jsonToBean(bodyStr, ResultBean.class);
if (resultBean.getResCode() == 1) {
Toast.makeText(MainActivity.this, "人脸识别成功:" + resultBean.getData().getUserName(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "人脸识别失败", Toast.LENGTH_SHORT).show();
dialog.needRetryDelay(2000L);
}
}
})
.setPreviewSizeSelector(source -> Collections.singletonList(new Size(1280, 720)))
.setShowLoadingDialog(true)
.setCameraListener(exception -> Toast.makeText(MainActivity.this, "摄像头开启异常:" + exception.getMessage(), Toast.LENGTH_SHORT).show())
.setAnybodyCallback(new AnybodyCallback() {
@Override
public void somebody() {
System.out.println("有人--->");
}
@Override
public void nobody() {
System.out.println("无人--->");
}
}).build();
//重试操作
requestDialog.needRetry();
//延迟重试操作
requestDialog.needRetryDelay(1000L);
//设置目标检测的级联分类器
requestDialog.loadClassifierCascade(R.raw.haarcascade_eye, new LoadClassifierCallback() {
@Override
public void onSuccess() {
}
@Override
public void onError(Exception e) {
}
});
requestDialog.show();
requestDialog.dismiss();//requestDialog.cancel();
requestDialog.destroy();
```
- Nv21Util
> nv21转bitmap工具类
```java
//nv21转Bitmap
Nv21Util.nv21ToBitmap(@NonNull byte[] nv21, int width, int height);
//nv21剪裁转Bitmap,注:会进行二次转换,剪裁出的图片要比提供位置矩阵的略大
Nv21Util.cropNv21ToBitmap(@NonNull byte[] nv21, int width, int height, Rect rect);
```
- BitmapUtil
```java
//Bitmap转base64
BitmapUtil.bitmapToBase64(@Nullable Bitmap bitmap, int quality);
```
## 级联分类器
[基于OpenCV源码](https://github.com/shenbengit/JavaCV-FaceDetect/tree/master/lib/src/main/res/raw)
# [License](https://github.com/shenbengit/JavaCV-FaceDetect/blob/master/LICENSE)