• OpenCV On Android环境配置最新&最全指南(Android Studio篇)


    本文是从本人简书上搬运而来,属本人原创,如有转载,请注明出处:http://www.jianshu.com/p/6e16c0429044

    简介

    本文是《OpenCV On Android环境配置最新&最全指南》系列教程第二篇,也是配置教程的最后一篇。通过对android Studio里opencv环境配置讲解,快速帮新人解决入门配置问题。
    本文内容是本人经过多次踩坑,并参考网上众多OpenCV On Android的配置教程总结而来,尽希望能帮助学习移动图像处理的朋友们少走弯路,如有转载,请标明出处http://www.jianshu.com/p/6e16c0429044
    本篇文章写的时候有点匆忙,肯定有遗漏之处,后续将持续补充。同时如有不足之处,希望各位dalao能够指正,我也将及时修改。配置上如果遇到问题,也可以在评论里留言,我将尽力帮助解决。
    如果您使用的是Eclipse,请参考前一章OpenCV On Android环境配置最新&最全指南(Eclipse篇)


    环境

    电脑:Windows10
    Java:jdk1.8.0_131
    Android Studio:Version 2.3.3
    SDK:Android Studio2.3.3自带的最新SDK (请不要与Eclipse同用一SDK,以免出错)。
    NDK:Android Studio2.3.3自带的最新NDK
    OpenCV:V3.2.0

    注:以上配置基本上为最新版本


    问答:

    1、我已经会使用Eclipse搭建OpenCV Java和NDK环境了,为什么还需要看你这篇文章?

    答:原因有以下几点:
    1、现实原因,参见为什么要用Android Studio?,可见Android Studio迟早会称霸Android IDE界;
    2、配置原因,OpenCV在Eclipse配置非常复杂(我当初配置了接近一个月),而Android Studio则简单到令人泪奔(下面我将介绍详细的配置方式)。
    3、调试原因,也是最重要的一点,Eclipse NDK代码调试功能弱,并且出现异常概率高,相比较,Android Studio稳定多了,NDK调试非常方便。

    2、我已经会使用Android Studio搭建OpenCV Java和NDK环境了,为什么还需要看你这篇文章,你这篇文章有什么特殊之处吗?

    答:我也不是一个喜欢重复造轮子的人,既然写了这篇文章,肯定会去介绍一种不同的配置方式。正如本教程题目所提到的“最新”这个词,我敢能保证我的配置方式是紧跟“时代潮流”。
    传统的Android Studio配置OpenCV环境与Eclipse无异,都是采用Android.mk文件进行配置,而本文则采用CMake进行配置,更加方便,简洁,这种方式也是Android Studio所提倡的。


    配置前说明:

    本次配置不像上篇介绍Eclipse配置环境那样编写多个Demo,本次将使用一个Demo,将OpenCV Java和NDK配置方式完全包含,尽可能帮助大家去理解,请大家不要跳跃式地阅读。
    同时OpenCV Java库和NDK库的优缺点在上篇文章里面已经提及,本文就不再赘述。

    一、安装必要组键

    1、打开SDK Manager。如果是欢迎界面,选择Configure->SDK Manager。如果是项目界面,选择Tools->Android->SDK Manager
    打开后界面如图下图:
    1.png

    将选项条切换到SDK Tools,勾上CMake和NDK,然后OK,开始下载(如果之前是勾选上的,则可以忽略此步)。
    2.png
    下载完后,则可以开始正式创建项目。

    二、创建Android Studio工程

    Create New Projec,这一步没什么好说的,由于是在一个Demo里介绍Java和NDK配置,所以我们必须提前将Include C++ support勾选上,如下图(请注意我的项目名和包名,以免后续JNI编写时出错)
    3.png
    接下来几步都默认,但在Customize the Activity这步,我将Activity Name设置为JavaActivity,如下图:
    4.png
    下一步,Customize C++ Support中,C++ Standard设置为C++11,下面两个CheckBox都勾选上(别问我为什么,我也不知道改咋解释)。如下图:

    5.png
    Finish,项目创建成功

    三、OpenCV Java库使用指南

    环境配置:

    第一步、将OpenCV Java库作为Module导入。具体步骤为:File->New->Import Module,然后将OpenCV-android-sdksdkjava目录导入,如下图,然后Next->Finish
    6.png
    如果导入后报以下错误,你可以选择点击链接下载缺少的sdk版本,但我一般不这样做,因为这个版本我一般不怎么用,毕竟太低了,下载了占内存。
    7.png
    我的做法是,将文件列表上方Android切换至Project,展开文件列表,分别打开appuild.gradle文件和OpenCVLibrary320uild.gradle文件,将OpenCVLibrary320uild.gradle的几个版本号改成与appuild.gradle文件里相同即可,然后在文本域上方点击Try Again,如下图:
    8.png

    第二步、给项目添加OpenCV Java库依赖
    菜单File->Project Structure,在Modules里选择app,右侧进入Dependencies,点击加号,选择Module dependency,如下图:
    9.png
    选择OpenCVLibrary320,OK!

    代码编写:

    在AndroidManifest.xml文件中添加权限:

    ....
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.CAMERA" />
    
        <uses-feature android:name="android.hardware.camera.autofocus" />
        <uses-feature
            android:name="android.hardware.camera"
            android:required="true" />
    ....
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    将activity_java.xml内容修改为以下内容:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <org.opencv.android.JavaCameraView
            android:id="@+id/javaCameraView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:camera_id="back"
            app:show_fps="true" />
    
    </LinearLayout>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    将JavaActivity.java改为以下内容:

    public class JavaActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
        private JavaCameraView javaCameraView;
        private BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    case LoaderCallbackInterface.SUCCESS: {
                        javaCameraView.enableView();
                    }
                    break;
                    default:
                        super.onManagerConnected(status);
                        break;
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //保持屏幕常亮
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            setContentView(R.layout.activity_java);
            javaCameraView = (JavaCameraView) findViewById(R.id.javaCameraView);
            javaCameraView.setVisibility(SurfaceView.VISIBLE);
            javaCameraView.setCvCameraViewListener(this);
        }
    
        @Override
        public void onPause() {
            super.onPause();
            if (javaCameraView != null)
                javaCameraView.disableView();
        }
    
        @Override
        public void onResume() {
            super.onResume();
            if (!OpenCVLoader.initDebug()) {
                OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_2_0, this, baseLoaderCallback);
            } else {
                baseLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
            }
        }
    
        @Override
        public void onCameraViewStarted(int width, int height) {
    
        }
    
        @Override
        public void onCameraViewStopped() {
    
        }
    
        @Override
        public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
            return inputFrame.rgba();
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    在手机里安装OpenCV Manager.apk,考虑到兼容性,一般选择OpenCV_3.2.0_Manager_3.20_armeabi.apk,然后安装我们的apk,运行如下图(我是在虚拟机运行的,故横屏)。
    10.png

    免安装OpenCV Manager

    此处参见OpenCV On Android环境配置最新&最全指南(Eclipse篇)OpenCV Java库使用指南最后部分。

    四、OpenCV NDK库使用指南

    环境配置:

    Android Studio配置OpenCV环境灰常简单(是的,没错),只需修改一个文件便能成功配置环境,什么Android.mk啊、Application.mk啊,全部滚蛋。
    配置方式:打开CMakeLists.txt,内容修改如下,记得将OpenCV_DIR设置为你的路径

    cmake_minimum_required(VERSION 3.4.1)
    
    # ##################### OpenCV 环境 ############################
    #设置OpenCV-android-sdk路径
    set( OpenCV_DIR D:/OpenCV/OpenCV-android-sdk/sdk/native/jni )
    
    find_package(OpenCV REQUIRED )
    if(OpenCV_FOUND)
        include_directories(${OpenCV_INCLUDE_DIRS})
        message(STATUS "OpenCV library status:")
        message(STATUS "    version: ${OpenCV_VERSION}")
        message(STATUS "    libraries: ${OpenCV_LIBS}")
        message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
    else(OpenCV_FOUND)
        message(FATAL_ERROR "OpenCV library not found")
    endif(OpenCV_FOUND)
    
    # ###################### 项目原生模块 ###########################
    
    add_library( native-lib
                 SHARED
                 src/main/cpp/native-lib.cpp)
    
    target_link_libraries( native-lib
                           ${OpenCV_LIBS}
                           log
                           jnigraphics)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    OK,环境配置好了,嘿嘿嘿,接下来开始代码编写。

    代码编写:

    菜单File->New->Activity->Empty Activity,创建一个新的Activity,其命名下如图,并设置为起点页,Finish

    11.png
    为了桌面上两个程序入口不冲突,请在AndroidManifest.xml文件中给两个Activity指定label,如下图:

    12.png
    布局文件activity_jni.xml内容如下:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal" >
    
            <Button
                android:id="@+id/show"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1" 
                android:text="show"/>
    
            <Button
                android:id="@+id/process"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1" 
                android:text="process"/>
        </LinearLayout>
    
    </RelativeLayout>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    JniActivity.java内容如下:

    public class JniActivity extends AppCompatActivity implements View.OnClickListener {
        private ImageView imageView;
        private Button showBtn, processBtn;
    
        static {//加载so库
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_jni);
            imageView = (ImageView) findViewById(R.id.imageView);
            showBtn = (Button) findViewById(R.id.show);
            showBtn.setOnClickListener(this);
            processBtn = (Button) findViewById(R.id.process);
            processBtn.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            if (v == showBtn) {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
                imageView.setImageBitmap(bitmap);
            } else {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
                getEdge(bitmap);
                imageView.setImageBitmap(bitmap);
            }
        }
    
        //获得Canny边缘
        native void getEdge(Object bitmap);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    将一张名为test.jpg的图片放置在drawable目录下,我使用的是我的偶像照片,嘿嘿嘿^_^!

    test.png

    应用层写好了,现在开始原生层操作:

    第一步:生成头文件
    打开Android Studio下方Terminal栏,输入cd appsrcmainjava(所有应用都一样),回车。然后输入javah com.demo.opencvdemo.JniActivity(这里是包名.类名),回车后,将在appsrcmainjava目录下生成一个头文件,将其剪切到appsrcmaincpp目录下。
    13.png
    第二步:编写NDK代码
    native-lib.cpp内容修改为:

    #include "com_demo_opencvdemo_JniActivity.h"
    #include <android/bitmap.h>
    #include <opencv2/opencv.hpp>
    
    using namespace cv;
    
    JNIEXPORT void JNICALL Java_com_demo_opencvdemo_JniActivity_getEdge
            (JNIEnv *env, jobject thizz, jobject bitmap) {
    
        AndroidBitmapInfo info;
        void *pixels;
    
        CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
        CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
                  info.format == ANDROID_BITMAP_FORMAT_RGB_565);
        CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
        CV_Assert(pixels);
        if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
            Mat temp(info.height, info.width, CV_8UC4, pixels);
            Mat gray;
            cvtColor(temp, gray, COLOR_RGBA2GRAY);
            Canny(gray, gray, 3, 9, 3);
            cvtColor(gray, temp, COLOR_GRAY2RGBA);
        } else {
            Mat temp(info.height, info.width, CV_8UC2, pixels);
            Mat gray;
            cvtColor(temp, gray, COLOR_RGB2GRAY);
            Canny(gray, gray, 3, 9, 3);
            cvtColor(gray, temp, COLOR_GRAY2RGB);
        }
        AndroidBitmap_unlockPixels(env, bitmap);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    运行程序,注意,此时可能会默认打开JavaActivity,退出应用,从桌面进入JniActivity,运行效果如下:

    14.png
    点击处理:

    15.png
    额······我的偶像,即使变成被Canny检测了边缘,还是我的偶像,哈哈哈!!!

    五、总结

    OpenCV On Android 系列配置教程就到此为止,写这两篇文章确实也不容易,修改了很多遍,尤其是这篇Android Studio,算是百忙之中抽空完成的吧,也拖了很久。自己在配置的过程中踩了无数的坑,希望我的经验能够帮助到大家少走弯路,同时也虚心接受大家的批评与指正。移动端图像处理的路还长,我也将不断去学习充实自己,这两篇文章算是了却我的一个心愿,接下来的时间,我将全身心投入考研,反正大家都加油吧,下面是我创的学习群,我也将不定期帮助大家解决问题,请加群的人保持一个和善的心,分享经验,共同进步,记住:别人帮助你不是必须的

  • 相关阅读:
    Action<T>和Func<T>的使用(转)
    javascript将网页表格导出Word(转载)
    jQuery扩展方法2(转载)
    Microsoft SQL Server 2008 安装说明
    INSERT INTO 语句的语法错误 access 保留字段
    .NET 验证控件
    TFS强制撤销用户的签出
    .net 操作XML
    TFS 恢复删除文件
    checkboxlist详细用法、checkboxlist用法、checkboxlist
  • 原文地址:https://www.cnblogs.com/antflow/p/7340724.html
Copyright © 2020-2023  润新知