全网最简单实用Android摄像头开发,同时预览多个摄像头,双目摄像头,同时打开手机前后摄像头(红外摄像头、人脸识别、活体检测、Android Camera、缩放、焦距、旋转、镜像、截图保存)

如果你受够了网上那些乱七八糟的代码,你可以了解下我这个,能同时打开多个摄像头,在界面上预览,并且可以取得摄像头数据,byte[] 转为 Bitmap,保存为 jpg图片。

最近我们的某个项目要加上Android人脸识别,虽然有别人写好的“考勤”、“门口闸机”这些,但不能直接用于我们的项目,我们有自己的业务需求。

我们机器有3个摄像头,在进行人脸识别的时候,3个摄像头都要处于工作状态;分别是:一个主摄像头本来就一直处于拍照检测中的,另外的双目摄像头,一个用于人脸检测,另一个是红外摄像头于用进行活体检测。

当我开始调整的时候,才发现原来用的“androidx.camera”并不能同时打开多个摄像头,然后我去了解 camera2,发现使用比较复杂,我的想法是,简单实用就好,并不要非常强大的各种功能,后来我再去了解"camera1",即 “android.hardware.Camera”,这个虽然现在被弃用了,但是还能用,而且我感觉这个比较好理解,基于它我实现了需求。

下面是我摄像头的相关代码,有需求的朋友可参考:

package cn.example.test.facesdk.camera;import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.view.TextureView;import java.io.IOException;
import java.util.List;public class PreviewCamera {private Camera mCamera;private boolean mirror = false; // 镜像(左右翻转)private int rotate = -1; // 旋转(相机传感器方向相对于设备自然方向的角度)private int zoom = -1; // 焦距(有些摄像头可能不支持)public void setMirror(boolean mirror) {this.mirror = mirror;}public void setRotate(int rotate) {this.rotate = rotate;}public void setZoom(int zoom) {this.zoom = zoom;}public void startCamera(TextureView textureView, int cameraIndex, int width, int height, ICallback callback) {stopCamera();try {mCamera = Camera.open(cameraIndex);checkPreviewSize(width, height);// 设置参数(尺寸、对焦、焦距、旋转)Camera.Parameters params = mCamera.getParameters();//List list = params.getSupportedPreviewFormats();params.setPreviewSize(width, height);List focusModes = params.getSupportedFocusModes();if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);}if (this.zoom >= 0 && params.isZoomSupported() && this.zoom <= params.getMaxZoom()) {params.setZoom(this.zoom);mCamera.setParameters(params);}mCamera.setParameters(params);if (this.rotate >= 0) {mCamera.setDisplayOrientation(this.rotate);}// 预览初始化(左右翻转)initPreview(textureView);if (this.mirror) {textureView.setRotationY(180);}// 回调mCamera.setPreviewCallback(new Camera.PreviewCallback() {@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {if (callback != null) {callback.onData(data, camera);}}});if (callback != null) {callback.onSucc(mCamera);}} catch (Exception e) {e.printStackTrace();if (callback != null) {callback.onError(e);}}}public void stopCamera() {try {mCamera.setPreviewCallback(null);mCamera.stopPreview();mCamera.release();mCamera = null;} catch (Exception e) {}}private void checkPreviewSize(int width, int height) throws Exception {boolean sizeOk = false;List sizeList = mCamera.getParameters().getSupportedPreviewSizes();for (Camera.Size size : sizeList) {if (size.width == width && size.height == height) {sizeOk = true;}}if (!sizeOk) {throw new Exception(String.format("不支持该预览尺寸: [%d,%d]", width, height));}}private TextureView initPreview(TextureView textureView) {textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {try {if (mCamera != null) {mCamera.setPreviewTexture(surfaceTexture);mCamera.startPreview();}} catch (IOException e) {e.printStackTrace();}}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {stopCamera();return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}});return textureView;}public interface ICallback {void onSucc(Camera camera);void onData(byte[] data, Camera camera);void onError(Exception e);}
}

上面代码直接放到你项目即可,使用也非常简单明了,如下:

package cn.example.test.Activity;import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.TextureView;import cn.example.test.Activity.Base.BaseActivity;
import cn.example.test.R;
import cn.example.test.facesdk.camera.PreviewCamera;
import cn.example.test.facesdk.camera.PreviewCameraUtils;public class MainActivity extends BaseActivity {PreviewCamera previewCamera1 = new PreviewCamera();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overrideprotected void onResume() {super.onResume();start();}@Overrideprotected void onPause() {super.onPause();stop();}private void start() {TextureView textureView1 = findViewById(R.id.camera_preview);// 设置镜像(左右翻转)previewCamera1.setMirror(false);// 设置旋转角度//previewCamera1.setRotate(90);// 设置焦距//previewCamera1.setZoom(50);previewCamera1.startCamera(textureView1, 0, 640, 480, new PreviewCamera.ICallback() {@Overridepublic void onData(byte[] data, Camera camera) {dealData1(data, camera);}@Overridepublic void onSucc(Camera camera) {}@Overridepublic void onError(Exception e) {}});}private void stop() {previewCamera1.stopCamera();}long lastTime1 = 0;private void dealData1(byte[] data, Camera camera) {// 控制下频率long currTime = System.currentTimeMillis();if (currTime - lastTime1 < 5000) {return;}lastTime1 = currTime;// 转换为BitmpaBitmap bitmap = PreviewCameraUtils.cameraDataToBitmap(data, camera);// 旋转&翻转bitmap = PreviewCameraUtils.bitmapXform(bitmap, 270, false, true);// 保存为jpgString path = PreviewCameraUtils.getSDCardPath() + "/" + System.currentTimeMillis() + ".jpg";PreviewCameraUtils.saveBitmapToFile(bitmap, path);}
}

上面就是核心的代码,已经可以把摄像头使用起来了,下面放几个常用的帮助方法:

package cn.example.test.facesdk.camera;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Environment;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;public class PreviewCameraUtils {public static Bitmap cameraDataToBitmap(byte[] data, Camera camera) {Camera.Parameters parameters = camera.getParameters();int width = parameters.getPreviewSize().width;int height = parameters.getPreviewSize().height;int format = parameters.getPreviewFormat();Bitmap bitmap = yuvToBitmap(data, format, width, height);return bitmap;}/*** 摄像头数据转换为Bitmap** @param data* @param format* @param width* @param height* @return*/public static Bitmap yuvToBitmap(byte[] data, int format, int width, int height) {ByteArrayOutputStream out = new ByteArrayOutputStream();YuvImage yuvImage = new YuvImage(data, format, width, height, null);yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, out);byte[] imageBytes = out.toByteArray();return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);}/*** Bitmap进行旋转和翻转** @param bitmap* @param rotate        旋转的角度* @param leftRightTurn 是否左右翻转* @param upDownTurn    是否上下翻转* @return*/public static Bitmap bitmapXform(Bitmap bitmap, int rotate, boolean leftRightTurn, boolean upDownTurn) {int width = bitmap.getWidth();int height = bitmap.getHeight();Matrix matrix = new Matrix();if (leftRightTurn) {matrix.preScale(-1f, 1f);}if (upDownTurn) {matrix.preScale(1f, -1f);}if (rotate > 0) {matrix.postRotate(rotate);}Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);return rotatedBitmap;}/*** 把Bitmap保存为jpg文件** @param bitmap* @param filePath 绝对路径*/public static void saveBitmapToFile(Bitmap bitmap, String filePath) {File file = new File(filePath);try {// 创建文件输出流FileOutputStream outputStream = new FileOutputStream(file);// 将bitmap写入输出流中bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);// 刷新缓冲区outputStream.flush();// 关闭输出流outputStream.close();} catch (IOException e) {e.printStackTrace();}}/*** 取得SDCard根路径** @return*/public static String getSDCardPath() {return "" + Environment.getExternalStorageDirectory();}}

另外,记得声明权限,示例:

    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_PERMIS_CODE);} else {}

-------------------(完)-------------------


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部