百度人脸识别官方的sdk 只有前置摄像头+竖屏的方式,要横屏需要自己去适配了。
在百度sdk中有FaceDetectStrategyExtModule 这个类 里面有这样一段代码:
private void processStrategy(byte[] imageData) {
BDFaceImageInstance imageInstance = new BDFaceImageInstance(imageData, this.mPreviewRect.width(), this.mPreviewRect.height(), BDFaceImageType.BDFACE_IMAGE_TYPE_YUV_NV21, (float)(360 - this.mDegree), 1);
FaceInfo[] faceInfos = FaceSDKManager.getInstance().detect(imageInstance);
FaceModel model = this.setFaceModel(faceInfos, imageInstance);
this.processUIResult(model, imageInstance);
}
(360 – this.mDegree) 矫正了图像的旋转度数
竖屏前置需要旋转90度。才能矫正
if (mIDetectStrategy == null ){
mIDetectStrategy = FaceSDKManager.getInstance().getDetectStrategyModule();
mIDetectStrategy.setPreviewDegree(90); //前置竖屏
mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
// Rect detectRect = mFaceDetectRoundViewNew.getPreviewDetectRect();
mPreviewRect.set(0, 0,480,640);
Rect detectRect = new Rect( 0, 0, 480, 640 );
mIDetectStrategy.setDetectStrategyConfig(mPreviewRect, detectRect, this);
}
竖屏后置需要旋转270度。
if (mIDetectStrategy == null ){
mIDetectStrategy = FaceSDKManager.getInstance().getDetectStrategyModule();
mIDetectStrategy.setPreviewDegree(270); //后置竖屏
mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
// Rect detectRect = mFaceDetectRoundViewNew.getPreviewDetectRect();
mPreviewRect.set(0, 0,480,640);
Rect detectRect = new Rect( 0, 0, 480, 640 );
mIDetectStrategy.setDetectStrategyConfig(mPreviewRect, detectRect, this);
}
处理NV21图片 不需要去旋转角度了。(这里摄像头id注意切换判断)
横屏的前置和后置 图片都是显示正确的,为了和sdk 兼容,我们需要调整度数
if (mIDetectStrategy == null ){
mIDetectStrategy = FaceSDKManager.getInstance().getDetectStrategyModule();
mIDetectStrategy.setPreviewDegree(90); //前置+后置 横屏
mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
// Rect detectRect = mFaceDetectRoundViewNew.getPreviewDetectRect();
mPreviewRect.set(0, 0,480,640);
Rect detectRect = new Rect( 0, 0, 480, 640 );
mIDetectStrategy.setDetectStrategyConfig(mPreviewRect, detectRect, this);
}
这里得到的预览图片需要旋转90度,在送去解析,使用矩阵的变换方式。
完成的竖屏方式源码:
/**
* Copyright (C) 2017 Baidu Inc. All rights reserved.
*/
package com.baidu.idl.face.platform.ui;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.baidu.idl.face.platform.FaceConfig;
import com.baidu.idl.face.platform.FaceSDKManager;
import com.baidu.idl.face.platform.FaceStatusNewEnum;
import com.baidu.idl.face.platform.IDetectStrategy;
import com.baidu.idl.face.platform.IDetectStrategyCallback;
import com.baidu.idl.face.platform.model.ImageInfo;
import com.baidu.idl.face.platform.ui.utils.BrightnessUtils;
import com.baidu.idl.face.platform.ui.utils.CameraUtils;
import com.baidu.idl.face.platform.ui.utils.VolumeUtils;
import com.baidu.idl.face.platform.ui.widget.FaceDetectRoundView;
import com.baidu.idl.face.platform.ui.widget.FaceDetectRoundViewNew;
import com.baidu.idl.face.platform.utils.APIUtils;
import com.baidu.idl.face.platform.utils.Base64Utils;
import com.baidu.idl.face.platform.ui.utils.CameraPreviewUtils;
import com.baidu.idl.face.platform.utils.FileUtils;
import com.baidu.idl.main.facesdk.model.BDFaceImageInstance;
import com.baidu.idl.main.facesdk.model.BDFaceSDKCommon;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 人脸采集接口
* 横屏
*/
public class FaceDetectActivity extends Activity implements
SurfaceHolder.Callback,
Camera.PreviewCallback,
Camera.ErrorCallback,
VolumeUtils.VolumeCallback,
IDetectStrategyCallback {
public static final String TAG = FaceDetectActivity.class.getSimpleName();
// View
protected View mRootView;
protected FrameLayout mFrameLayout;
protected SurfaceView mSurfaceView;
protected SurfaceHolder mSurfaceHolder;
//protected FaceDetectRoundView mFaceDetectRoundView;
protected FaceDetectRoundViewNew mFaceDetectRoundViewNew;
// 人脸信息
protected FaceConfig mFaceConfig;
protected IDetectStrategy mIDetectStrategy;
// 显示Size
private Rect mPreviewRect = new Rect();
protected int mDisplayWidth = 0;
protected int mDisplayHeight = 0;
protected int mSurfaceWidth = 0;
protected int mSurfaceHeight = 0;
protected Drawable mTipsIcon;
// 状态标识
protected volatile boolean mIsEnableSound = true;
protected HashMap<String, String> mBase64ImageMap = new HashMap<String, String>();
protected boolean mIsCreateSurface = false;
protected volatile boolean mIsCompletion = false;
// 相机
protected Camera mCamera;
protected Camera.Parameters mCameraParam;
protected int mCameraId;
protected int mPreviewWidth;
protected int mPreviewHight;
protected int mPreviewDegree;
// 监听系统音量广播
protected BroadcastReceiver mVolumeReceiver;
// 是否弹窗
protected boolean mHasShownTimeoutDialog;
private int headHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setScreenBright();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_face_detect_v3100);
DisplayMetrics dm = new DisplayMetrics();
Display display = this.getWindowManager().getDefaultDisplay();
display.getMetrics(dm);
mDisplayWidth = dm.widthPixels;
mDisplayHeight = dm.heightPixels;
//dp转px
headHeight = (int) (60 * dm.density + 0.5f);
FaceSDKResSettings.initializeResId();
mFaceConfig = FaceSDKManager.getInstance().getFaceConfig();
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int vol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
mIsEnableSound = vol > 0 ? mFaceConfig.isSound() : false;
mRootView = this.findViewById(R.id.detect_root_layout);
mFrameLayout = (FrameLayout) mRootView.findViewById(R.id.detect_surface_layout);
mSurfaceView = new SurfaceView(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setSizeFromLayout();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
int w = mDisplayWidth;
int h = mDisplayHeight;
// surfaceView使用屏幕分辨率的大小
FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(mDisplayWidth, mDisplayHeight,
Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
// FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(640, 480,
// Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
// cameraFL = new FrameLayout.LayoutParams(
// (int) (w * FaceDetectRoundView.SURFACE_RATIO * FaceDetectRoundView.RECT_RATIO),
// (int) (w * FaceDetectRoundView.SURFACE_RATIO * FaceDetectRoundView.RECT_RATIO * 640.0f / 480.0f),
// Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
mSurfaceView.setLayoutParams(cameraFL);
mFrameLayout.addView(mSurfaceView);
mRootView.findViewById(R.id.detect_close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mFaceDetectRoundViewNew = (FaceDetectRoundViewNew) mRootView.findViewById(R.id.detect_face_round);
mFaceDetectRoundViewNew.init(mDisplayWidth, mDisplayHeight-headHeight );
mRootView.findViewById(R.id.detect_close).setOnClickListener( v->{
finish();
});
if (mBase64ImageMap != null) {
mBase64ImageMap.clear();
}
}
/**
* 设置屏幕亮度
*/
private void setScreenBright() {
int currentBright = BrightnessUtils.getScreenBrightness(this);
BrightnessUtils.setBrightness(this, currentBright + 100);
}
@Override
public void onResume() {
super.onResume();
if (!mHasShownTimeoutDialog) {
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mVolumeReceiver = VolumeUtils.registerVolumeReceiver(this, this);
// if (mFaceDetectRoundView != null) {
// mFaceDetectRoundView.setTipTopText("请将脸移入取景框");
// }
startPreview();
}
}
@Override
public void onPause() {
if (mIDetectStrategy != null) {
mIDetectStrategy.reset();
}
super.onPause();
VolumeUtils.unRegisterVolumeReceiver(this, mVolumeReceiver);
mVolumeReceiver = null;
mIsCompletion = false;
stopPreview();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void finish() {
super.finish();
}
@Override
public void volumeChanged() {
}
private Camera open() {
Camera camera;
int numCameras = Camera.getNumberOfCameras();
if (numCameras == 0) {
return null;
}
int index = 0;
while (index < numCameras) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(index, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
break;
}
index++;
}
if (index < numCameras) {
camera = Camera.open(index);
mCameraId = index;
} else {
camera = Camera.open(0);
mCameraId = 0;
}
return camera;
}
protected void startPreview() {
if (mSurfaceView != null && mSurfaceView.getHolder() != null) {
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
if (mCamera != null) {
CameraUtils.releaseCamera(mCamera);
mCamera = null;
}
if (mCamera == null) {
try {
mCamera = open();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
if (mCamera == null) {
return;
}
if (mCameraParam == null) {
mCameraParam = mCamera.getParameters();
}
mCameraParam.setPictureFormat(PixelFormat.JPEG);
// 获取前置摄像头预览角度,为90度
int degree = displayOrientation(this);
mCamera.setDisplayOrientation(degree);
// 设置后无效,camera.setDisplayOrientation方法有效
//mCameraParam.set("rotation", degree);
//mCamera.setDisplayOrientation( degree );
mPreviewDegree = degree;
if (mIDetectStrategy != null) {
mIDetectStrategy.setPreviewDegree(degree);
}
// 以屏幕分辨率为基准选取分辨率
// Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
// new Point(mDisplayWidth, mDisplayHeight));
// 以640 * 480为基准选取分辨率
Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
new Point(640, 480 ));
mPreviewWidth = point.x;
mPreviewHight = point.y;
// Preview 768,432
mPreviewRect.set(0, 0,mPreviewHight, mPreviewWidth);
mCameraParam.setPreviewSize(mPreviewWidth, mPreviewHight);
mCamera.setParameters(mCameraParam);
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.stopPreview();
mCamera.setErrorCallback(this);
mCamera.setPreviewCallback(this);
mCamera.startPreview();
} catch (RuntimeException e) {
e.printStackTrace();
CameraUtils.releaseCamera(mCamera);
mCamera = null;
} catch (Exception e) {
e.printStackTrace();
CameraUtils.releaseCamera(mCamera);
mCamera = null;
}
}
protected void stopPreview() {
if (mCamera != null) {
try {
mCamera.setErrorCallback(null);
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
CameraUtils.releaseCamera(mCamera);
mCamera = null;
}
}
if (mSurfaceHolder != null) {
mSurfaceHolder.removeCallback(this);
}
if (mIDetectStrategy != null) {
mIDetectStrategy.reset();
mIDetectStrategy = null;
}
}
/**
* 获取摄像头预览角度
* @param context 当前上下文
* @return
*/
private int displayOrientation(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (windowManager == null) {
return 90;
}
int rotation = windowManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
default:
degrees = 0;
break;
}
int result = (0 - degrees + 360) % 360;
if (APIUtils.hasGingerbread()) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(mCameraId, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
}
return result;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsCreateSurface = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder,
int format,
int width,
int height) {
mSurfaceWidth = width;
mSurfaceHeight = height;
if (holder.getSurface() == null) {
return;
}
startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsCreateSurface = false;
}
ImageView iv_frame;
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (mIsCompletion) {
return;
}
if (mIDetectStrategy == null ){
mIDetectStrategy = FaceSDKManager.getInstance().getDetectStrategyModule();
mIDetectStrategy.setPreviewDegree(90); //前置横屏
mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
// Rect detectRect = mFaceDetectRoundViewNew.getPreviewDetectRect();
mPreviewRect.set(0, 0,480,640);
Rect detectRect = new Rect( 0, 0, 480, 640 );
mIDetectStrategy.setDetectStrategyConfig(mPreviewRect, detectRect, this);
}
if (mIDetectStrategy != null) {
/// Log.e("ssss","=========解析中");
if( iv_frame == null ){
iv_frame = (ImageView) findViewById(R.id.iv_frame);
}
//Bitmap bitmap = getPriviewPicBitmap(data);
//iv_frame.setImageBitmap( bitmap );
// //获取app 应用路径
String path = getApplicationContext().getFilesDir().getAbsolutePath();
//写入本地文件
try {
FileOutputStream fos = new FileOutputStream(path+"/10.jpg");
fos.write(getPriviewPic(data));
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//旋转
// byte[] newdata = rotateImage(bitmap);
// try {
// FileOutputStream fos = new FileOutputStream(path+"/10——2.jpg");
// fos.write(newdata);
// fos.close();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
//mIDetectStrategy.detectStrategy( jpegToNV21( newdata,480,640 ) );
byte[] output = new byte[data.length];
rotateNV21( data,output,640,480, 90 );
Bitmap bitmap = getPriviewPicBitmap(output);
iv_frame.setImageBitmap( bitmap );
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); // 可根据需要调整压缩格式和质量
byte[] rotatedImageBytes = stream.toByteArray();
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileOutputStream fos = new FileOutputStream(path+"/10——5.jpg");
fos.write(rotatedImageBytes);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mIDetectStrategy.detectStrategy( output );
}
}
public byte[] getPriviewPic(byte[] data) {//这里传入的data参数就是onpreviewFrame中需要传入的byte[]型数据
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高
byte[] rawImage = baos.toByteArray();
return rawImage;
}
// 将字节数组表示的图片旋转90度
public byte[] rotateImage(Bitmap bitmap ) {
// 将字节数组转换为Bitmap
// Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
// 旋转Bitmap
Matrix matrix = new Matrix();
matrix.postRotate(270); // 旋转90度
// matrix.setScale(-1, 1); // 水平镜像
// matrix.postTranslate(bitmap.getWidth(), 0); // 平移
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
// 将旋转后的Bitmap转换为字节数组
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); // 可根据需要调整压缩格式和质量
byte[] rotatedImageBytes = stream.toByteArray();
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return rotatedImageBytes;
}
public Bitmap getPriviewPicBitmap(byte[] data) {//这里传入的data参数就是onpreviewFrame中需要传入的byte[]型数据
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高
byte[] rawImage = baos.toByteArray();
//将rawImage转换成bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
return bitmap;
}
public byte[] jpegToNV21(byte[] jpegData, int width, int height) {
// 将JPEG数据解码为Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
// 将Bitmap转换为NV21格式的字节数组
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
byte[] jpegByteArray = outputStream.toByteArray();
YuvImage yuvImage = new YuvImage(jpegByteArray, ImageFormat.NV21, width, height, null);
// 将YuvImage转换为NV21格式的字节数组
ByteArrayOutputStream nv21Stream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, nv21Stream);
return nv21Stream.toByteArray();
}
public void rotateNV21(byte[] input, byte[] output, int width, int height, int rotation) {
boolean swap = (rotation == 90 || rotation == 270);
boolean yflip = (rotation == 90 || rotation == 180);
boolean xflip = (rotation == 270 || rotation == 180);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int xo = x, yo = y;
int w = width, h = height;
int xi = xo, yi = yo;
if (swap) {
xi = w * yo / h;
yi = h * xo / w;
}
if (yflip) {
yi = h - yi - 1;
}
if (xflip) {
xi = w - xi - 1;
}
output[w * yo + xo] = input[w * yi + xi];
int fs = w * h;
int qs = (fs >> 2);
xi = (xi >> 1);
yi = (yi >> 1);
xo = (xo >> 1);
yo = (yo >> 1);
w = (w >> 1);
h = (h >> 1);
// adjust for interleave here
int ui = fs + (w * yi + xi) * 2;
int uo = fs + (w * yo + xo) * 2;
// and here
int vi = ui + 1;
int vo = uo + 1;
output[uo] = input[ui];
output[vo] = input[vi];
}
}
}
@Override
public void onError(int error, Camera camera) {
}
@Override
public void onDetectCompletion(FaceStatusNewEnum status, String message,
HashMap<String, ImageInfo> base64ImageCropMap,
HashMap<String, ImageInfo> base64ImageSrcMap) {
if (mIsCompletion) {
return;
}
onRefreshView(status, message);
if (status == FaceStatusNewEnum.OK) {
Log.e("ssss","=========解析成功");
mIsCompletion = true;
// saveAllImage(base64ImageCropMap, base64ImageSrcMap);
}
}
private void onRefreshView(FaceStatusNewEnum status, String message) {
Log.e("ssss","=========message:"+message);
switch (status) {
case OK:
mFaceDetectRoundViewNew.setTipTopText(message);
// onRefreshSuccessView(true);
// onRefreshTipsView(false, message);
break;
case DetectRemindCodePitchOutofUpRange:
case DetectRemindCodePitchOutofDownRange:
case DetectRemindCodeYawOutofLeftRange:
case DetectRemindCodeYawOutofRightRange:
mFaceDetectRoundViewNew.setTipTopText(message);
// onRefreshTipsView(true, message);
// onRefreshSuccessView(false);
break;
default:
mFaceDetectRoundViewNew.setTipTopText(message);
// onRefreshTipsView(false, message);
// onRefreshSuccessView(false);
}
}
private static Bitmap base64ToBitmap(String base64Data) {
byte[] bytes = Base64Utils.decode(base64Data, Base64Utils.NO_WRAP);
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
// ----------------------------------------供调试用----------------------------------------------
private void saveAllImage(HashMap<String, ImageInfo> imageCropMap, HashMap<String, ImageInfo> imageSrcMap) {
if (imageCropMap != null && imageCropMap.size() > 0) {
List<Map.Entry<String, ImageInfo>> list1 = new ArrayList<>(imageCropMap.entrySet());
Collections.sort(list1, new Comparator<Map.Entry<String, ImageInfo>>() {
@Override
public int compare(Map.Entry<String, ImageInfo> o1,
Map.Entry<String, ImageInfo> o2) {
String[] key1 = o1.getKey().split("_");
String score1 = key1[2];
String[] key2 = o2.getKey().split("_");
String score2 = key2[2];
// 降序排序
return Float.valueOf(score2).compareTo(Float.valueOf(score1));
}
});
setImageView1(list1);
}
if (imageSrcMap != null && imageSrcMap.size() > 0) {
List<Map.Entry<String, ImageInfo>> list2 = new ArrayList<>(imageSrcMap.entrySet());
Collections.sort(list2, new Comparator<Map.Entry<String, ImageInfo>>() {
@Override
public int compare(Map.Entry<String, ImageInfo> o1,
Map.Entry<String, ImageInfo> o2) {
String[] key1 = o1.getKey().split("_");
String score1 = key1[2];
String[] key2 = o2.getKey().split("_");
String score2 = key2[2];
// 降序排序
return Float.valueOf(score2).compareTo(Float.valueOf(score1));
}
});
setImageView2(list2);
}
}
private void setImageView1(List<Map.Entry<String, ImageInfo>> list) {
Bitmap bmp = null;
for (Map.Entry<String, ImageInfo> entry : list) {
bmp = base64ToBitmap(entry.getValue().getBase64());
ImageView iv = new ImageView(this);
iv.setImageBitmap(bmp);
}
}
private void setImageView2(List<Map.Entry<String, ImageInfo>> list) {
Bitmap bmp = null;
for (Map.Entry<String, ImageInfo> entry : list) {
bmp = base64ToBitmap(entry.getValue().getBase64());
ImageView iv = new ImageView(this);
iv.setImageBitmap(bmp);
}
}
}
横屏的实现源码:
package com.baidu.idl.face.example;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.baidu.idl.face.example.widget.TimeoutDialog;
import com.baidu.idl.face.platform.FaceConfig;
import com.baidu.idl.face.platform.FaceSDKManager;
import com.baidu.idl.face.platform.FaceStatusNewEnum;
import com.baidu.idl.face.platform.IDetectStrategy;
import com.baidu.idl.face.platform.IDetectStrategyCallback;
import com.baidu.idl.face.platform.model.ImageInfo;
import com.baidu.idl.face.platform.ui.FaceDetectActivity;
import com.baidu.idl.face.platform.ui.FaceSDKResSettings;
import com.baidu.idl.face.platform.ui.utils.BrightnessUtils;
import com.baidu.idl.face.platform.ui.utils.CameraPreviewUtils;
import com.baidu.idl.face.platform.ui.utils.CameraUtils;
import com.baidu.idl.face.platform.ui.utils.IntentUtils;
import com.baidu.idl.face.platform.ui.utils.VolumeUtils;
import com.baidu.idl.face.platform.ui.widget.FaceDetectRoundViewNew;
import com.baidu.idl.face.platform.utils.APIUtils;
import com.baidu.idl.face.platform.utils.Base64Utils;
import com.healthplatform.health_platform.R;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//百度人脸识别横屏版本
public class BaiduFaceDetectExpActivity extends Activity implements
SurfaceHolder.Callback,
Camera.PreviewCallback,
Camera.ErrorCallback,
VolumeUtils.VolumeCallback,
IDetectStrategyCallback
{
// View
protected View mRootView;
protected FrameLayout mFrameLayout;
protected SurfaceView mSurfaceView;
protected SurfaceHolder mSurfaceHolder;
protected FaceDetectRoundViewNew mFaceDetectRoundViewNew;
// 人脸信息
protected FaceConfig mFaceConfig;
protected IDetectStrategy mIDetectStrategy;
// 显示Size
private Rect mPreviewRect = new Rect();
protected int mDisplayWidth = 0;
protected int mDisplayHeight = 0;
protected int mSurfaceWidth = 0;
protected int mSurfaceHeight = 0;
// 状态标识 语音
protected volatile boolean mIsEnableSound = true;
protected HashMap<String, String> mBase64ImageMap = new HashMap<String, String>();
protected boolean mIsCreateSurface = false;
protected volatile boolean mIsCompletion = false;
// 相机
protected Camera mCamera;
protected Camera.Parameters mCameraParam;
protected int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT ;///默认前置
protected int mPreviewWidth;
protected int mPreviewHight;
protected int mPreviewDegree;
// 监听系统音量广播
protected BroadcastReceiver mVolumeReceiver;
// 是否弹窗
protected boolean mHasShownTimeoutDialog;
private int headHeight;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setScreenBright();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_baidu_face_detectexp);
DisplayMetrics dm = new DisplayMetrics();
Display display = this.getWindowManager().getDefaultDisplay();
display.getMetrics(dm);
mDisplayWidth = dm.widthPixels;
mDisplayHeight = dm.heightPixels;
//dp转px
headHeight = (int) (60 * dm.density + 0.5f);
FaceSDKResSettings.initializeResId();
mFaceConfig = FaceSDKManager.getInstance().getFaceConfig();
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int vol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
mIsEnableSound = vol > 0 ? mFaceConfig.isSound() : false;
mRootView = this.findViewById(R.id.detect_root_layout);
mFrameLayout = (FrameLayout) mRootView.findViewById(R.id.detect_surface_layout);
mSurfaceView = new SurfaceView(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setSizeFromLayout();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// surfaceView使用屏幕分辨率的大小
FrameLayout.LayoutParams cameraFL = new FrameLayout.LayoutParams(mDisplayWidth, mDisplayHeight,
Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
mSurfaceView.setLayoutParams(cameraFL);
mFrameLayout.addView(mSurfaceView);
mRootView.findViewById(R.id.detect_close).setOnClickListener(v -> onBackPressed());
mFaceDetectRoundViewNew = (FaceDetectRoundViewNew) mRootView.findViewById(R.id.detect_face_round);
mFaceDetectRoundViewNew.init(mDisplayWidth, mDisplayHeight - headHeight);
mRootView.findViewById(R.id.detect_close).setOnClickListener(v -> {
finish();
});
ImageView iv_flip = (ImageView)findViewById(R.id.iv_flip);
iv_flip.setOnClickListener(v->{
if (mCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
iv_flip.setImageResource(R.drawable.camera_rear);
} else {
mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
iv_flip.setImageResource(R.drawable.camera_front);
}
stopPreview();
startPreview();
});
if (mBase64ImageMap != null) {
mBase64ImageMap.clear();
}
}
/**
* 设置屏幕亮度
*/
private void setScreenBright() {
int currentBright = BrightnessUtils.getScreenBrightness(this);
BrightnessUtils.setBrightness(this, currentBright + 100);
}
@Override
public void onResume() {
super.onResume();
if (!mHasShownTimeoutDialog) {
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mVolumeReceiver = VolumeUtils.registerVolumeReceiver(this, this);
if (mFaceDetectRoundViewNew != null) {
mFaceDetectRoundViewNew.setTipTopText("请将脸移入取景框");
}
startPreview();
}
}
@Override
public void onPause() {
if (mIDetectStrategy != null) {
mIDetectStrategy.reset();
}
super.onPause();
VolumeUtils.unRegisterVolumeReceiver(this, mVolumeReceiver);
mVolumeReceiver = null;
mIsCompletion = false;
stopPreview();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void finish() {
super.finish();
}
//音频声音改变监听
@Override
public void volumeChanged() {
}
///打开摄像头
private Camera open() {
Camera camera;
int numCameras = Camera.getNumberOfCameras();
if (numCameras == 0) {
return null;
}
camera = Camera.open(mCameraId);
return camera;
}
///开始预览
protected void startPreview() {
if (mSurfaceView != null && mSurfaceView.getHolder() != null) {
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
if (mCamera != null) {
CameraUtils.releaseCamera(mCamera);
mCamera = null;
}
if (mCamera == null) {
try {
mCamera = open();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
if (mCamera == null) {
return;
}
if (mCameraParam == null) {
mCameraParam = mCamera.getParameters();
}
mCameraParam.setPictureFormat(PixelFormat.JPEG);
// 获取前置摄像头预览角度,为90度
int degree = displayOrientation(this);
mCamera.setDisplayOrientation(degree);
// 设置后无效,camera.setDisplayOrientation方法有效
//mCameraParam.set("rotation", degree);
//mCamera.setDisplayOrientation( degree );
mPreviewDegree = degree;
if (mIDetectStrategy != null) {
mIDetectStrategy.setPreviewDegree(degree);
}
// 以屏幕分辨率为基准选取分辨率
// Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
// new Point(mDisplayWidth, mDisplayHeight));
// 以640 * 480为基准选取分辨率
Point point = CameraPreviewUtils.getBestPreview(mCameraParam,
new Point(640, 480));
mPreviewWidth = point.x;
mPreviewHight = point.y;
// Preview 768,432
mPreviewRect.set(0, 0, mPreviewHight, mPreviewWidth);
mCameraParam.setPreviewSize(mPreviewWidth, mPreviewHight);
mCamera.setParameters(mCameraParam);
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.stopPreview();
mCamera.setErrorCallback(this);
mCamera.setPreviewCallback(this);
mCamera.startPreview();
} catch (RuntimeException e) {
e.printStackTrace();
CameraUtils.releaseCamera(mCamera);
mCamera = null;
} catch (Exception e) {
e.printStackTrace();
CameraUtils.releaseCamera(mCamera);
mCamera = null;
}
}
protected void stopPreview() {
if (mCamera != null) {
try {
mCamera.setErrorCallback(null);
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
CameraUtils.releaseCamera(mCamera);
mCamera = null;
mCameraParam = null;
}
}
if (mSurfaceHolder != null) {
mSurfaceHolder.removeCallback(this);
}
if (mIDetectStrategy != null) {
mIDetectStrategy.reset();
mIDetectStrategy = null;
}
}
/**
* 获取摄像头预览角度
*
* @param context 当前上下文
* @return
*/
private int displayOrientation(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (windowManager == null) {
return 90;
}
int rotation = windowManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
default:
degrees = 0;
break;
}
int result = (0 - degrees + 360) % 360;
if (APIUtils.hasGingerbread()) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(mCameraId, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
}
return result;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsCreateSurface = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder,
int format,
int width,
int height) {
mSurfaceWidth = width;
mSurfaceHeight = height;
if (holder.getSurface() == null) {
return;
}
startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsCreateSurface = false;
}
ImageView iv_frame;
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (mIsCompletion) {
return;
}
if (mIDetectStrategy == null) {
mIDetectStrategy = FaceSDKManager.getInstance().getDetectStrategyModule();
mIDetectStrategy.setPreviewDegree(90); //前置横屏
mIDetectStrategy.setDetectStrategySoundEnable(mIsEnableSound);
mIDetectStrategy.setDetectStrategyConfig(mPreviewRect, mPreviewRect, this);
}
if (mIDetectStrategy != null) {
/// Log.e("ssss","=========解析中");
if (iv_frame == null) {
iv_frame = (ImageView) findViewById(R.id.iv_frame);
}
String path = getApplicationContext().getFilesDir().getAbsolutePath();
//写入本地文件
try {
FileOutputStream fos = new FileOutputStream(path + "/90.jpg");
fos.write(getPriviewPic(data));
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] output = new byte[data.length];
rotateNV21(data, output, 640, 480, 90);
Bitmap bitmap = getPriviewPicBitmap(output);
iv_frame.setImageBitmap(bitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); // 可根据需要调整压缩格式和质量
byte[] rotatedImageBytes = stream.toByteArray();
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileOutputStream fos = new FileOutputStream(path + "/90——5.jpg");
fos.write(rotatedImageBytes);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mIDetectStrategy.detectStrategy(output);
}
}
//
public byte[] getPriviewPic(byte[] data) {//这里传入的data参数就是onpreviewFrame中需要传入的byte[]型数据
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高
byte[] rawImage = baos.toByteArray();
return rawImage;
}
// 将字节数组表示的图片旋转90度
public Bitmap getPriviewPicBitmap(byte[] data) {//这里传入的data参数就是onpreviewFrame中需要传入的byte[]型数据
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG图片的质量[0-100],100最高
byte[] rawImage = baos.toByteArray();
//将rawImage转换成bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
return bitmap;
}
public void rotateNV21(byte[] input, byte[] output, int width, int height, int rotation) {
boolean swap = (rotation == 90 || rotation == 270);
boolean yflip = (rotation == 90 || rotation == 180);
boolean xflip = (rotation == 270 || rotation == 180);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int xo = x, yo = y;
int w = width, h = height;
int xi = xo, yi = yo;
if (swap) {
xi = w * yo / h;
yi = h * xo / w;
}
if (yflip) {
yi = h - yi - 1;
}
if (xflip) {
xi = w - xi - 1;
}
output[w * yo + xo] = input[w * yi + xi];
int fs = w * h;
int qs = (fs >> 2);
xi = (xi >> 1);
yi = (yi >> 1);
xo = (xo >> 1);
yo = (yo >> 1);
w = (w >> 1);
h = (h >> 1);
// adjust for interleave here
int ui = fs + (w * yi + xi) * 2;
int uo = fs + (w * yo + xo) * 2;
// and here
int vi = ui + 1;
int vo = uo + 1;
output[uo] = input[ui];
output[vo] = input[vi];
}
}
}
@Override
public void onError(int error, Camera camera) {
}
@Override
public void onDetectCompletion(FaceStatusNewEnum status, String message,
HashMap<String, ImageInfo> base64ImageCropMap,
HashMap<String, ImageInfo> base64ImageSrcMap) {
if (mIsCompletion) {
return;
}
onRefreshView(status, message);
if (status == FaceStatusNewEnum.OK) {
Log.e("ssss", "=========解析成功");
mIsCompletion = true;
// saveAllImage(base64ImageCropMap, base64ImageSrcMap);
getBestImage(base64ImageCropMap, base64ImageSrcMap);
}else if (status == FaceStatusNewEnum.DetectRemindCodeTimeout){
///识别超时
}
}
private void onRefreshView(FaceStatusNewEnum status, String message) {
Log.e("ssss", "=========message:" + message);
switch (status) {
case OK:
mFaceDetectRoundViewNew.setTipTopText(message);
// onRefreshSuccessView(true);
// onRefreshTipsView(false, message);
break;
case DetectRemindCodePitchOutofUpRange:
case DetectRemindCodePitchOutofDownRange:
case DetectRemindCodeYawOutofLeftRange:
case DetectRemindCodeYawOutofRightRange:
mFaceDetectRoundViewNew.setTipTopText(message);
// onRefreshTipsView(true, message);
// onRefreshSuccessView(false);
break;
default:
mFaceDetectRoundViewNew.setTipTopText(message);
// onRefreshTipsView(false, message);
// onRefreshSuccessView(false);
}
}
private static Bitmap base64ToBitmap(String base64Data) {
byte[] bytes = Base64Utils.decode(base64Data, Base64Utils.NO_WRAP);
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
/**
* 获取最优图片
* @param imageCropMap 抠图集合
* @param imageSrcMap 原图集合
*/
private void getBestImage(HashMap<String, ImageInfo> imageCropMap, HashMap<String, ImageInfo> imageSrcMap) {
// 将抠图集合中的图片按照质量降序排序,最终选取质量最优的一张抠图图片
String cropImageBase64 = ""; ///剪切后的图
String originalImageBase64 = ""; ///原图
if (imageCropMap != null && imageCropMap.size() > 0) {
List<Map.Entry<String, ImageInfo>> list1 = new ArrayList<>(imageCropMap.entrySet());
Collections.sort(list1, (o1, o2) -> {
String[] key1 = o1.getKey().split("_");
String score1 = key1[2];
String[] key2 = o2.getKey().split("_");
String score2 = key2[2];
// 降序排序
return Float.valueOf(score2).compareTo(Float.valueOf(score1));
});
// 获取抠图中的加密或非加密的base64
int secType = mFaceConfig.getSecType();
if (secType == 0) {
cropImageBase64 = list1.get(0).getValue().getBase64();
} else {
cropImageBase64 = list1.get(0).getValue().getSecBase64();
}
}
// 将原图集合中的图片按照质量降序排序,最终选取质量最优的一张原图图片
if (imageSrcMap != null && imageSrcMap.size() > 0) {
List<Map.Entry<String, ImageInfo>> list2 = new ArrayList<>(imageSrcMap.entrySet());
Collections.sort(list2, new Comparator<Map.Entry<String, ImageInfo>>() {
@Override
public int compare(Map.Entry<String, ImageInfo> o1,
Map.Entry<String, ImageInfo> o2) {
String[] key1 = o1.getKey().split("_");
String score1 = key1[2];
String[] key2 = o2.getKey().split("_");
String score2 = key2[2];
// 降序排序
return Float.valueOf(score2).compareTo(Float.valueOf(score1));
}
});
originalImageBase64 = list2.get(0).getValue().getBase64();
// 获取原图中的加密或非加密的base64
int secType = mFaceConfig.getSecType();
if (secType != 0){//加密
originalImageBase64 = list2.get(0).getValue().getSecBase64();
}
}
// 页面跳转
IntentUtils.getInstance().setBitmap(cropImageBase64);
Intent intent = new Intent(BaiduFaceDetectExpActivity.this,
CollectionSuccessActivity.class);
intent.putExtra("destroyType", "FaceDetectExpActivity");
startActivity(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
mFaceDetectRoundViewNew.release();
}
}
这里只是测试代码 主要删减 再使用。
