OpenCV for Android——摄像头打开与预览_Android


 


》权限

 	<uses-permission android:name="android.permission.CAMERA" /> <!-- 摄像头 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 内部存储 -->
    
<uses-feature android:name="android.hardware.camera" android:required="false"/>    
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>

》》 在MainActivity中继承CvCameraViewListener2接口

CvCameraViewListener2是使用OpenCV相机的核心监听

 public class MainActivity extends Activity implements CvCameraViewListener2 {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public void onCameraViewStarted(int width, int height) {
        // TODO Auto-generated method stub

    }
    @Override
    public void onCameraViewStopped() {
        // TODO Auto-generated method stub

    }
    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        // TODO Auto-generated method stub
        return null;
    }
}

onCameraViewStarted:相机启动时调用
onCameraViewStopped:相机销毁时调用
onCameraFrame: 相机工作时调用,参数是相机每一帧的图像,实时对比就在这个方法中进行

》》》 OnCreate中初始化相机,并添加开启相机的回调

     /**
     * CV相机
     */
    private CameraBridgeViewBase mCVCamera;
    /**
     * 加载OpenCV的回调
     */
    private BaseLoaderCallback mLoaderCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化CV相机
        mCVCamera = (CameraBridgeViewBase) findViewById(R.id.cv);
        mCVCamera.setVisibility(CameraBridgeViewBase.VISIBLE);
        // 设置相机监听
        mCVCamera.setCvCameraViewListener(this);
        // 连接到OpenCV的回调
        mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    mCVCamera.enableView();
                    break;
                default:
                    break;
                }
            }
        };
    }

》》》》界面加载完成时说明OpenCV已经初始化完成

所以重写onResume()方法,开启相机

     @Override
    protected void onResume() {
        // 界面加载完成的时候向OpenCV的连接回调发送连接成功的信号
        if (OpenCVLoader.initDebug()) {
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
        super.onResume();
    }

重写onPause方法,及时销毁相机

     @Override
    protected void onPause() {
        super.onPause();
        // 销毁OpenCV相机
        if (mCVCamera != null)
            mCVCamera.disableView();
    }

编辑onCameraFrame方法,让相机的每一帧展示在界面上

     @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        return inputFrame.rgba();
    }




 package com.e.opcv;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.util.Collections;
import java.util.Date;
import java.util.List;


public class MainActivity extends  CameraActivity implements CvCameraViewListener2{
    private static final String TAG = "OCVSample::Activity";
    //opencv接口标志


    /**
     * CV相机
     */
    private CameraBridgeViewBase mOpenCvCameraView;
    //缓存相机每帧输入的数据



    private Mat mRgba;
    private Button button;

    private boolean              mIsJavaCamera = true;
    private MenuItem             mItemSwitchCamera = null;


/**
 * 加载OpenCV的回调
 * 通过OpenCV管理Android服务,初始化OpenCV
 */
    private BaseLoaderCallback mLoaderCallback ;



    public MainActivity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }


    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            if(msg.what == 1){
                button.performClick();
            }
        }
    };


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_main);


        // //初始化并设置预览部件  // 初始化CV相机
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);

        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        // 设置相机监听
        mOpenCvCameraView.setCvCameraViewListener(this);




        //拍照按键
        button = (Button) findViewById(R.id.deal_btn);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mRgba != null) {
                    if(!mRgba.empty()) {
                        Mat inter = new Mat(mRgba.width(), mRgba.height(), CvType.CV_8UC4);
                        Log.e("Mat","...............1...............");
                        //将四通道的RGBA转为三通道的BGR,重要!!
                        Imgproc.cvtColor(mRgba, inter, Imgproc.COLOR_RGBA2BGR);
                        Log.e("Mat","...............2...............");
                        File sdDir = null;
                        //判断是否存在机身内存
                        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
                        if(sdCardExist) {
                            //获得机身储存根目录
                            sdDir = Environment.getExternalStorageDirectory();
                            Log.e("Mat","...............3...............");
                        }
                        //将拍摄准确时间作为文件名
                        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
                        String filename = sdf.format(new Date());
                        String savepath=sdDir + "/Pictures/OpenCV/";
                        File f=new File(savepath);
                        if(!f.exists()){
                            f.mkdirs();
                        }
                        String filePath = sdDir + "/Pictures/OpenCV/" + filename + ".png";
                        Log.e("Mat","..............."+filePath+"...............");
                        //将转化后的BGR矩阵内容写入到文件中
                        Imgcodecs.imwrite(filePath, inter);
                        Toast.makeText(MainActivity.this, "图片保存到: "+ filePath, Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });

        // moveTaskToBack(true);
//        new test().start();



        // 连接到OpenCV的回调
        mLoaderCallback   = new BaseLoaderCallback(this){
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    case LoaderCallbackInterface.SUCCESS:
                    {
                        Log.i(TAG, "OpenCV loaded successfully");
                        mOpenCvCameraView.enableView();
                    } break;
                    default:
                    {
                        super.onManagerConnected(status);
                    } break;
                }
            }
        };




    }



    private class test extends Thread{
        @Override
        public void run() {
            super.run();
            while (true){
                try {
                    Thread.sleep(2000);
                    Log.e("begin","kaishi.........");

                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }catch (Exception e){
                    Log.e("error",e.getMessage());
                }
            }
        }
    }






    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {




        // 界面加载完成的时候向OpenCV的连接回调发送连接成功的信号
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }

        super.onResume();
    }

    @Override
    public List<? extends CameraBridgeViewBase> getCameraViewList() {
        return Collections.singletonList(mOpenCvCameraView);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }


    //对象实例化及基本属性的设置,包括长度、宽度和图像类型标志
    public void onCameraViewStarted(int width, int height) {
        Log.e("Mat","...............4...............");
        mRgba = new Mat(height, width, CvType.CV_8UC4);
    }




    /**图像处理都写在这里!!!**/
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

        mRgba = inputFrame.rgba();  //一定要有!!!不然数据保存不进MAT中!!!
        //直接返回输入视频预览图的RGB数据并存放在Mat数据中
        Log.e("Mat","...............5...............");
        return mRgba;

    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }


    //结束时释放
    public void onCameraViewStopped() {

        Log.e("Mat","...............6...............");
        mRgba.release();
        // mTmp.release();
    }
}




OpenCV for Android——摄像头打开与预览_Android_02

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:opencv="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <org.opencv.android.JavaCameraView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"
        android:id="@+id/tutorial1_activity_java_surface_view"
        opencv:show_fps="true"
        opencv:camera_id="any" />

</FrameLayout>

 package com.e.opcv;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;

import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;

import java.util.Collections;
import java.util.List;


public class MainActivity extends  CameraActivity implements CvCameraViewListener2{
    private static final String TAG = "OCVSample::Activity";

    private CameraBridgeViewBase mOpenCvCameraView;
    private boolean              mIsJavaCamera = true;
    private MenuItem             mItemSwitchCamera = null;

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    mOpenCvCameraView.enableView();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    public MainActivity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_main);

        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);

        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);

        mOpenCvCameraView.setCvCameraViewListener(this);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    @Override
    public List<? extends CameraBridgeViewBase> getCameraViewList() {
        return Collections.singletonList(mOpenCvCameraView);
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    public void onCameraViewStarted(int width, int height) {
    }

    public void onCameraViewStopped() {
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        return inputFrame.rgba();
    }
}

OpenCV for Android——摄像头打开与预览_Android_03

修改 protected void deliverAndDrawFrame(CvCameraViewFrame frame)函数为:

 //新方法
                Matrix matrix = new Matrix(); // I rotate it with minimal process
                //matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);
                //matrix.postRotate(90f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
                //float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
                //matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
                //canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
 
                if (getDisplay().getRotation() == Surface.ROTATION_0) {
                    matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);
                    matrix.postRotate(90f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
                    float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
                    matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
                    canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
                } else if (getDisplay().getRotation() == Surface.ROTATION_90) {
                    float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
                    matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
                    canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
                } else if (getDisplay().getRotation() == Surface.ROTATION_180) {
                    matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);
                    matrix.postRotate(270f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
                    float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
                    matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
                    canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
                } else if (getDisplay().getRotation() == Surface.ROTATION_270) {
                    matrix.postRotate(180f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
                    float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
                    matrix.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
                    canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
                } 

OpenCV for Android——摄像头打开与预览_Android_04

拍照

OpenCV for Android——摄像头打开与预览_Android_05

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:opencv="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <org.opencv.android.JavaCameraView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"
        android:id="@+id/tutorial1_activity_java_surface_view"
        opencv:show_fps="true"
        opencv:camera_id="any" />

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom|center_horizontal">

    <Button
        android:id="@+id/deal_btn"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:layout_marginBottom="20dp"
        android:text="拍照处理"/>

</RelativeLayout>



</FrameLayout>

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.e.opcv">
    <uses-permission android:name="android.permission.CAMERA" />
    <!--摄像头-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!--内部存储-->

    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
 package com.e.opcv;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraActivity;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.util.Collections;
import java.util.Date;
import java.util.List;


public class MainActivity extends  CameraActivity implements CvCameraViewListener2{
    private static final String TAG = "OCVSample::Activity";
    //opencv接口标志

    private CameraBridgeViewBase mOpenCvCameraView;
    //缓存相机每帧输入的数据

    private Mat mRgba;
    private Button button;

    private boolean              mIsJavaCamera = true;
    private MenuItem             mItemSwitchCamera = null;



    /**通过OpenCV管理Android服务,初始化OpenCV**/
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    mOpenCvCameraView.enableView();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    public MainActivity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }


 Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            if(msg.what == 1){
                button.performClick();
            }
        }
    };
    

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_main);


        // //初始化并设置预览部件
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);

        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);

        mOpenCvCameraView.setCvCameraViewListener(this);




                //拍照按键
        button = (Button) findViewById(R.id.deal_btn);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mRgba != null) {
                    if(!mRgba.empty()) {
                        Mat inter = new Mat(mRgba.width(), mRgba.height(), CvType.CV_8UC4);
                        Log.e("Mat","...............1...............");
                        //将四通道的RGBA转为三通道的BGR,重要!!
                        Imgproc.cvtColor(mRgba, inter, Imgproc.COLOR_RGBA2BGR);
                        Log.e("Mat","...............2...............");
                        File sdDir = null;
                        //判断是否存在机身内存
                        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
                        if(sdCardExist) {
                            //获得机身储存根目录
                            sdDir = Environment.getExternalStorageDirectory();
                            Log.e("Mat","...............3...............");
                        }
                        //将拍摄准确时间作为文件名
                        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
                        String filename = sdf.format(new Date());
                        String savepath=sdDir + "/Pictures/OpenCV/";
                        File f=new File(savepath);
                        if(!f.exists()){
                            f.mkdirs();
                        }
                        String filePath = sdDir + "/Pictures/OpenCV/" + filename + ".png";
                        Log.e("Mat","..............."+filePath+"...............");
                        //将转化后的BGR矩阵内容写入到文件中
                        Imgcodecs.imwrite(filePath, inter);
                        Toast.makeText(MainActivity.this, "图片保存到: "+ filePath, Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });

       // moveTaskToBack(true);
//        new test().start();
    }



private class test extends Thread{
        @Override
        public void run() {
            super.run();
            while (true){
                try {
                    Thread.sleep(2000);
                    Log.e("begin","kaishi.........");

                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }catch (Exception e){
                    Log.e("error",e.getMessage());
                }
            }
        }
    }






    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {


        /***强制横屏***/
        if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else {
            //横屏后才加载部件,否则会FC
            if(!OpenCVLoader.initDebug()) {
                Log.d(TAG, "OpenCV library not found!");
            } else {
                Log.d(TAG, "OpenCV library found inside package. Using it!");
                mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
            }
        }
        
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    @Override
    public List<? extends CameraBridgeViewBase> getCameraViewList() {
        return Collections.singletonList(mOpenCvCameraView);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }


 //对象实例化及基本属性的设置,包括长度、宽度和图像类型标志
    public void onCameraViewStarted(int width, int height) {
         Log.e("Mat","...............4...............");
        mRgba = new Mat(height, width, CvType.CV_8UC4);
    }

   


 /**图像处理都写在这里!!!**/
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

        mRgba = inputFrame.rgba();  //一定要有!!!不然数据保存不进MAT中!!!
        //直接返回输入视频预览图的RGB数据并存放在Mat数据中
        Log.e("Mat","...............5...............");
        return mRgba;

        // return inputFrame.rgba();
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }


//结束时释放
     public void onCameraViewStopped() {

        Log.e("Mat","...............6...............");
        mRgba.release();
       // mTmp.release();
    }
}

OpenCV for Android——摄像头打开与预览_Android_06

         /***强制横屏***/
        if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else {
            //横屏后才加载部件,否则会FC
            if(!OpenCVLoader.initDebug()) {
                Log.d(TAG, "OpenCV library not found!");
            } else {
                Log.d(TAG, "OpenCV library found inside package. Using it!");
                mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
            }
        }

OpenCV for Android——摄像头打开与预览_Android_07

activity 生命周期

 package com.e.opcv;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class Main2Activity  extends Activity implements SurfaceHolder.Callback, Camera.ShutterCallback, Camera.PictureCallback {


    public static final String FILE_PATH = "filePath";
    private Camera mCamera;
    private SurfaceView mPreview;
    private Button ibSnapPhoto, ibCancelPhoto;
    private String pictureFilePath;


    /**
     * 外部调用接口
     * @param context
     * @param filePath 拍摄照片的存储地址
     */
    public static void callMe(Context context, String filePath){
        Intent intent = new Intent(context,Main2Activity.class);
        intent.putExtra(FILE_PATH, filePath);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);


        //mPrevie为摄像机预览图层
        mPreview = (SurfaceView) findViewById(R.id.surface_view);
        mPreview.getHolder().addCallback(this);
        mPreview.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        ibSnapPhoto = (Button) findViewById(R.id.snap_photo);
        ibCancelPhoto = (Button) findViewById(R.id.cancel_photo);
        ibSnapPhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onSnapPhoto();
            }
        });
        ibCancelPhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onCancelPhoto();
            }
        });

        pictureFilePath = getIntent().getStringExtra(FILE_PATH);

//开启Camera
        mCamera = Camera.open();


    }

    @Override
    protected void onPause() {
        super.onPause();
        mCamera.stopPreview();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCamera.release();
    }

    /**
     * 点击按钮拍照
     */
    private void onSnapPhoto(){
//拍照
        mCamera.takePicture(this, null, null, this);
    }

    /**
     * 点击按钮取消
     */
    private void onCancelPhoto(){
        mCamera.stopPreview();
        finish();
    }





    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        try {
            savePictureToFile(data, pictureFilePath);
        } catch (IOException e) {
            Log.d("wcj", "originalImage保存失败!");
            e.printStackTrace();
        }

//重新启动预览
        mCamera.startPreview();


    }

    @Override
    public void onShutter() {
        Toast.makeText(Main2Activity.this, "click!", Toast.LENGTH_SHORT).show();
    }
    //以下为Surface三种回调方法
    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        //当surfaceView建立时,在上面绑定预览显示界面
        try{
            mCamera.setPreviewDisplay(mPreview.getHolder());
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {



        Camera.Parameters params = mCamera.getParameters();
        List<Camera.Size> sizes = params.getSupportedPreviewSizes();
        Camera.Size selectedSize  =getBestSupportPreviewSize(sizes, getScreenSize());

//设定摄像机预览界面尺寸
        params.setPreviewSize(selectedSize.width, selectedSize.height);
        mCamera.setParameters(params);

        mCamera.setDisplayOrientation(90);
        mCamera.startPreview();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }



    /**
     * 保存照片到存储器
     *
     * @param data
     * @param _file
     * @throws IOException
     */
    public static void savePictureToFile(byte[] data, String _file) throws IOException {
        BufferedOutputStream os = null;
        try {
            File file = new File(_file);
// String _filePath_file.replace(File.separatorChar +
            // file.getName(), "");
            int end = _file.lastIndexOf(File.separator);
            String _filePath = _file.substring(0, end);
            File filePath = new File(_filePath);
            if (!filePath.exists()) {
                filePath.mkdirs();
            }
            file.createNewFile();
            os = new BufferedOutputStream(new FileOutputStream(file));
            os.write(data);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 寻找最大的预览图片尺寸(与屏幕分辨率适配)
     *
     * @param previewSizes 所有支持的预览图片大小
     * @return
     */
    public static Camera.Size getBestSupportPreviewSize(List<Camera.Size> previewSizes, Camera.Size screenSize) {
        double screenRatio = screenSize.width * 1.0 / screenSize.height;
        Camera.Size maxSize = previewSizes.get(0);
        for (Camera.Size size : previewSizes) {
            double sizeRatio = size.width * 1.0 / size.height;
            if (size.width < 2000 && sizeRatio > screenRatio - 0.1 && sizeRatio < screenRatio + 0.1)
                maxSize = (size.width > maxSize.width) ? size : maxSize;
        }
        return maxSize;
    }

    private Camera.Size getScreenSize() {
        DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);
        int width = metric.widthPixels;  // 宽度(PX)
        int height = metric.heightPixels;  // 高度(PX)

        return mCamera.new Size(height, width);
    }



}

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <SurfaceView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/surface_view"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/snap_photo"
        android:text="SNAP"
        android:layout_alignParentBottom="true"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/cancel_photo"
        android:text="CANCEL"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"/>

</RelativeLayout>

OpenCV for Android——摄像头打开与预览_Android_08

机器视觉应用