OpenCV for Android打开相机-阿里云开发者社区

开发者社区> 开发与运维> 正文

OpenCV for Android打开相机

简介: 一、知识准备: 1.了解Android工程如何运行在设备上 2.了解C/C++编译过程,能够读懂makefile 二、实现流程: 1.

一、知识准备:

1.了解Android工程如何运行在设备上

2.了解C/C++编译过程,能够读懂makefile


二、实现流程:

1.打开Eclipse,新建一个空白的Android工程:

        

         

        项目名称为OpenCV_Test:

        


2.为新建工程引入OpenCV Library - 3.1.0库工程:

        

        选择工程,右键点击Properties(属性),然后在Android页签中,用Add功能添加一个库工程引用。


3.打开src目录下面的MainActivity,由于我们的目标是在应用中通过OpenCV的Java API实现打开相机全屏显示,并获取预览框,所以MainActivity需要实现CvCameraViewListener2接口,可以实现三个方法,分别是:onCameraViewStartedonCameraViewStoppedonCameraFrame关键的图像处理写在onCameraFrame函数中:

        


4.修改AndroidManifest.xml文件:

        添加相机的相关权限:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <uses-permission android:name="android.permission.CAMERA"/>  
  2. <uses-feature android:name="android.hardware.camera" android:required="false"/>    
  3. <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>  
        设置应用的界面主题为没有顶部标题栏且全屏显示的,在application标签中添加:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <application  
  2.         android:allowBackup="true"  
  3.         android:icon="@drawable/ic_launcher"  
  4.         android:label="@string/app_name"  
  5.         android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >  

5.为界面布局文件添加显示相机内容的组件:

        打开res/layout下面的activity_main.xml布局文件,往布局中添加一个OpenCV的视觉组件JavaCameraView

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout   
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     xmlns:opencv="http://schemas.android.com/apk/res-auto"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent">  
  7.   
  8.     <org.opencv.android.JavaCameraView   
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         android:id="@+id/camera_view"  
  12.         opencv:show_fps="true"   
  13.         opencv:camera_id="any"/>  
  14.   
  15. </RelativeLayout>  


6.回到MainActivity中,完成API的调用:

        声明一个CameraBridgeViewBase对象,用于存放activity_main.xml中的JavaCameraView组件,并在OnCreate中实现绑定和添加事件监听:

[java] view plain copy
 print?
  1. mCVCamera = (CameraBridgeViewBase) findViewById(R.id.camera_view);  
  2. mCVCamera.setCvCameraViewListener(this);  


7.添加C/C++编译支持,即Add Native Support,这是为了不依赖于OpenCV Manager,直接引入库文件进行编译:

        

        记住这里的填写的名称就是引入的库文件被编译生成.so文件的名称:

        

        打开生成的jni目录下的Android.mk文件,这个是C/C++编译和链接时使用到的makefile配置文件,稍微做一点点修改内容,在“include $(CLEAR_VARS)”后面添加以下内容:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. OPENCV_CAMERA_MODULES:=on  
  2. OPENCV_INSTALL_MODULES:=on  
  3. OPENCV_LIB_TYPE:=SHARED  
  4. ifdef OPENCV_ANDROID_SDK  
  5.   ifneq ("","$(wildcard $(OPENCV_ANDROID_SDK)/OpenCV.mk)")  
  6.     include ${OPENCV_ANDROID_SDK}/OpenCV.mk  
  7.   else  
  8.     include ${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk  
  9.   endif  
  10. else  
  11.   include ../../sdk/native/jni/OpenCV.mk  
  12. endif  
        如此,我们就完成了库文件的引入操作,那么接下来就是让相机的输入帧展示在预览组件JavaCameraView上。


8.修改public Mat onCameraFrame(CvCameraViewFrame inputFrame)回调函数的内容了,这个函数在相机刷新每一帧都会调用一次,而且每次的输入参数就是当前相机视图信息,我们直接获取其中的RGBA信息作为Mat数据返回给显示组件即可:

[java] view plain copy
 print?
  1. /** 
  2.      * 图像处理都写在此处 
  3.      */  
  4.     @Override  
  5.     public Mat onCameraFrame(CvCameraViewFrame inputFrame) {  
  6.         //直接返回输入视频预览图的RGBA数据并存在Mat数据中  
  7.         return inputFrame.rgba();  
  8.     }  

        

9.以上操作中,我们在OnCreate函数中已经获取到mCVCamera对象,只有调用mCVCamera.enableView()之后,预览组件才会显示每一帧的Mat图像,但是在显示之前我们必须先确保OpenCV的库文件已经加载完成,所以调用此方法需要进行异步处理:

[java] view plain copy
 print?
  1. /** 
  2.      * 通过OpenCV管理Android服务,异步初始化OpenCV 
  3.      */  
  4.     BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {  
  5.         @Override  
  6.         public void onManagerConnected(int status){  
  7.             switch (status) {  
  8.             case LoaderCallbackInterface.SUCCESS:  
  9.                 Log.i(TAG,"OpenCV loaded successfully");  
  10.                 mCVCamera.enableView();  
  11.                 break;  
  12.             default:  
  13.                 break;  
  14.             }  
  15.         }  
  16.     };  

            所以只有当mLoaderCallback收到LoaderCallbackInterface.SUCCESS消息的时候,才会打开预览显示,那么这个消息是从哪里发出来的呢,这就需要我们重写Activity的onRusume方法了,因为每次当前Activity激活都会调用此方法,所以可以在此处检测OpenCV的库文件是否加载完毕:

[java] view plain copy
 print?
  1. @Override  
  2.     public void onResume() {  
  3.         super.onResume();  
  4.         if (!OpenCVLoader.initDebug()) {  
  5.             Log.d(TAG,"OpenCV library not found!");  
  6.         } else {  
  7.             Log.d(TAG, "OpenCV library found inside package. Using it!");  
  8.             mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);  
  9.         }  
  10.     };  


三、结果展示:

        至此,我们就完成了设备相机打开以及输入预览数据的获取,运行在设备上可以看到:

        

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章