• Android CameraManager 类


    先看代码:

        private SurfaceView mSurfaceView;
        private SurfaceHolder mSurfaceHolder;
        private CameraManager cameraManager;
    
            cameraManager = new CameraManager(this);
            mSurfaceView = (SurfaceView) findViewById(R.id.java_surface_view);
            mSurfaceHolder = mSurfaceView.getHolder();
    
            // mSurfaceView 不需要自己的缓冲区
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            // mSurfaceView添加回调
            mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
                    try {
                        cameraManager.openDriver(mSurfaceHolder);
                        cameraManager.startPreview();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    
                }
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
                    holder.removeCallback(this); // Camera is being used after Camera.release() was called
                    cameraManager.stopPreview();
                    cameraManager.closeDriver();
    
                }
            });

    自定义一个 CameraManager 类,在关闭当前页面,释放camera资源时偶尔报错 

    Camera is being used after Camera.release() was called

    第一次,加了一句 holder.removeCallback(this); 运行发现还是时不时出现报错。

    第二次在释放 camera前加  camera.setPreviewCallback(null); 问题解决。

        /**
         * 关闭预览
         */
        public synchronized void stopPreview() {
            Log.e(TAG, "stopPreview");
            if (autoFocusManager != null) {
                autoFocusManager.stop();
                autoFocusManager = null;
            }
            if (camera != null && previewing) {
                camera.stopPreview();
                camera.setPreviewCallback(null);  // Camera is being used after Camera.release() was called
                previewing = false;
            }
        }
    
    
    
        /**
         * 关闭camera
         */
        public synchronized void closeDriver() {
            Log.e(TAG, "closeDriver");
            if (camera != null) {
                camera.release();
                camera = null;
            }
        }

    原来:如果程序中加入了previewCallback,在surfaceDestroy释放camera的时候,最好执行myCamera.setOneShotPreviewCallback(null); 或者myCamera.setPreviewCallback(null);中止这种回调,然后再释放camera更安全。否则可能会报错。 

    附:CameraManager类:

    package com.myproject.facedetection.entity;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.ImageFormat;
    import android.graphics.Matrix;
    import android.hardware.Camera;
    import android.util.Log;
    import android.view.Display;
    import android.view.Surface;
    import android.view.SurfaceHolder;
    import android.view.WindowManager;
    
    
    import com.opencvlib.ObjectDetector;
    
    import org.opencv.android.Utils;
    import org.opencv.core.CvType;
    import org.opencv.core.Mat;
    import org.opencv.core.MatOfRect;
    import org.opencv.core.Rect;
    import org.opencv.imgproc.Imgproc;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import static com.myproject.facedetection.common.myUtils.ByteToBitmap;
    
    /**
     * User:lizhangqu(513163535@qq.com)
     * Date:2015-09-05
     * Time: 10:56
     */
    public class CameraManager implements Camera.PreviewCallback {
        private static final String TAG = CameraManager.class.getName();
        private Camera camera;
        private Camera.Parameters parameters;
        private AutoFocusManager autoFocusManager;
        private int requestedCameraId = -1; // 默认打开后置摄像头
        private int cameraPosition;//0代表前置摄像头,1代表后置摄像头
        private int numCameras = Camera.getNumberOfCameras(); // 初始化摄像头数量
        private Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        private Context mContext;
    
        private boolean initialized;
        private boolean previewing;
        private ArrayList<ObjectDetector> mObjectDetects;
        private CustomImageButton cimbt;
        private SurfaceHolder holder;
    
        /**
         * 打开摄像头
         *
         * @param cameraId 摄像头id
         * @return Camera
         */
        public Camera open(int cameraId) {
            if (numCameras <= 0) {
                Log.e(TAG, "No cameras!");
                return null;
            }
    
            // 如果 cameraId 在 [0-numCameras) 之间则打开cameraId 否则默认优先打开后置
            boolean explicitRequest = (cameraId >= 0 && cameraId < numCameras);
    
            int index = 0;
            if (!explicitRequest) {
                // Select a camera if no explicit camera requested
                while (index < numCameras) {
                    Camera.getCameraInfo(index, cameraInfo);
                    cameraId = index;
                    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                        cameraPosition = 1;
                        break;
                    }
                    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                        cameraPosition = 0;
                        continue;
                    }
    
                    index++;
                }
            }
    
            // 不在 [0-numCameras) 之间 且 没有默认打开的
            Camera camera;
            if (index < numCameras) {
                Log.e(TAG, "Opening camera #" + cameraId);
                camera = Camera.open(cameraId);
            } else {
                Log.e(TAG, "Requested camera does not exist: " + cameraId);
                camera = null;
            }
    
    
            int rotation = getDisplayOrientation();
            camera.setDisplayOrientation(rotation);
            camera.setPreviewCallback(this);
            //camera.setOneShotPreviewCallback(this); // 激活 onPreviewFrame 执行一次
            return camera;
        }
    
        public int getDisplayOrientation() {
            Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            int rotation = display.getRotation();
            int degrees = 0;
            switch (rotation) {
                case Surface.ROTATION_0:
                    degrees = 0;
                    break;
                case Surface.ROTATION_90:
                    degrees = 90;
                    break;
                case Surface.ROTATION_180:
                    degrees = 180;
                    break;
                case Surface.ROTATION_270:
                    degrees = 270;
                    break;
            }
            Camera.CameraInfo camInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo);
            int result = (camInfo.orientation - degrees + 360) % 360;
            return result;
        }
    
        public CameraManager(Context context, ArrayList<ObjectDetector> mObjectDetects, CustomImageButton cimbt, SurfaceHolder holder) {
            this.mContext = context;
            this.mObjectDetects = mObjectDetects;
            this.cimbt = cimbt;
            this.holder = holder;
        }
    
    
        /**
         * 打开camera
         *
         * @throws IOException IOException
         */
        public synchronized void openDriver()
                throws IOException {
            Log.e(TAG, "openDriver");
            Camera theCamera = camera;
            if (theCamera == null) {
                theCamera = open(requestedCameraId);
                if (theCamera == null) {
                    throw new IOException();
                }
                camera = theCamera;
            }
            theCamera.setPreviewDisplay(holder);
    
            if (!initialized) {
                initialized = true;
                parameters = camera.getParameters();
                List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
    
                int w = 800;
                int h = 600;
                for (Camera.Size size : previewSizes) {
                    Log.e("TAG", "previewSizes " + size.width);
                    Log.e("TAG", "previewSizes height:" + size.height);
                    if (size.width - w <= 200 & size.width >= w) {
                        w = size.width;
                        h = size.height;
                        break;
                    }
                }
                Log.e("w*h", String.format("%d*%d", w, h));
                parameters.setPreviewSize(w, h);
                parameters.setPictureFormat(ImageFormat.JPEG);
                parameters.setJpegQuality(100);
                parameters.setPictureSize(800, 600);
                theCamera.setParameters(parameters);
            }
        }
    
    
        /*
            切换摄像头
         */
        public synchronized void changeCamera() throws IOException {
            for (int i = 0; i < numCameras; i++) {
                Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
                //现在是后置,变更为前置
                if (cameraPosition == 1) {
                    //代表摄像头的方位  CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
                    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                        stopPreview();
                        closeDriver();
    
                        requestedCameraId = i;
                        initialized = false;
    
                        openDriver();
                        startPreview();
                        cameraPosition = 0;
                        break;
                    }
                } else {
                    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                        stopPreview();
                        closeDriver();
    
                        requestedCameraId = i;
                        initialized = false;
    
                        openDriver();
                        startPreview();
                        cameraPosition = 1;
                        break;
                    }
                }
    
            }
        }
    
        @Override
        public void onPreviewFrame(byte[] bytes, Camera camera) {
            Camera.Size previewSize = camera.getParameters().getPreviewSize();
    
            Bitmap bitmap = ByteToBitmap(bytes, previewSize);
            //Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);//将data byte型数组转换成bitmap文件
    
            final Matrix matrix = new Matrix();//转换成矩阵旋转90度
            if (cameraPosition == 1) {
                matrix.setRotate(90);
            } else {
                matrix.setRotate(-90);
            }
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);//旋转图片
    
    
            Mat grayscaleImage = new Mat(previewSize.height, previewSize.width, CvType.CV_8UC4);
            int absoluteFaceSize = (int) (previewSize.height * 0.2);
    
            if (bitmap != null) {
                Mat inputFrame = new Mat();
                Utils.bitmapToMat(bitmap, inputFrame);
    
                if (!bitmap.isRecycled()) {
                    bitmap.recycle();
                }
    
                // Create a grayscale image
                Imgproc.cvtColor(inputFrame, grayscaleImage, Imgproc.COLOR_RGBA2RGB);
    
                MatOfRect mRect = new MatOfRect();
    
    
                int maxRectArea = 0 * 0;
                Rect maxRect = null;
    
                int facenum = 0;
    
                for (ObjectDetector detector : mObjectDetects) {
                    // 检测目标
                    Rect[] object = detector.detectObjectImage(inputFrame, mRect);
                    Log.e(TAG, object.length + "");
    
                    for (Rect rect : object) {
                        ++facenum;
                        // 找出最大的面积
                        int tmp = rect.width * rect.height;
                        if (tmp >= maxRectArea) {
                            maxRectArea = tmp;
                            maxRect = rect;
                        }
                    }
                }
    
                Bitmap rectBitmap = null;
                if (facenum != 0) {
                    // 剪切最大的头像
                    //Log.e("剪切的长宽", String.format("高:%s,宽:%s", maxRect.width, maxRect.height));
                    Rect rect = new Rect(maxRect.x, maxRect.y, maxRect.width, maxRect.height);
                    Mat rectMat = new Mat(inputFrame, rect);  // 从原始图像拿
                    rectBitmap = Bitmap.createBitmap(rectMat.cols(), rectMat.rows(), Bitmap.Config.ARGB_8888);
                    Utils.matToBitmap(rectMat, rectBitmap);
    
                    Bitmap resizeBmp = cimbt.resizeBitmap(rectBitmap, cimbt.getWidth(), cimbt.getHeight());
                    cimbt.setBitmap(resizeBmp);
                } else {
                    cimbt.clearnImage();
                    cimbt.setText("没有检测到人脸");
                }
            }
    
        }
    
    
        public interface OnObjectTrackingInterface {
            // 传输camera的字节流
            void onCameraByteStream(byte[] bytes, Camera camera);
    
        }
    
        /**
         * camera是否打开
         *
         * @return camera是否打开
         */
    
        public synchronized boolean isOpen() {
            return camera != null;
        }
    
        /**
         * 关闭camera
         */
        public synchronized void closeDriver() {
            Log.e(TAG, "closeDriver");
            if (camera != null) {
                camera.release();
                camera = null;
            }
        }
    
        /**
         * 开始预览
         */
        public synchronized void startPreview() {
            Log.e(TAG, "startPreview");
            Camera theCamera = camera;
            if (theCamera != null && !previewing) {
                theCamera.startPreview();
                previewing = true;
                autoFocusManager = new AutoFocusManager(camera);
            }
        }
    
        /**
         * 关闭预览
         */
        public synchronized void stopPreview() {
            Log.e(TAG, "stopPreview");
            if (autoFocusManager != null) {
                autoFocusManager.stop();
                autoFocusManager = null;
            }
            if (camera != null && previewing) {
                camera.stopPreview();
                camera.setPreviewCallback(null);  // Camera is being used after Camera.release() was called
                previewing = false;
            }
        }
    
    
        /**
         * 打开闪光灯
         */
        public synchronized void openLight() {
            Log.e(TAG, "openLight");
            if (camera != null) {
                parameters = camera.getParameters();
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                camera.setParameters(parameters);
            }
        }
    
        /**
         * 关闭闪光灯
         */
        public synchronized void offLight() {
            Log.e(TAG, "offLight");
            if (camera != null) {
                parameters = camera.getParameters();
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                camera.setParameters(parameters);
            }
        }
    
        /**
         * 拍照
         *
         * @param shutter ShutterCallback
         * @param raw     PictureCallback
         * @param jpeg    PictureCallback
         */
        public synchronized void takePicture(final Camera.ShutterCallback shutter, final Camera.PictureCallback raw,
                                             final Camera.PictureCallback jpeg) {
            camera.takePicture(shutter, raw, jpeg);
        }
    
        private Bitmap reSize(byte[] data) {
            Log.i(TAG, "myJpegCallback:onPictureTaken...");
            Bitmap cutMap = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
            //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。图片竟然不能旋转了,故这里要旋转下
            Matrix matrix = new Matrix();
            matrix.postRotate((float) 90.0);
            Bitmap rotaBitmap = Bitmap.createBitmap(cutMap, 0, 0, cutMap.getWidth(), cutMap.getHeight(), matrix, false);
    
            //旋转后rotaBitmap是960×1280.预览surfaview的大小是540×800
            //将960×1280缩放到540×800
            Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
            Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
            return rectBitmap;
        }
    }
    CameraManager

     

  • 相关阅读:
    linux之卸载软件
    linux之挂载硬盘
    windows MySQL 5+ 服务手动安装
    深刻理解Python中的元类(metaclass)
    Python_cmd的各种实现方法及优劣(subprocess.Popen, os.system和commands.getstatusoutput)
    WSGI、flup、fastcgi、web.py的关系
    Windows下python环境变量配置
    External file changes sync may be slow: Project files cannot be watched (are they under network mount?)
    as。 对象和数组
    为什么for不能有序遍历数组的所有元素?(Array的设计原理)
  • 原文地址:https://www.cnblogs.com/haoxr/p/7680140.html
Copyright © 2020-2023  润新知