热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Androidcamera实时预览实时处理,人脸识别示例

Android camera实时预览 实时处理,面部认证。 预览操作是网友共享的代码,我在继承SurfaceView 的CameraSur

Android camera实时预览 实时处理,面部认证。

预览操作是网友共享的代码,我在继承SurfaceView 的CameraSurfaceView 中加入了帧监听事件,每次预览监听前五个数据帧,在处理做一个面部识别。

先看目录关系

  • 自定义控件CameraSurfaceView.java
  • 自定义接口方法CameraInterface.java
  • CameraActivity预览界面。

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;
  //传输五个bitmap数组
  Bitmap [] bitmaps = new Bitmap[5];

  int number = 0;//作为计数器用

  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;
  }

  /**
   * 收集五张图片 监听器
   */
  public static interface OnFaceCollectListener {

    /**
     * 收集五张face
     * @param bitmaps 返回的五张脸的数组
     */
    void OnFaceCollected(Bitmap[] bitmaps);

    /**
     * face重新绘制
     * @param isStart 是否重新收集
     */
    void OnFaceCollectStart(boolean isStart);
  }
  /**
   * 设置面部的监听器
   * @param onFaceCollectListener
   */
  public void setOnFaceCollectListener(OnFaceCollectListener onFaceCollectListener){

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

  /***
   * 想在这里做一个监听处理 收五侦 传输出去
   * @param bytes
   * @param camera
   */
  @Override
  public void onPreviewFrame(byte[] bytes, Camera camera) {
    if(number

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();
  }

  /**
   * 开启预览
   *
   * @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);//设置拍照后存储的图片格式

      //对支持的图片的大小的一个收集
      CamParaUtil.getInstance().printSupportPictureSize(mParams);
      CamParaUtil.getInstance().printSupportPreviewSize(mParams);
      //设置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 focusModes = mParams.getSupportedFocusModes();
      if (focusModes.contains("continuous-video")) {
        mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
      }
      mCamera.setParameters(mParams);  //参数设置完毕

      try {
        mCamera.setPreviewDisplay(holder);
        mCamera.setPreviewCallback(previewCallback);
        mCamera.startPreview();//开启预览
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      isPreviewing = true;
      mPreviwRate = previewRate;

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

  /**
   * 停止预览,释放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", "程序运行到这里了111");
      mCamera.takePicture(mShutterCallback, null, mJpegPictureCallback);
    }
  }

  /*为了实现拍照的快门声音及拍照保存照片需要下面三个回调变量*/
  Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback()
      //快门按下的回调,在这里我们可以设置类似播放“咔嚓”声之类的操作。默认的就是咔嚓。
  {
    public void onShutter() {
      // TODO Auto-generated method stub
      Log.i(TAG, "myShutterCallback:onShutter...");
    }
  };
  /*  Camera.PictureCallback mRawCallback = new Camera.PictureCallback()
        // 拍摄的未压缩原数据的回调,可以为null
    {

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

      }
    };*/
  Camera.PictureCallback mJpegPictureCallback = new Camera.PictureCallback()
      //对jpeg图像数据的回调,最重要的一个回调
  {
    public void onPictureTaken(byte[] data, Camera camera) {
      Log.d("FileUtils", "程序运行到这里了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是字节数据,将其解析成位图
        mCamera.stopPreview();
        isPreviewing = false;
        Log.d("FileUtils", "程序运行到这里了333");
      }
      //保存图片到sdcard
      if (null != b) {
        Log.d("FileUtils", "程序运行到这里了444");
        //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。
        //图片竟然不能旋转了,故这里要旋转下
        Log.d("FileUtils", "程序运行到这里了");
        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);
  }
  /**
   * 回调方法
   * activity中的视图和 interface中的代码实现绑定
   */
  @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("检测时间:" + 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); //默认全屏的比例预览
    surfaceView.setLayoutParams(params);
    //手动设置拍照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 返回的五张脸的数组
   */
  @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);
          // 默认一个暂存的路径 /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;
      }
    }

  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 请看|间隔时间_Postgresql 主从复制 ... [详细]
  • iTOP4412开发板QtE5.7源码编译指南
    本文详细介绍了如何在iTOP4412开发板上编译QtE5.7源码,包括所需文件的位置、编译器设置、触摸库编译以及QtE5.7的完整编译流程。 ... [详细]
  • VMware Horizon View 5.0桌面虚拟化部署实践与心得
    在近期的研究中,我花费了大约两天时间成功部署了桌面虚拟化环境,并在此过程中积累了一些宝贵的经验。本文将分享这些经验和部署细节,希望能对同样关注桌面虚拟化的同行有所帮助。 ... [详细]
  • NFS(Network File System)即网络文件系统,是一种分布式文件系统协议,主要用于Unix和类Unix系统之间的文件共享。本文详细介绍NFS的配置文件/etc/exports和相关服务配置,帮助读者理解如何在Linux环境中配置NFS客户端。 ... [详细]
  • 本文详细介绍了 Kubernetes 集群管理工具 kubectl 的基本使用方法,涵盖了一系列常用的命令及其应用场景,旨在帮助初学者快速掌握 kubectl 的基本操作。 ... [详细]
  • 利用SSH隧道实现外网对局域网机器的安全访问
    本文探讨了一种常见的网络配置问题及其解决方案,即如何在外网环境下安全地访问位于局域网内的计算机。特别介绍了使用SSH反向隧道技术来实现这一目标的具体步骤和注意事项。 ... [详细]
  • 在Linux系统上构建Web服务器的详细步骤
    本文详细介绍了如何在Linux系统上搭建Web服务器的过程,包括安装Apache、PHP和MySQL等关键组件,以及遇到的一些常见问题及其解决方案。 ... [详细]
  • 使用LVS与ldirectord实现高可用负载均衡
    本文介绍了如何通过LVS(Linux Virtual Server)结合ldirectord工具来实现服务器的健康检查及负载均衡功能。环境设置包括一个LVS节点和两个真实服务器节点,通过配置ldirectord进行健康状态监测,确保系统的高可用性。 ... [详细]
  • 近期,考虑到在Vim内部进行GDB调试、运行Python脚本和数据库连接等多样化需求,思考是否可以通过集成终端来简化这些操作,而非逐一编写Vim脚本来实现。通过研究发现,确实存在一种高效的方法——利用特定插件实现终端功能的整合。 ... [详细]
  • Linux网络安装指南
    本文详细介绍了如何通过网络安装Linux操作系统,包括必要的服务配置和常见问题解决方法,旨在帮助IT专业人士提高系统部署效率。 ... [详细]
  • 本文档详细介绍了在 Kubernetes 集群中部署 ETCD 数据库的过程,包括实验环境的准备、ETCD 证书的生成及配置、以及集群的启动与健康检查等关键步骤。 ... [详细]
  • 本文详细介绍了如何在CentOS 7操作系统上搭建GitLab服务器的过程,包括环境准备、软件安装及基本配置等关键步骤。 ... [详细]
  • 本文基于《Linux命令行与Shell脚本编程大全》第三版的第十一章内容,探讨了如何构建基本的Shell脚本,包括命令组合、脚本创建、消息显示、变量使用、输入输出重定向、管道、数学运算及脚本退出等方面的知识。 ... [详细]
  • 通常,ping命令用于快速检测与远程服务器之间的网络延迟,以评估连接质量。然而,在某些情况下,即使服务器可以正常访问,ping请求也可能无法成功。本文将介绍在CentOS 7系统上禁用ping命令的方法,包括临时和永久性设置。 ... [详细]
  • 探讨 MySQL 8.0 版本中出现的连接错误 1130,分析其产生原因及提供详细的解决方案。 ... [详细]
author-avatar
zf19920222
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有