溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

在Android 開發(fā)中使用camera怎么實(shí)現(xiàn)一個(gè)人臉識(shí)別功能

發(fā)布時(shí)間:2020-11-20 15:31:35 來源:億速云 閱讀:207 作者:Leah 欄目:移動(dòng)開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)在Android 開發(fā)中使用camera怎么實(shí)現(xiàn)一個(gè)人臉識(shí)別功能,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

Android camera實(shí)時(shí)預(yù)覽 實(shí)時(shí)處理,面部認(rèn)證。

預(yù)覽操作是網(wǎng)友共享的代碼,我在繼承SurfaceView 的CameraSurfaceView 中加入了幀監(jiān)聽事件,每次預(yù)覽監(jiān)聽前五個(gè)數(shù)據(jù)幀,在處理做一個(gè)面部識(shí)別。

先看目錄關(guān)系

在Android 開發(fā)中使用camera怎么實(shí)現(xiàn)一個(gè)人臉識(shí)別功能

  • 自定義控件CameraSurfaceView.java
  • 自定義接口方法CameraInterface.java
  • CameraActivity預(yù)覽界面。

CameraSurfaceView.Java

package com.centaur.camera.preview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.centaur.camera.camera.CameraInterface;

import java.io.ByteArrayOutputStream;

/**
 * Created by Tianchaoxiong on 2017/1/16.
 */

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback{


  private static final int FACENUM = 5;

  private static final String TAG = "yanzi";
  CameraInterface mCameraInterface;
  Context mContext;
  SurfaceHolder mSurfaceHolder;

  private boolean isFinish;
  //傳輸五個(gè)bitmap數(shù)組
  Bitmap [] bitmaps = new Bitmap[5];

  int number = 0;//作為計(jì)數(shù)器用

  OnFaceCollectListener onFaceCollectListener = null;

  public CameraSurfaceView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mContext = context;
    mSurfaceHolder = getHolder();
    mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mSurfaceHolder.addCallback(this);
  }

  @Override
  public void surfaceCreated(SurfaceHolder surfaceHolder) {
    Log.i(TAG, "surfaceCreated...");
  }

  @Override
  public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
    Log.i(TAG, "surfaceChanged...");
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    Log.i(TAG, "surfaceDestroyed...");
    CameraInterface.getInstance().doStopCamera();
  }
  public SurfaceHolder getSurfaceHolder(){
    return mSurfaceHolder;
  }

  /**
   * 收集五張圖片 監(jiān)聽器
   */
  public static interface OnFaceCollectListener {

    /**
     * 收集五張face
     * @param bitmaps 返回的五張臉的數(shù)組
     */
    void OnFaceCollected(Bitmap[] bitmaps);

    /**
     * face重新繪制
     * @param isStart 是否重新收集
     */
    void OnFaceCollectStart(boolean isStart);
  }
  /**
   * 設(shè)置面部的監(jiān)聽器
   * @param onFaceCollectListener
   */
  public void setOnFaceCollectListener(OnFaceCollectListener onFaceCollectListener){

    if(onFaceCollectListener!=null){
      this.onFaceCollectListener = onFaceCollectListener;
    }
  }

  /***
   * 想在這里做一個(gè)監(jiān)聽處理 收五偵 傳輸出去
   * @param bytes
   * @param camera
   */
  @Override
  public void onPreviewFrame(byte[] bytes, Camera camera) {
    if(number<FACENUM){
      //收集
      //判斷監(jiān)聽器 開始
      if(onFaceCollectListener!=null){
        onFaceCollectListener.OnFaceCollectStart(true);
        //有byte數(shù)組轉(zhuǎn)為bitmap
        bitmaps[number] = byte2bitmap(bytes,camera);
        Log.d("ceshiTian","********收集了"+number+"個(gè)************");
        number = number+1;
        if(number==5){
          Log.d("ceshiTian","********收集夠5個(gè)************");
          //提交
          onFaceCollectListener.OnFaceCollected(bitmaps);
        }
      }
    }else {
      //不做操作
      onFaceCollectListener.OnFaceCollectStart(false);
      onFaceCollectListener.OnFaceCollected(null);
    }
  }

  private Bitmap byte2bitmap(byte[] bytes, Camera camera) {
    Bitmap bitmap = null;

    Camera.Size size = camera.getParameters().getPreviewSize(); // 獲取預(yù)覽大小
    final int w = size.width; // 寬度
    final int h = size.height;
    final YuvImage image = new YuvImage(bytes, ImageFormat.NV21, w, h,
        null);
    ByteArrayOutputStream os = new ByteArrayOutputStream(bytes.length);
    if (!image.compressToJpeg(new Rect(0, 0, w, h), 100, os)) {
      return null;
    }
    byte[] tmp = os.toByteArray();
    bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);

    Matrix matrix = new Matrix();
    matrix.setRotate(-90);
    bitmap = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);

    return bitmap;
  }
}

CameraInterface.java

package com.centaur.camera.camera;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;

import com.centaur.camera.util.CamParaUtil;
import com.centaur.camera.util.ImageUtil;
import com.centaur.util.FileUtils;

import java.io.IOException;
import java.util.List;

/**
 * Created by Tianchaoxiong on 2017/1/16.
 */

public class CameraInterface {
  private static final String TAG = "Tianchaoxiong";
  private Camera mCamera;
  private Camera.Parameters mParams;
  private boolean isPreviewing = false;
  private float mPreviwRate = -1f;
  private static CameraInterface mCameraInterface;

  public interface CamOpenOverCallback {
    public void cameraHasOpened();
  }

  private CameraInterface() {

  }

  public static synchronized CameraInterface getInstance() {
    if (mCameraInterface == null) {
      mCameraInterface = new CameraInterface();
    }
    return mCameraInterface;
  }

  /**
   * 打開Camera
   *
   * @param callback
   */
  public void doOpenCamera(CamOpenOverCallback callback) {
    Log.i(TAG, "Camera open....");
    mCamera = Camera.open(1);
    Log.i(TAG, "Camera open over....");
    callback.cameraHasOpened();
  }

  /**
   * 開啟預(yù)覽
   *
   * @param holder
   * @param previewRate
   */
  public void doStartPreview(SurfaceHolder holder, float previewRate, Camera.PreviewCallback previewCallback) {
    Log.i(TAG, "doStartPreview...");
    if (isPreviewing) {
      mCamera.stopPreview();
      return;
    }
    if (mCamera != null) {

      mParams = mCamera.getParameters();
      mParams.setPictureFormat(PixelFormat.JPEG);//設(shè)置拍照后存儲(chǔ)的圖片格式

      //對(duì)支持的圖片的大小的一個(gè)收集
      CamParaUtil.getInstance().printSupportPictureSize(mParams);
      CamParaUtil.getInstance().printSupportPreviewSize(mParams);
      //設(shè)置PreviewSize和PictureSize
      Camera.Size pictureSize = CamParaUtil.getInstance().getPropPictureSize(
          mParams.getSupportedPictureSizes(), previewRate, 800);
      mParams.setPictureSize(pictureSize.width, pictureSize.height);
      Camera.Size previewSize = CamParaUtil.getInstance().getPropPreviewSize(
          mParams.getSupportedPreviewSizes(), previewRate, 800);
      mParams.setPreviewSize(previewSize.width, previewSize.height);

      mCamera.setDisplayOrientation(90);

      CamParaUtil.getInstance().printSupportFocusMode(mParams);
      List<String> focusModes = mParams.getSupportedFocusModes();
      if (focusModes.contains("continuous-video")) {
        mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
      }
      mCamera.setParameters(mParams);  //參數(shù)設(shè)置完畢

      try {
        mCamera.setPreviewDisplay(holder);
        mCamera.setPreviewCallback(previewCallback);
        mCamera.startPreview();//開啟預(yù)覽
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      isPreviewing = true;
      mPreviwRate = previewRate;

      mParams = mCamera.getParameters(); //重新get一次
      Log.i(TAG, "最終設(shè)置:PreviewSize--With = " + mParams.getPreviewSize().width
          + "Height = " + mParams.getPreviewSize().height);
      Log.i(TAG, "最終設(shè)置:PictureSize--With = " + mParams.getPictureSize().width
          + "Height = " + mParams.getPictureSize().height);
    }
  }

  /**
   * 停止預(yù)覽,釋放Camera
   */
  public void doStopCamera() {
    if (null != mCamera) {
      mCamera.setPreviewCallback(null);
      mCamera.stopPreview();
      isPreviewing = false;
      mPreviwRate = -1f;
      mCamera.release();
      mCamera = null;
    }
  }

  /**
   * 拍照
   */
  public void doTakePicture() {
    if (isPreviewing && (mCamera != null)) {
      Log.d("FileUtils", "程序運(yùn)行到這里了111");
      mCamera.takePicture(mShutterCallback, null, mJpegPictureCallback);
    }
  }

  /*為了實(shí)現(xiàn)拍照的快門聲音及拍照保存照片需要下面三個(gè)回調(diào)變量*/
  Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback()
      //快門按下的回調(diào),在這里我們可以設(shè)置類似播放“咔嚓”聲之類的操作。默認(rèn)的就是咔嚓。
  {
    public void onShutter() {
      // TODO Auto-generated method stub
      Log.i(TAG, "myShutterCallback:onShutter...");
    }
  };
  /*  Camera.PictureCallback mRawCallback = new Camera.PictureCallback()
        // 拍攝的未壓縮原數(shù)據(jù)的回調(diào),可以為null
    {

      public void onPictureTaken(byte[] data, Camera camera) {
        // TODO Auto-generated method stub
        Log.i(TAG, "myRawCallback:onPictureTaken...");

      }
    };*/
  Camera.PictureCallback mJpegPictureCallback = new Camera.PictureCallback()
      //對(duì)jpeg圖像數(shù)據(jù)的回調(diào),最重要的一個(gè)回調(diào)
  {
    public void onPictureTaken(byte[] data, Camera camera) {
      Log.d("FileUtils", "程序運(yùn)行到這里了222");
      // TODO Auto-generated method stub
      Log.i(TAG, "myJpegCallback:onPictureTaken...");
      Bitmap b = null;
      if (null != data) {
        b = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字節(jié)數(shù)據(jù),將其解析成位圖
        mCamera.stopPreview();
        isPreviewing = false;
        Log.d("FileUtils", "程序運(yùn)行到這里了333");
      }
      //保存圖片到sdcard
      if (null != b) {
        Log.d("FileUtils", "程序運(yùn)行到這里了444");
        //設(shè)置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。
        //圖片竟然不能旋轉(zhuǎn)了,故這里要旋轉(zhuǎn)下
        Log.d("FileUtils", "程序運(yùn)行到這里了");
        Bitmap rotaBitmap = ImageUtil.getRotateBitmap(b, -90.0f);
        FileUtils.savePaiZhaoBitmap(rotaBitmap);
      }
    }
  };

}

CameraActivity

package com.centaur.camera.Activity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;

import com.centaur.camera.camera.CameraInterface;
import com.centaur.camera.preview.CameraSurfaceView;
import com.centaur.camera.util.DisplayUtil;
import com.centaur.testutil.R;
import com.centaur.testutil.ShowPic;
import com.centaur.util.DetecteSDK;
import com.centaur.util.DetecteSeeta;



public class CameraActivity extends AppCompatActivity implements CameraSurfaceView.OnFaceCollectListener, CameraInterface.CamOpenOverCallback{
  private static final String TAG = "CameraActivity";

  private float recLen = 0;
  long te;
  float previewRate = -1f;
  DetecteSDK detecteSDK;
  DetecteSeeta detecteSeeta;

  Bitmap bmp;
  Bitmap bitmapfianl;

  private ImageButton shutterBtn;
  private TextView textView;
  private CameraSurfaceView surfaceView = null;


  @Override
  protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    Thread openThread = new Thread(){
      @Override
      public void run() {
        CameraInterface.getInstance().doOpenCamera(CameraActivity.this);
      }
    };
    openThread.start();
    te = System.currentTimeMillis();
    setContentView(R.layout.activity_camera);
    initView();
    initViewParams();
    surfaceView.setOnFaceCollectListener(this);

    shutterBtn.setOnClickListener(new BtnListeners());
    TimeHandler.postDelayed(TimeRunnable, 500);
  }
  /**
   * 回調(diào)方法
   * activity中的視圖和 interface中的代碼實(shí)現(xiàn)綁定
   */
  @Override
  public void cameraHasOpened() {
    SurfaceHolder holder = surfaceView.getSurfaceHolder();
    CameraInterface.getInstance().doStartPreview(holder, previewRate,surfaceView );
  }

  @Override
  protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    CameraInterface.getInstance().doStopCamera();
    Log.d("RunTime", "onDestroy:time:"+te);
    TimeHandler.removeCallbacks(TimeRunnable);
  }
  @Override
  protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    CameraInterface.getInstance().doStopCamera();
    te = System.currentTimeMillis()-te;
    Log.d("RunTime", "onPause:time:"+te);
    TimeHandler.removeCallbacks(TimeRunnable);
  }

  Handler TimeHandler = new Handler();
  Runnable TimeRunnable = new Runnable() {
    @Override
    public void run() {
      recLen+=500;
      textView.setText("檢測(cè)時(shí)間:" + recLen/1000+"秒");
      TimeHandler.postDelayed(this, 500);
    }
  };


  private void initView(){
    surfaceView = (CameraSurfaceView)findViewById(R.id.camera_surfaceview);
    shutterBtn = (ImageButton)findViewById(R.id.btn_shutter);
    textView = (TextView) findViewById(R.id.time);
  }
  private void initViewParams(){
    ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
    Point p = DisplayUtil.getScreenMetrics(this);
    params.width = p.x;
    params.height = p.y;
    previewRate = DisplayUtil.getScreenRate(this); //默認(rèn)全屏的比例預(yù)覽
    surfaceView.setLayoutParams(params);
    //手動(dòng)設(shè)置拍照ImageButton的大小為120dip×120dip,原圖片大小是64×64
    ViewGroup.LayoutParams p2 = shutterBtn.getLayoutParams();
    p2.width = DisplayUtil.dip2px(this, 80);
    p2.height = DisplayUtil.dip2px(this, 80);
    shutterBtn.setLayoutParams(p2);

  }




  /**
   * 自建
   * @param bitmaps 返回的五張臉的數(shù)組
   */
  @Override
  public void OnFaceCollected(Bitmap[] bitmaps) {

  }

  /**
   * 自建
   * @param isStart 是否重新收集
   */
  @Override
  public void OnFaceCollectStart(boolean isStart) {
    if(isStart){
      Log.d("CameraActivity","開始收集");
    }

  }

  private class BtnListeners implements View.OnClickListener {

    @Override
    public void onClick(View v) {
      // TODO Auto-generated method stub
      switch(v.getId()){
        case R.id.btn_shutter:
          CameraInterface.getInstance().doTakePicture();
          Intent intent =new Intent(CameraActivity.this, ShowPic.class);
          // 默認(rèn)一個(gè)暫存的路徑 /FaceDetection/useso/Pictures/Tmp/tmp.png
          String FolderPath = "/FaceDetection/useso/Pictures/Tmp/tmp.png";
          String path = Environment.getExternalStorageDirectory()+FolderPath;
          intent.putExtra("picpath",path);
          startActivity(intent);
          finish();
          break;
        default:break;
      }
    }

  }
}

關(guān)于在Android 開發(fā)中使用camera怎么實(shí)現(xiàn)一個(gè)人臉識(shí)別功能就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI