編輯:關於Android編程
Android camera實時預覽 實時處理,面部認證。
預覽操作是網友共享的代碼,我在繼承SurfaceView 的CameraSurfaceView 中加入了幀監聽事件,每次預覽監聽前五個數據幀,在處理做一個面部識別。
先看目錄關系
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; } } } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
三種得到LinearInflater的方法a. LayoutInflater inflater = getLayoutInflater();b. LayoutInflat
一、前言前一段時間在做視頻開發,由於本人剛接觸視頻開發這塊,所以領導沒有對我提很高的要求,僅僅要求能夠播放本地視頻即可。我想怎麼簡單怎麼做。於是選擇用Android Vi
一、問題概述 在android開發中,經常會使用到文件下載的功能,比如app版本更新等。在api level 9之後,android系統為我們提供了DownLoa
突然想要在android上寫一個消消樂的代碼,在此之前沒有系統地學過java的面向對象,也沒有任何android相關知識,不過還是會一點C++。8月初開始搭建環境,在這上