簡(jiǎn)介
在移動(dòng)開發(fā)中闺鲸,如果我們要實(shí)現(xiàn)一些圖像處理相關(guān)的功能,難免要用到OpenCV赛糟。而OpenCV是用c++開發(fā)的派任。我們?cè)贏ndroid中,需要使用jni的方法去使用它璧南。
引入配置
我們引入jni開發(fā)的基本配置方法掌逛,已經(jīng)在另一篇博客中介紹過了,不再贅述司倚。這一次我們無非是要引入第三方的c++庫豆混。
首先,我們找到或新建jniLibs文件夾动知,然后將依賴的動(dòng)態(tài)庫和靜態(tài)庫(路徑為OpenCV-android-sdk\sdk\native\libs
)拷貝到\src\main\jniLibs
下面皿伺。
然后,找到cpp文件夾盒粮。將include文件夾(路徑OpenCV-android-sdk\sdk\native\jni\include
)拷貝到cpp(路徑\app\src\main\cpp
)文件夾里心傀。
接著,我們需要引入c++的相關(guān)支持拆讯。在module的build.gradle里面加入:
externalNativeBuild {
cmake {
//arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_static'
cppFlags "-std=c++11","-frtti", "-fexceptions"
}
}
ndk{
abiFilters 'armeabi-v7a'
}
最后脂男,我們需要在CMakeLists.txt中,加入opencv相關(guān)的聲明种呐。由于配置比較復(fù)雜宰翅,在此直接將demo的CMakeLists.txt的內(nèi)容貼到這里。
# 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)
# 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.
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_calib3d STATIC IMPORTED )
set_target_properties(libopencv_calib3d PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_calib3d.a")
add_library(libopencv_core STATIC IMPORTED )
set_target_properties(libopencv_core PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_core.a")
add_library(libopencv_features2d STATIC IMPORTED )
set_target_properties(libopencv_features2d PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_features2d.a")
add_library(libopencv_flann STATIC IMPORTED )
set_target_properties(libopencv_flann PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_flann.a")
add_library(libopencv_highgui STATIC IMPORTED )
set_target_properties(libopencv_highgui PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_highgui.a")
add_library(libopencv_imgcodecs STATIC IMPORTED )
set_target_properties(libopencv_imgcodecs PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_imgcodecs.a")
add_library(libopencv_imgproc STATIC IMPORTED )
set_target_properties(libopencv_imgproc PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_imgproc.a")
add_library(libopencv_ml STATIC IMPORTED )
set_target_properties(libopencv_ml PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_ml.a")
add_library(libopencv_objdetect STATIC IMPORTED )
set_target_properties(libopencv_objdetect PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_objdetect.a")
add_library(libopencv_photo STATIC IMPORTED )
set_target_properties(libopencv_photo PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_photo.a")
add_library(libopencv_shape STATIC IMPORTED )
set_target_properties(libopencv_shape PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_shape.a")
add_library(libopencv_stitching STATIC IMPORTED )
set_target_properties(libopencv_stitching PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_stitching.a")
add_library(libopencv_superres STATIC IMPORTED )
set_target_properties(libopencv_superres PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_superres.a")
add_library(libopencv_video STATIC IMPORTED )
set_target_properties(libopencv_video PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_video.a")
add_library(libopencv_videoio STATIC IMPORTED )
set_target_properties(libopencv_videoio PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_videoio.a")
add_library(libopencv_videostab STATIC IMPORTED )
set_target_properties(libopencv_videostab PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_videostab.a")
add_library(libopencv_ts STATIC IMPORTED )
set_target_properties(libopencv_ts PROPERTIES
IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_ts.a")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fexceptions -frtti")
#include_directories(D:/Projects/Android/CLMAndroid/OpenCV-android-sdk/sdk/native/jni/include )
#set(OpenCV_DIR D:/Projects/Android/CLMAndroid/OpenCV-android-sdk/sdk/native/jni)
#find_package(OpenCV REQUIRED)
#target_link_libraries(${OpenCV_LIBS})
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( # Specifies the target library.
native-lib android log
libopencv_java3 libopencv_calib3d libopencv_core libopencv_features2d libopencv_flann libopencv_highgui libopencv_imgcodecs
libopencv_imgproc libopencv_ml libopencv_objdetect libopencv_photo libopencv_shape libopencv_stitching libopencv_superres
libopencv_video libopencv_videoio libopencv_videostab
# Links the target library to the log library
# included in the NDK.
${log-lib} )
這樣配置之后爽室,我們就可以在cpp中汁讼,直接使用OpenCV庫了。在此貼一個(gè)簡(jiǎn)單的均值濾波:
#include <jni.h>
#include <string>
#include <opencv2/opencv.hpp>
#include <bits/stdc++.h>
#include <android/log.h>
#include<opencv2/core/core.hpp>
#include"opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
#define MAKE_ARGB(a, r, g, b) ((a&0xff)<<24) | ((r&0xff)<<16) | ((g&0xff)<<8) | (b&0xff)
#define MAKE_RGB565(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
extern "C"
{
JNIEXPORT jintArray JNICALL
Java_com_live_longsiyang_opencvdemo_OpenCVNativeManager_getBlurImage(JNIEnv *env, jobject thiz,
jintArray pixels_, jint w,
jint h) {
int colorType = CV_8UC4;
jint *pixels = env->GetIntArrayElements(pixels_, NULL);
Mat imgMat(h, w, colorType, pixels);
Mat out(h, w, colorType);
blur(imgMat, out, Size(20, 20));
env->ReleaseIntArrayElements(pixels_, pixels, 0);
int *outIntImage = new int[w * h];
for (int i = 0; i < w * h; i++) {
int a, r, g, b;
for (int j = 0; j < 4; j++) {
a = out.data[i * 4 + 3];
r = out.data[i * 4 + 2];
g = out.data[i * 4 + 1];
b = out.data[i * 4 + 0];
outIntImage[i] = (int) out.data[i * 4 + j];
}
outIntImage[i] = MAKE_ARGB(a,r,g,b);
}
jintArray result = env->NewIntArray(w * h);
env->SetIntArrayRegion(result, 0, w * h, outIntImage);
return result;
}
}
這樣我們就能看到一個(gè)基本的模糊效果的demo阔墩。
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
ImageView mIvTest;
Button mBtnTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvTest = (ImageView) findViewById(R.id.img_test);
mIvTest.setImageResource(R.drawable.beauty_steward_course_video_thumb_icon);
mBtnTest = (Button) findViewById(R.id.btn_test);
mBtnTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.beauty_steward_course_video_thumb_icon);
int w = srcBitmap.getWidth();
int h = srcBitmap.getHeight();
int[] pixels = new int[w*h];
srcBitmap.getPixels(pixels,0,w,0,0,w,h);
int[] outPixels = OpenCVNativeManager.getBlurImage(pixels ,w,h);
Bitmap destBitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
destBitmap.setPixels(outPixels,0,w,0,0,w,h);
mIvTest.setImageBitmap(destBitmap);
}
});
findViewById(R.id.btn_reset).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mIvTest.setImageResource(R.drawable.beauty_steward_course_video_thumb_icon);
}
});
}
}
導(dǎo)出.so
在build中找到這個(gè)so嘿架,這就是我們需要的文件。此外啸箫,由于我們使用了opencv相關(guān)的庫耸彪,我們還需要將opencv的相關(guān)文件復(fù)制出來。將其導(dǎo)入我們需要的工程忘苛。
導(dǎo)入之后蝉娜,我們只需要在module的build.gradle里面加入:
android {
...
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
aidl.srcDirs = ['src/main/aidl']
}
}
}
之后,我們就可以直接調(diào)用
System.loadLibrary("native-lib");
值得注意的是扎唾,JNI的方法是與路徑名相關(guān)的召川,所以當(dāng)我們以這樣的方法調(diào)用native方法時(shí),我們需要路徑名匹配胸遇。
以上荧呐。