Newer
Older
SafetyAuxiliary_AR / sdk / java / src / org / opencv / android / NativeCameraView.java
pengxianhong on 12 Jun 2024 5 KB 集成OpenCV
package org.opencv.android;

import org.opencv.core.Mat;
import org.opencv.core.Size;

import org.opencv.imgproc.Imgproc;

import org.opencv.videoio.Videoio;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;

/**
 * This class is an implementation of a bridge between SurfaceView and OpenCV VideoCapture.
 * The class  is experimental implementation and not recoomended for production usage.
 */
public class NativeCameraView extends CameraBridgeViewBase {

    public static final String TAG = "NativeCameraView";
    private boolean mStopThread;
    private Thread mThread;

    protected VideoCapture mCamera;
    protected NativeCameraFrame mFrame;

    public NativeCameraView(Context context, int cameraId) {
        super(context, cameraId);
    }

    public NativeCameraView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected boolean connectCamera(int width, int height) {

        /* 1. We need to instantiate camera
         * 2. We need to start thread which will be getting frames
         */
        /* First step - initialize camera connection */
        if (!initializeCamera(width, height))
            return false;

        /* now we can start update thread */
        mThread = new Thread(new CameraWorker());
        mThread.start();

        return true;
    }

    @Override
    protected void disconnectCamera() {
        /* 1. We need to stop thread which updating the frames
         * 2. Stop camera and release it
         */
        if (mThread != null) {
            try {
                mStopThread = true;
                mThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                mThread =  null;
                mStopThread = false;
            }
        }

        /* Now release camera */
        releaseCamera();
    }

    public static class OpenCvSizeAccessor implements ListItemAccessor {

        public int getWidth(Object obj) {
            Size size  = (Size)obj;
            return (int)size.width;
        }

        public int getHeight(Object obj) {
            Size size  = (Size)obj;
            return (int)size.height;
        }

    }

    private boolean initializeCamera(int width, int height) {
        synchronized (this) {

            if (mCameraIndex == -1) {
                Log.d(TAG, "Try to open default camera");
                mCamera = new VideoCapture(0, Videoio.CAP_ANDROID);
            } else {
                Log.d(TAG, "Try to open camera with index " + mCameraIndex);
                mCamera = new VideoCapture(mCameraIndex, Videoio.CAP_ANDROID);
            }

            if (mCamera == null)
                return false;

            if (mCamera.isOpened() == false)
                return false;

            mFrame = new NativeCameraFrame(mCamera);

            mCamera.set(Videoio.CAP_PROP_FRAME_WIDTH, width);
            mCamera.set(Videoio.CAP_PROP_FRAME_HEIGHT, height);

            mFrameWidth = (int)mCamera.get(Videoio.CAP_PROP_FRAME_WIDTH);
            mFrameHeight = (int)mCamera.get(Videoio.CAP_PROP_FRAME_HEIGHT);

            if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
                mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
            else
                mScale = 0;

            if (mFpsMeter != null) {
                mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
            }

            AllocateCache();
        }

        Log.i(TAG, "Selected camera frame size = (" + mFrameWidth + ", " + mFrameHeight + ")");

        return true;
    }

    private void releaseCamera() {
        synchronized (this) {
            if (mFrame != null) mFrame.release();
            if (mCamera != null) mCamera.release();
        }
    }

    private static class NativeCameraFrame implements CvCameraViewFrame {

        @Override
        public Mat rgba() {
            mCapture.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('R','G','B','3'));
            mCapture.retrieve(mBgr);
            Log.d(TAG, "Retrived frame with size " + mBgr.cols() + "x" + mBgr.rows() + " and channels: " + mBgr.channels());
            Imgproc.cvtColor(mBgr, mRgba, Imgproc.COLOR_RGB2RGBA);
            return mRgba;
        }

        @Override
        public Mat gray() {
            mCapture.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('G','R','E','Y'));
            mCapture.retrieve(mGray);
            Log.d(TAG, "Retrived frame with size " + mGray.cols() + "x" + mGray.rows() + " and channels: " + mGray.channels());
            return mGray;
        }

        public NativeCameraFrame(VideoCapture capture) {
            mCapture = capture;
            mGray = new Mat();
            mRgba = new Mat();
            mBgr = new Mat();
        }

        public void release() {
            if (mGray != null) mGray.release();
            if (mRgba != null) mRgba.release();
            if (mBgr != null) mBgr.release();
        }

        private VideoCapture mCapture;
        private Mat mRgba;
        private Mat mGray;
        private Mat mBgr;
    };

    private class CameraWorker implements Runnable {

        public void run() {
            do {
                if (!mCamera.grab()) {
                    Log.e(TAG, "Camera frame grab failed");
                    break;
                }

                deliverAndDrawFrame(mFrame);
            } while (!mStopThread);
        }
    }

}