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

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

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

2024-07-06 20:23| 来源: 网络整理| 查看: 265

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

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

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

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

如果你想要快速获得摄像头数据(甚至不用在界面显示预览),像下面这样即可:

android.hardware.Camera mCamera; android.graphics.SurfaceTexture mSurface; /** * 摄像头快速预览并取得数据 * 注意:mCamera和mSurface不要在本方法内定义 */ private void startCamera() { int cameraId = 0; try { // 打开相机 mCamera = Camera.open(cameraId); // 设置图像尺寸 Camera.Parameters params = mCamera.getParameters(); params.setPreviewSize(640, 480); mCamera.setParameters(params); // 设置预览视图 mSurface = new SurfaceTexture(0); mCamera.setPreviewTexture(mSurface); // 设置图像数据回调 mCamera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] data, Camera camera) { // 取得图像数据,每一帧图像都回调到这里,在这里做图像处理 // 该方法高频调用,用RXJava做流控,data转换为Bitmap或Mat等 } }); // 开启预览 mCamera.startPreview(); } catch (Exception ignored) { // 发生异常 } }

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

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 = 0) { mCamera.setDisplayOrientation(this.rotate); } // 预览初始化(左右翻转) initPreview(textureView); if (this.mirror) { textureView.setRotationY(180); } // 回调 mCamera.setPreviewCallback(new Camera.PreviewCallback() { @Override public 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() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) { try { if (mCamera != null) { mCamera.setPreviewTexture(surfaceTexture); mCamera.startPreview(); } } catch (IOException e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { stopCamera(); return false; } @Override public 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(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onResume() { super.onResume(); start(); } @Override protected 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() { @Override public void onData(byte[] data, Camera camera) { dealData1(data, camera); } @Override public void onSucc(Camera camera) { } @Override public 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; // 转换为Bitmpa Bitmap bitmap = PreviewCameraUtils.cameraDataToBitmap(data, camera); // 旋转&翻转 bitmap = PreviewCameraUtils.bitmapXform(bitmap, 270, false, true); // 保存为jpg String 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 { }

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3