Android NDK环境配置:Android Studio3.0.1 + CMAKE +OpenCV3.4.1

1.前言

由于笔者在配置NDK环境时遇到了各种坑,在爬坑的过程中有所感悟,所以特地写一篇博客来详细描述利用Android Studio3.0.1(版本>=2.2即可)中的CMAKE方式配置NDK的过程,希望能够帮助各位。

 

2.准备工作

2.1开发环境

  • Android Studio 3.0.1(版本>=2.2即可)
  • Android NDK 17.1.4828580
  • CMAKE
  • Android SDK 27.0.1
  • OpenCV-3.4.1-android-sdk    OpenCV下载地址(点击此链接即可下载)
  • 下载ndk,在File->Settings->Appearance & Behavior -> System Settings-> Android SDK下载相应的ndk
  • 同时如图所示,下载相应的CMake和LLDB

 

3.Java  OpenCV环境的配置

1.创建一个新项目,注意勾选Include C++ support 选项

根据图示勾选相应的选项后点击Finish即可

 

2.将OpenCV下面的java文件夹(路径为OpenCV-android-sdk\sdk\java)作为模块导入,导入后会发现在Project目录下生成openCVLibrary341的目录,修改该目录下的build.gradle的compileSDKVersion、buildToolsVersion、minSdkVersion和targetSdkVersion使其和app目录下的build.gradle文件中的相同,点击右上角的Try Again 重新配置应用即可消除错误

 

3.在主模块中加入对OpenCV Library的依赖(右击左侧边栏的app,选择Open Module Settings,切换到Dependencies窗口,选择Module dependency,若前面成功导入Opencv SDK,这里则会出现类似如图中的选项,选择OK即可将OpenCV引入应用当中)

4.至此,OpenCV的Java层配置已经完成,sync一下,应该就有代码补全了

5.为了愉快的使用OpenCV Library,可以直接在AndroidManifest.xml里面加入如下权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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"/>

 

4.配置NDK环境

1.将include文件夹(路径OpenCV-android-sdk\sdk\native\jni\include)拷贝到cpp目录下(路径\app\src\main\cpp) 

2.在\src\main目录下建议一个jniLIbs目录,将依赖的动态库静态库(路径为OpenCV-android-sdk\sdk\native\jni\libs)中的libopencv_java.so和libopencv_java3.so文件拷贝到\src\main\jniLibs下面

3.完成以上步骤,你的工程结构应该如下图所示

 

4.修改app中的gradle,修改成如图所示

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.zxing.cameraapplication.forlastopencv07151100"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -frtti -fexceptions"
                arguments "-DANDROID_TOOLCHAIN=gcc"

                arguments "-DANDROID_ABI=armeabi-v7a"
                arguments "-DCMAKE_BUILD_TYPE=Release"
            }
        }
        ndk{
            abiFilters "armeabi-v7a"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
    productFlavors{

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

}

dependencies {
    androidTestCompile('com.android.support:support-annotations:26.1.0') {
        force = true
    }
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation project(':openCVLibrary341')
}

5.修改CMakeLists.txt文件(重要),修改后如图所示

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_VERBOSE_MAKEFILE on)
set(libs "${CMAKE_SOURCE_DIR}/src/main/jniLibs")
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)

add_library(libopencv_java3 SHARED IMPORTED )
set_target_properties(libopencv_java3 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_java3.so")

add_library(libopencv_java SHARED IMPORTED )
set_target_properties(libopencv_java PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_java.so")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fexceptions -frtti")



# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries(native-lib android log
    libopencv_java3 #used for java sdk
    libopencv_java #same to static libs
    ${log-lib}
    )

点击右上角sync重新配置即可

 

5.demo演示(图片灰度化)

1.native-lib.cpp

#include <jni.h>
#include <string>
#include <opencv2/core/hal/interface.h>
#include <opencv2/calib3d.hpp>

using namespace cv;


extern "C" {

JNIEXPORT jintArray JNICALL
Java_com_www_ndk_MainActivity_getGrayImage(JNIEnv *env, jobject, jintArray buf, int w, int h){
    jint *pixels = env->GetIntArrayElements(buf, NULL);
    if(pixels == NULL){
        return NULL;
    }

    cv::Mat imgData(h, w,CV_8UC4, pixels);
    uchar *ptr = imgData.ptr(0);
    for(int i=0; i<w*h; i++){
        int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);
        ptr[4*i+0] = (uchar)grayScale;
        ptr[4*i+1] = (uchar)grayScale;
        ptr[4*i+2] = (uchar)grayScale;
    }
    int size = w * h;
    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result, 0, size, pixels);
    env->ReleaseIntArrayElements(buf, pixels, 0);
    return result;
}

}

 

2.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.www.ndk.MainActivity">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@drawable/boy"
        android:layout_centerInParent="true" />
    <Button
        android:id="@+id/bt_Gray"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:text="Gray"  />

</RelativeLayout>

 

3.MainActivity.java

package com.www.ndk;

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import org.opencv.core.Mat;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    private Button bt_photo = null;

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


        // adding
        bt_photo =  findViewById(R.id.bt_Gray);
        bt_photo.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                ImageView img = (ImageView)findViewById(R.id.img);
                Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(
                        R.drawable.boy)).getBitmap();
                int w = bitmap.getWidth(), h = bitmap.getHeight();
                int[] pix = new int[w * h];
                bitmap.getPixels(pix, 0, w, 0, 0, w, h);
                int[] resultPixes = getGrayImage(pix,w,h);
                Bitmap result = Bitmap.createBitmap(w,h, Bitmap.Config.RGB_565);
                result.setPixels(resultPixes, 0, w, 0, 0,w, h);
                img.setImageBitmap(result);
            }
        });

    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native int[] getGrayImage(int[] pixels, int w, int h);
}

 

4.将命名为boy的图片放在drawable目录下面

5.运行的结果如图所示

                        

 

至此,NDK环境已经确定配置好。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值