Android camera實時預覽 實時處理,面部認證。
Android camera實時預覽 實時處理,面部認證。
說的不清晰 程式碼在下面 是用android studio寫的。
程式碼地址(地址有問題 下午更新)
不好意思因為沒有事先說明 程式碼是再專案裡面的facelock那個module裡面。
https://share.weiyun.com/2e3f8b18e390e12b1836d6625e541172(這是微雲下載連線)
http://download.csdn.net/detail/u012222078/9749716
程式功能:預覽camera,並自動收集幾個資料幀儲存為bitmap陣列方便做面部識別的處理
預覽操作是網友共享的程式碼,我在繼承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<FACENUM){
//收集
//判斷監聽器 開始
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<String> 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;
}
}
}
}
相關文章
- Android camera2實現預覽Android
- angularjs 實現圖片上傳實時預覽AngularJS
- Android實時監控專案第三篇:通過攝像頭實時預覽幀視訊Android
- SpringMVC實現ajax上傳圖片實時預覽SpringMVC
- jq實現上傳頭像並實時預覽功能
- 如何利用Redis實現延時處理Redis
- SparkStreaming實時流處理學習Spark
- 實時處理 Kafka 資料來源Kafka
- Android平臺Camera實時濾鏡實現方法探討(一)--JNI操作BitmapAndroid
- (流式、lambda、觸發器)實時處理大比拼-物聯網(IoT)金融,時序處理最佳實踐觸發器
- 【Camera專題】Qcom-如何修改Camera預覽、拍照、視訊時支援的解析度
- Java如何使用實時流式計算處理?Java
- 日誌和實時流計算處理
- 實時資料處理:Kafka 和 FlinkKafka
- Kafka如何實現實時流處理 Part 1 - André MeloKafka
- 最好用的設計稿實時預覽工具【Sketch、Android App、iOS App】AndroidAPPiOS
- hyperf 實現延時佇列,處理超時未支付訂單佇列
- Flink基礎:實時處理管道與ETL
- 實時影片拍攝處理SDK解決方案
- 第32講:實時處理利器 mitmproxy 的使用MIT
- 《Storm實時資料處理》一1.1 簡介ORM
- 實時流處理框架Apache Flink簡介框架Apache
- HTML5:使用Canvas實時處理VideoHTMLCanvasIDE
- MSBuild + MSILInect實現編譯時AOP之預覽UI編譯
- Android使用Camera2獲取預覽資料Android
- flink使用Event_time處理實時資料
- 使用xsl實時處理xml文件(Javascript語言)XMLJavaScript
- 身份證真偽查詢介面、身份證實名認證一行python程式碼即可實現,實時資料Python
- 實時人工智慧:微軟釋出Project Brainwave預覽版人工智慧微軟ProjectAI
- Android音視訊(六) 使用OpenGL ES 3.0預覽CameraAndroid
- 網路實名制、電商實名認證、身份證實名認證介面
- AI 加持實時互動|ZegoAvatar 面部表情隨動技術解析AIGo
- 基於flink和drools的實時日誌處理
- 使用Storm、Kafka和ElasticSearch處理實時資料 -javacodegeeksORMKafkaElasticsearchJava
- 基於Spark的大資料實時處理開課Spark大資料
- 關於筆記軟體Obsidian實時預覽出現前段預覽,後段不預覽的解決方案筆記
- 蘋果釋出 Swift 程式語言,支援程式碼效果實時預覽蘋果Swift
- PHP 時間處理PHP