【Android】Android Studio 2上利用NDK进行OpenCV 3.1开发(注意点)

90 篇文章 0 订阅


【参考】Android Studio 2上利用NDK进行OpenCV 3.1开发

                OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰)

                [安卓开发笔记一]Android开发配置opencv环境超详细教程


开发环境

        Windows 7 x64 旗舰版

        Android Studio 2.1.2

        JDK 1.8.0————(C:\Program Files\Java\jdk1.8.0_102)

        Android 6.0(API 23)

        OpenCV 3.1.0 Android SDK————(E:\Android-Config\OpenCV-android-sdk\sdk\native\jni)

        Android NDK r12b————————(E:\Android-Config\android-ndk-r12b)


1、打开Android Studio 2.1.2,点击sdk_manager_button图标打开SDK Manager。选择SDK Tools,勾选NDK如下图


我是另外下载,解压到上面“开发环境”的路径。


2、打开Android Studio,新建一个项目;(参考一)

File——Project Structure

--Android SDK Location:C:\Users\duan\AppData\Local\Android\Sdk

--JDK Location:C:\Program Files\Java\jdk1.8.0_102

--Android NDK Location:E:\Android-Config\android-ndk-r12b   (重要)

3、右键main,新建jni——在源码目录创建一个jni文件夹。右击main文件夹,选择New->Directory,输入jni;

再新建Android.mk,Application.mk,gray-process.cpp




4、此时项目的文件结构如下图所示,比较重要的文件用红色框标记:



5、每个文件的内容:

MainActivity:

grayProc()、loadLibrary();

package com.example.duanjiwei.opencvndk;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements OnClickListener {

    private Button btnProc;
    private ImageView imageView;
    private Bitmap bmp;

    public static native int[] grayProc(int[] pixels, int w, int h);

    static {
        System.loadLibrary("gray-process");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnProc = (Button) findViewById(R.id.btn_gray_process);
        imageView = (ImageView) findViewById(R.id.image_view);
        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pic);
        imageView.setImageBitmap(bmp);
        btnProc.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {

        int w = bmp.getWidth();
        int h = bmp.getHeight();
        int[] pixels = new int[w*h];
        bmp.getPixels(pixels, 0, w, 0, 0, w, h);
        int[] resultInt = grayProc(pixels, w, h);
        Bitmap resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        resultImg.setPixels(resultInt, 0, w, 0, 0, w, h);
        imageView.setImageBitmap(resultImg);
    }

    @Override
    public void onResume(){
        super.onResume();
    }
}
activity_main.xml

添加Button、ImageView控件

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.duanjiwei.opencvndk.MainActivity">

    <Button
        android:id="@+id/btn_gray_process"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/str_proc"/>

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/str_proc"
        android:layout_marginTop="60dp"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

Android.mk

注意:OpenCV路径,使用 “/” 做分隔; 使用"\\"出现错误;

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#opencv
include E:/Android-Config/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED

LOCAL_SRC_FILES := gray-process.cpp
LOCAL_LDLIBS += -llog
LOCAL_MODULE := gray-process

include $(BUILD_SHARED_LIBRARY)
Application.mk

APP_ABI中添加适用范围;

APP_STL := gnustl_shared
APP_CPPFLAGS := -frtti -fexceptions -std=c++11
APP_ABI := armeabi armeabi-v7a x86
APP_PLATFORM := android-15

gray_process.cpp

.cpp文件中编写C++代码;Android中关于JNI 的学习(一)对于JNIEnv的一些认识

那么C++和Java之间的是如何通过JNI来进行互相调用的呢?
我们知道,在Android中,当Java文件被编译成dex文件之后,会由类加载器加载到Dalvik VM(DVM)中,由DVM来进行解释,翻译成机器语言之后,才能由机器来运行。
而对于C/C++来说,其源代码经由Android提供的NDK工具包,可以编译成可执行动态库(即.so文件),之后,Java和C++之间就可以进行通讯了。

jni.h源文件:http://blog.csdn.net/taily_duan/article/details/52488783

//
// Created by duanjiwei on 2016/9/8.
//

#include <jni.h>
#include <opencv2/opencv.hpp>

extern "C" {

using namespace cv;
using namespace std;

JNIEXPORT jintArray JNICALL Java_com_example_duanjiwei_opencvndk_MainActivity_grayProc(JNIEnv *env, jclass obj, jintArray buf, jint w, jint h){
    jboolean ptfalse = false;
    jint* srcBuf = env->GetIntArrayElements(buf, &ptfalse);
    if(srcBuf == NULL){
        return 0;
    }
    int size=w * h;

    Mat srcImage(h, w, CV_8UC4, (unsigned char*)srcBuf);
    Mat grayImage;
    cvtColor(srcImage, grayImage, COLOR_BGRA2GRAY);
    cvtColor(grayImage, srcImage, COLOR_GRAY2BGRA);

    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result, 0, size, srcBuf);
    env->ReleaseIntArrayElements(buf, srcBuf, 0);
    return result;
}

}
res--values--strings.xml

<resources>
    <string name="app_name">OpenCVNDK</string>
    <string name="str_proc">gray process</string>
    <string name="str_desc">image description</string>
</resources>
src下的build.gradle

import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.example.duanjiwei.opencvndk"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

    sourceSets.main {
        jniLibs.srcDirs = ['src/main/libs', 'src/main/jniLibs']
        jni.srcDirs = [] //disable automatic ndk-build call
    }

    project.ext.versionCodes = ['armeabi':1, 'armeabi-v7a':2, 'arm64-v8a':3, 'mips':5, 'mips64':6, 'x86':8, 'x86_64':9]
    //versionCode digit for each supported ABI, with 64bit>32bit and x86>armeabi-*

    android.applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
            output.versionCodeOverride =
                    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + defaultConfig.versionCode
        }
    }

    // call regular ndk-build(.cmd) script from app directory
    task ndkBuild(type: Exec) {
        Properties properties = new Properties()
        properties.load(project.rootProject.file('local.properties').newDataInputStream())
        def ndkDir = properties.getProperty('ndk.dir')

        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
            commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath
        } else {
            commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath
        }
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
}
app下的build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


local.properties

Android sdk路径、NDK路径;

## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=C\:\\Users\\duanjiwei\\AppData\\Local\\Android\\Sdk
ndk.dir=E\:\\Android-Config\\android-ndk-r12b


模拟器与手机上均能成功运行:




===================================================

网上Q群方法:

 先import module
添加依赖 


 app中创jniLibs 


 sourceSets改成这样 










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值