创建一个能够使用OpenCV JavaCameraView的应用程序来了解基于OpenCV java API 的应用程序的开发流程。有了Android的基础,在程序中需要修改的几个地方1.activity_main.xml 2.AndroidManifest.xml 3.MainActivity.java
安装创建android程序的方式创建一个blank activity,项目名称为hellosamples,其他采用默认的activity_main.xml,MainActivity.java。创建完成后,安装之前介绍的方式把OpenCV Library 包含进项目里(重要步骤)。
打开activity_main.xml
复制如下代码
<LinearLayout 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:id="@+id/HelloOpenCvView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="gone" opencv:camera_id="any" opencv:show_fps="true" /> </LinearLayout>
布局文件只包含一个全屏部件类org.opencv.android.JavaCameraView,这个类是在OpenCV library中实现的,采用的是Android CameraAPI实现的。opencv:show_fps="true" 和 opencv:camera_id="any"代表的是可以显示每秒的帧数,以及可以利用任一一个摄像头。当然最先使用的是后置的。
打开AndroidManifest.xml复制如下代码
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.hellosamples" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.CAMERA" /> <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="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
这个主要是设置许可以及主题
package com.example.hellosamples; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.CameraBridgeViewBase; import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame; import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.core.Mat; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.SurfaceView; import android.view.WindowManager; public class MainActivity extends Activity implements CvCameraViewListener2{ private static final String TAG = "OCVSample::Activity"; 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; } } }; @Override public void onResume() { super.onResume(); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback); } private CameraBridgeViewBase mOpenCvCameraView; @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.HelloOpenCvView); mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE); mOpenCvCameraView.setCvCameraViewListener(this); } @Override public void onPause() { super.onPause(); if (mOpenCvCameraView != null) mOpenCvCameraView.disableView(); } 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的初始化过程,OnManagerConnected callback会在UI线程中调用,在使用OpenCV调用或者载入OpenCV支撑的本地库前一定要先包含这一调用。在OpenCV成功初始化后载入本地库,默认的BaseLoaderCallback会把应用程序上下文当成是Activity,所以在初始化失败时会调用Activity.finish()。要重写这一行为,就必须重写finish()这一方法。
这里采用的非同步的方式进行初始化(即在目标机器上要安装好OpenCV manager),然后这个Activity生命周期过程的一些处理。主要的修改地方是实现CvCameraViewListener2中的重要函数onCameraFrame,这个函数可以让你在摄像头捕获图像帧之后对图像进行处理,然后显示在屏幕上,其中CvCameraViewFrame类代表的是从摄像头捕获的图像帧。可以利用这个类的两个方式rgba(),gray()来RGBA和单通道图像.