android 人脸识别边框_Android实现简单的人脸识别
時間:2019-09-03
概述:人臉識別
Android實現簡單的人臉識別,人臉檢測(這里用的是科大訊飛的人臉識別),因此需要此庫導入后,測試本代碼:
private final static String TAG = MainActivity.class.getSimpleName();
private SurfaceView mPreviewSurface;//用于顯示預覽圖像
private SurfaceView mFaceSurface;//用于繪制檢測人臉的返回信息
private SurfaceHolder mSurfaceHolder;//紋理控制器
private ImageButton changeCamera;//切換攝像頭按鈕
private Camera mCamera;//攝像頭對象
private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;//設置為默認開啟前置攝像頭
// 默認設置640*480,截至目前也只是支持640*480
private int PREVIEW_WIDTH = 640;
private int PREVIEW_HEIGHT = 480;
// 預覽幀數據存儲數組和緩存數組
private byte[] nv21;
private byte[] buffer;
// 縮放矩陣
private Matrix mScaleMatrix = new Matrix();
// 加速度感應器,用于獲取手機的朝向
private Accelerometer accelerometer;
private FaceDetector mFaceDetector;//調用訊飛的SDK來實現人臉識別
private boolean stop;//人臉檢測開關
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SpeechUtility.createUtility(this, "appid=" + "5833f456"); //設置AppKey用于注冊,AppID
initView();//初始化布局
initData();//初始化數據
requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1000);
}
@Override
public void permissionSuccess(int requestCode) {
super.permissionSuccess(requestCode);
if (requestCode == 1000){
Toast.makeText(MainActivity.this,"獲取文件寫入權限成功!",Toast.LENGTH_SHORT).show();
}
if (requestCode == 2000){
openCamera();//打開攝像頭
}
}
/**
* 用于顯示攝像頭拍攝到的圖像
*/
private SurfaceHolder.Callback mPreviewCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
closeCamera();//關閉攝像頭,并釋放資源
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
requestPermission(new String[]{Manifest.permission.CAMERA},2000);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mScaleMatrix.setScale(width / (float) PREVIEW_HEIGHT,
height / (float) PREVIEW_WIDTH);//設置縮放比例
}
};
/**
* 設置紋理尺寸
*/
private void setSurfaceSize() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = (int) (width * PREVIEW_WIDTH / (float) PREVIEW_HEIGHT);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
mPreviewSurface.setLayoutParams(params);
}
/**
* 初始化數據
*/
private void initData(){
nv21 = new byte[PREVIEW_WIDTH * PREVIEW_HEIGHT * 2];
buffer = new byte[PREVIEW_WIDTH * PREVIEW_HEIGHT * 2];
accelerometer = new Accelerometer(this);
mFaceDetector = FaceDetector.createDetector(this, null);//實例化人臉檢測對象
}
/**
* 初始化控件
*/
private void initView() {
mPreviewSurface = (SurfaceView) findViewById(R.id.preview);
mFaceSurface = (SurfaceView) findViewById(R.id.face);
changeCamera = (ImageButton) findViewById(R.id.change);
mPreviewSurface.getHolder().addCallback(mPreviewCallback);
mSurfaceHolder = mFaceSurface.getHolder();
mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);
mFaceSurface.setZOrderOnTop(true);
// 點擊SurfaceView,切換攝相頭
changeCamera.setOnClickListener(v -> {
// 只有一個攝相頭,不支持切換
if (Camera.getNumberOfCameras() == 1) {
Toast.makeText(this, "只有后置攝像頭,不能切換", Toast.LENGTH_SHORT).show();
return;
}
closeCamera();
if (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId) {
mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
} else {
mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
openCamera();
});
setSurfaceSize();
}
/**
* 打開攝像頭
*/
private void openCamera() {
if (mCamera != null) {
return;
}
try {
mCamera = Camera.open(mCameraId);
if (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId) {
Toast.makeText(this, "前置攝像頭已開啟,點擊可切換", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"后置攝像頭已開啟,點擊可切換",Toast.LENGTH_SHORT).show();
}
setCameraDisplayOrientation(this, mCameraId, mCamera);//設置攝像頭的預覽方向
} catch (Exception e) {
e.printStackTrace();
closeCamera();
return;
}
//獲取攝像頭參數對象
Camera.Parameters params = mCamera.getParameters();
//設置預覽的格式
params.setPreviewFormat(ImageFormat.NV21);
//設置預覽的分辨率,這里設置640*480,到目前為止只支持該分辨率的人臉檢測
params.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
//給攝像頭設置參數配置
mCamera.setParameters(params);
//給攝像頭設置預覽回到,這里使用的Lambda表達式代表的只有一個回調函數的匿名內部類
mCamera.setPreviewCallback((data, camera) -> System.arraycopy(data, 0, nv21, 0, data.length));
try {
mCamera.setPreviewDisplay(mPreviewSurface.getHolder());
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 釋放攝像頭資源
*/
private void closeCamera() {
if (null != mCamera) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
protected void onResume() {
super.onResume();
if (null != accelerometer) {
accelerometer.start();
}
stop = false;
new Thread(()->{
while (!stop) {
if (null == nv21) {
continue;
}
synchronized (nv21) {
System.arraycopy(nv21, 0, buffer, 0, nv21.length);
}
int direction = Accelerometer.getDirection();// 獲取手機朝向
boolean frontCamera = (Camera.CameraInfo.CAMERA_FACING_FRONT == mCameraId);
if (frontCamera) {
direction = (4 - direction) % 4;// 0,1,2,3,4分別表示0,90,180,270和360度
}
String result = mFaceDetector.trackNV21(
buffer, PREVIEW_WIDTH, PREVIEW_HEIGHT, 1, direction);//獲取人臉檢測結果
FaceRect face = Result.result(result);//獲取返回的數據
Log.e(TAG, "result:" + result);//輸出檢測結果,該結果為JSON數據
Canvas canvas =mSurfaceHolder.lockCanvas();//鎖定畫布用于繪制
if (null == canvas) {
continue;
}
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//清除之前的繪制圖像
canvas.setMatrix(mScaleMatrix);
if (face == null) {
mSurfaceHolder.unlockCanvasAndPost(canvas);
continue;
}
if (face != null) {
face.bound = DrawFaceRect.RotateDeg90(face.bound, PREVIEW_HEIGHT);//繪制人臉的區域
if (face.point != null) {//繪制臉上關鍵點
for (int i = 0; i < face.point.length; i++) {
face.point[i] = DrawFaceRect.RotateDeg90(face.point[i], PREVIEW_HEIGHT);
}
//繪制人臉檢測的區域
DrawFaceRect.drawFaceRect(canvas, face, PREVIEW_WIDTH, frontCamera);
}
} else {
Log.e(TAG, "沒有檢測出人臉");
}
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}).start();
}
解析人臉返回結果:
FaceRect rect = null;
if (TextUtils.isEmpty(json)) {
return null;
}
try {
JSONObject joResult = new JSONObject(json);
JSONArray items = joResult.getJSONArray("face");//解析face數組
JSONObject position = items.getJSONObject(0).getJSONObject("position");
//獲取人臉檢測框數據
rect = new FaceRect();
rect.bound.left = position.getInt("left");//左邊起始位置點
rect.bound.top = position.getInt("top");//上端起始位置點
rect.bound.right = position.getInt("right");//右邊結束位置點
rect.bound.bottom = position.getInt("bottom");//下端結束位置點
// 提取關鍵點數據
JSONObject landmark = items.getJSONObject(0).getJSONObject("landmark");
int keyPoint = landmark.length();//人臉檢測點數據
rect.point = new Point[keyPoint];//人臉檢測點數組
Iterator it = landmark.keys();//使用迭代器解析人臉監測點數據
int point = 0;
while (it.hasNext()) {//檢測點,的坐標
String key = (String) it.next();
JSONObject object = landmark.getJSONObject(key);
rect.point[point] = new Point(object.getInt("x"), object.getInt("y"));
point++;
}
} catch (JSONException e) {
e.printStackTrace();
}
return rect;
總結
以上是生活随笔為你收集整理的android 人脸识别边框_Android实现简单的人脸识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ-3061 尺取
- 下一篇: android sina oauth2.