zoukankan      html  css  js  c++  java
  • AndroidStudio 3.4.2配置 Opencv 3.7

    前言:

    前段时间做项目,需要给AS配置Opencv环境,查了很多博客,遇到了很多坑,为了避免遗忘,在此记录,如有错误,请指教。

    1、前期准备

    • 下载opencv androidSdk:https://opencv.org/releases/
      在这里插入图片描述
      这里网速太慢,我截个图示意一下,我之前下载的是3.7版本

    2、 新建AS项目

    这一步要注意,AS3.2版本的时候可以勾选include C++ Surpport,而AS3.4.2把 NativeC++单独拿了出来,需要下拉右侧滑动条选择 Native C++,我之前找这个找了半天?
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3、配置NDK

    NDK需要手动配置,在刚刚新建好的项目中,选择 file —>setting—>Android SDK —> SDK tools 勾选NDK和cmake
    在这里插入图片描述

    4、复制opencv的相关文件

    • include文件
      将下载好的opencv安装包解压后在路径*OpenCV-android-sdksdk ativejni下有一个include文件夹,复制该文件夹到我们项目中的src/main/cpp
    • jni 文件
      在项目的main文件夹下新建一个名为jniLibs的文件夹,然后在路径*OpenCV-android-sdksdk ative下有一个libs文件夹,将此文件夹复制到刚刚新建的jniLibs文件夹下。项目结构如下图所示在这里插入图片描述

    5、配置build-gradle

    app下的build-gradle中的android节点下添加以下代码

    sourceSets {
            main {
                jniLibs.srcDirs = ['src/main/jniLibs/libs']
            }
        }
    

    此代码的作用就是设置动态链接库的地址,android节点是下图圈出的部分
    在这里插入图片描述
    然后在Android.defaultConfig.externalNativeBuild 的节点内增加过滤器,如下:

    abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
    

    其中'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64',选择一个就行,如果是在模拟器上开发就选择X86,如果在手机上选择armeabi-v7a,这一步要注意的是过滤器添加的位置不要弄错了,是添加在下图中上第一个圈出来的节点。在这里插入图片描述
    完整的build-gradle文件,如下

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 29
        buildToolsVersion "29.0.1"
        defaultConfig {
            applicationId "com.example.opencvdemo"
            minSdkVersion 23
            targetSdkVersion 29
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
            externalNativeBuild {
                cmake {
                    cppFlags "-std=c++11"
                    abiFilters 'armeabi-v7a'
                }
                ndk {
                    abiFilters 'armeabi-v7a'
                }
            }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
        externalNativeBuild {
            cmake {
                path "src/main/cpp/CMakeLists.txt"
                version "3.10.2"
            }
        }
        sourceSets {
            main {
                jniLibs.srcDirs = ['src/main/jniLibs/libs']
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'androidx.appcompat:appcompat:1.1.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test:runner:1.2.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    }
    

    配置完后,Sysn Now一下

    6、配置Cmake

    还记得之前项目结构中的CMakeList.txt文件吗?这里我们需要先把该文件移动到app文件夹下,这样方便之后配置include文件夹路径和动态链接库的路径,与此同时需要将app下build-gradle文件中android.externalNativeBuild节点下cmake的路径修改为"CMakeLists.txt",即第二张图中 的path改为path "CMakeLists.txt"
    在这里插入图片描述
    在这里插入图片描述
    CMakeLists.txt文件中添加如下代码。

    # 设置include文件夹的地址
    include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)
    
    # 设置opencv的动态库
    add_library(libopencv_java3 SHARED IMPORTED)
    set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/src/main/jniLibs/libs/${ANDROID_ABI}/libopencv_java3.so)
    
    target_link_libraries( # Specifies the target library.
                           native-lib libopencv_java3
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )
    

    include_directories 函数设置了include文件夹的路径
    add_library 函数设置库名和类型,其中libopencv_java3 是用户自定义的变量名,前后保持一致即可,SHARE 表示引入的库是动态链接库
    set_target_properties 设置了OpenCV的动态链接库的路径
    target_link_libraries 具有依赖关系的动态库链接到指定目标上,链接顺序需符合gcc链接规则,这里我们把libopencv_java3log链接到了native-lib上。

    7、测试

    经过上面一些列配置,opencv环境已经配置完成,可以编写代码进行测试.

    • native-lib
    #include <jni.h>
    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    using namespace std;
    
    extern "C" JNIEXPORT jintArray
    
    JNICALL
    Java_com_example_opencvdemo_MainActivity_Bitmap2Grey(
            JNIEnv *env,
            jobject /* this */,jintArray buf,jint w,jint h) {
        jint *cbuf;
        jboolean ptfalse = false;
        cbuf = env->GetIntArrayElements(buf, &ptfalse);
        if(cbuf == NULL){
            return 0;
        }
    
        Mat imgData(h, w, CV_8UC4, (unsigned char*)cbuf);
        // 注意,Android的Bitmap是ARGB四通道,而不是RGB三通道
        cvtColor(imgData,imgData,CV_BGRA2GRAY);
        cvtColor(imgData,imgData,CV_GRAY2BGRA);
    
        int size=w * h;
        jintArray result = env->NewIntArray(size);
        env->SetIntArrayRegion(result, 0, size, (jint*)imgData.data);
        env->ReleaseIntArrayElements(buf, cbuf, 0);
        return result;
    }
    
    • MainActivity
    package com.example.opencvdemo;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        private Button btn_1;
        private Button btn_2;
        private ImageView imageView;
        private Bitmap bitmap;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn_1 = (Button)findViewById(R.id.button_1);
            imageView = (ImageView)findViewById(R.id.image);
            bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.flower);
            imageView.setImageBitmap(bitmap);
            btn_1.setOnClickListener(this);
    
            btn_2 = (Button)findViewById(R.id.button_2);
            btn_2.setOnClickListener(this);
        }
        public void showImage(){
            bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.flower);
            imageView.setImageBitmap(bitmap);
        }
    
        public void gray(){
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            int[] piexls = new int[w*h];
            bitmap.getPixels(piexls,0,w,0,0,w,h);
            int[] resultData =Bitmap2Grey(piexls,w,h);
            Bitmap resultImage = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
            resultImage.setPixels(resultData,0,w,0,0,w,h);
            imageView.setImageBitmap(resultImage);
        }
    
        @Override
        public void onClick(View view){
            switch(view.getId()){
                case R.id.button_1:showImage();break;
                case R.id.button_2:gray();break;
            }
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native int[] Bitmap2Grey(int[] pixels,int w,int h);
    
        @Override
        public void onResume(){
            super.onResume();
        }
    }
    
    • activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical">
    
            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/flower" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <Button
                android:id="@+id/button_2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="灰度图" />
    
            <Button
                android:id="@+id/button_1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="色图" />
        </LinearLayout>
    
    </LinearLayout>
    
    • 效果
      在这里插入图片描述

    8 参考链接

    [1].Android NDK学习笔记:Android Studio3.1+CMAKE+OpenCV3.4配置
    [2].AndroidStudio NDK之使用OpenCV
    [3].Android Studio配置及使用OpenCV
    [4].Android Studio中配置OpenCV

  • 相关阅读:
    TCP 连接断连问题剖析
    libtool: link: you must specify an output file
    socket编程bind浮动ip
    epoll或者kqueue的原理是什么?
    推荐 30 款最好的免费项目管理软件
    QNX开发最完整图文教程(官方文档,非官方翻译)
    Android 4.X系列の界面设计中退出Android程序的代码
    APScheduler 定时任务系统
    给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。
    APSchenuler嵌入Django
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13860121.html
Copyright © 2011-2022 走看看