Android Studio使用Opencv2.4.9进行NDK开发

Home / C++ MrLee 2019-5-28 4935

环境介绍:

Android Studio 3.3.2

NDK:android-ndk-r16(这里强调一下,用AS自带的NDK编译会报fatal error: 'ext/atomicity.h' file not found错误。因为不包含此文件,可能是版本比较高,所以建议用android-ndk-r16编译)

OpenCV-2.4.9-android-sdk(够用库文件还小)

首先创建一个C++工程如已经有工程新建一个module->android library

具体参考:

已经存在的android Studio工程添加ndk支持

然后主要是CMakeLists.txt的编写,在编写之前,先将OpenCV-2.4.9-android-sdk\sdk\native\libs拷贝到工程(module)下的src\main\jniLibs目录,具体如下图:

当然你也可以选择去掉不要的库,减小APK的体积,比如我只保留了armeabi-v7a,主流手机已经够了!

CMakeLists.txt源码

cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(OPENCV "D:/OpenCV-2.4.9-android-sdk/sdk")
#"${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi" 解决asm.h 找不到的问题
include_directories(
        "D:\\OpenCV-2.4.9-android-sdk\\sdk\\native\\jni\\include"
        "${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi")
# 设置opencv的动态库
add_library(libopencv_java SHARED IMPORTED)
set_target_properties(libopencv_java PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java.so)
add_library(sdklib
             SHARED
             src/main/jni/sdknative.cpp
             )
target_link_libraries(sdklib
                        android
                        log
                        libopencv_java
        )

接着就是gradle文件的配置,在android下面添加或修改

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
            }
        }
        ndk {
            moduleName "sdklib"
            abiFilters "armeabi-v7a"
            //abiFilters "armeabi","armeabi-v7a"
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
    }

顺便提下,这个目录src/main/jniLibs是需要自己手动创建的

最后就是测试代码部分

SdkNative.java

package com.core;
public class SdkNative {
    static {
        System.loadLibrary("sdklib");
    }
    public static native void debug();
    public static native void img2gray(int[] pixels, int w, int h);
}

OpenActivity.java

package com.lee.clicker;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import com.android.dev.base.BaseActivity;
import com.core.SdkNative;
public class OpenActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open);
    }
    public void imgToGray(View view) {
        ImageView iv = (ImageView) view;
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        int w = bitmap.getWidth(), h = bitmap.getHeight();
        int[] pixels = new int[w * h];
        bitmap.getPixels(pixels, 0, w, 0, 0, w, h);
        SdkNative.img2gray(pixels, w, h);
        Bitmap resultImage = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        resultImage.setPixels(pixels, 0, w, 0, 0, w, h);
        iv.setImageBitmap(resultImage);
    }
}

activity_open.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:onClick="imgToGray"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

sdknative.cpp

#include "com_core_SdkNative.h"
#include <android/log.h>
#include <jni.h>
#include <string>
#include <opencv2/ml/ml.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sdklib-log", __VA_ARGS__))
JNIEXPORT void JNICALL Java_com_core_SdkNative_debug(JNIEnv *pEnv, jclass _class) {
    LOGI("=======Java_com_core_SdkNative_debug=======");
}
JNIEXPORT void JNICALL Java_com_core_SdkNative_img2gray(JNIEnv *pEnv, jclass _class, jintArray pData, jint iW, jint iH) {
    jint *pixels = pEnv->GetIntArrayElements(pData, JNI_FALSE);
    if (pixels == NULL)return;
    Mat src(iH, iW, CV_8UC4, pixels);
    // 注意,Android的Bitmap是ARGB四通道,而不是RGB三通道
    cvtColor(src,src,CV_BGRA2GRAY);
    cvtColor(src,src,CV_GRAY2BGRA);
    pEnv->SetIntArrayRegion(pData, 0, iW * iH, (jint *) src.data);
}

效果图:

本文链接:https://www.it72.com/12547.htm

推荐阅读
最新回复 (0)
返回