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
//收集
//判断监听器 开始
if(onFaceCollectListener!=null){
onFaceCollectListener.OnFaceCollectStart(true);
//有byte数组转为bitmap
bitmaps[number] = byte2bitmap(bytes,camera);
Log.d("ceshiTian","********收集了"+number+"个************");
number = number+1;
if(number==5){
Log.d("ceshiTian","********收集够5个************");
//提交
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(); // 获取预览大小
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();
}
/**
* 开启预览
*
* @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;
}
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。