Android引入OpenCV的示例

作者:oldFrog 时间:2022-04-26 08:19:33 

简介

在移动开发中,如果我们要实现一些图像处理相关的功能,难免要用到OpenCV。而OpenCV是用c++开发的。我们在Android中,需要使用jni的方法去使用它。

引入配置

我们引入jni开发的基本配置方法,已经在另一篇博客中介绍过了,不再赘述。这一次我们无非是要引入第三方的c++库。

首先,我们找到或新建jniLibs文件夹,然后将依赖的动态库和静态库(路径为OpenCV-android-sdk\sdk\native\libs)拷贝到\src\main\jniLibs下面。

然后,找到cpp文件夹。将include文件夹(路径OpenCV-android-sdk\sdk\native\jni\include)拷贝到cpp(路径\app\src\main\cpp)文件夹里。

接着,我们需要引入c++的相关支持。在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相关的声明。由于配置比较复杂,在此直接将demo的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)

# 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库了。在此贴一个简单的均值滤波:


#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;  
 }
}

这样我们就能看到一个基本的模糊效果的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);
     }
   });
 }
}

Android引入OpenCV的示例

导出.so

Android引入OpenCV的示例

在build中找到这个so,这就是我们需要的文件。此外,由于我们使用了opencv相关的库,我们还需要将opencv的相关文件复制出来。将其导入我们需要的工程。

Android引入OpenCV的示例

导入之后,我们只需要在module的build.gradle里面加入:


android {
 ...

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

之后,我们就可以直接调用


System.loadLibrary("native-lib");

值得注意的是,JNI的方法是与路径名相关的,所以当我们以这样的方法调用native方法时,我们需要路径名匹配。

来源:https://www.jianshu.com/p/4864af795969?utm_source=tuicool&utm_medium=referral

标签:Android,OpenCV
0
投稿

猜你喜欢

  • Java Struts图片上传至指定文件夹并显示图片功能

    2023-03-15 10:48:51
  • Android 基于Bitmap的四种图片压缩方式

    2022-06-13 11:50:21
  • Spring Boot Reactor 整合 Resilience4j详析

    2021-08-08 10:30:02
  • SpringIOC框架的简单实现步骤

    2021-10-28 21:44:35
  • 双重检查锁定模式Java中的陷阱案例

    2023-11-13 22:11:02
  • javafx实现五子棋游戏

    2022-02-01 07:00:01
  • WPF中不规则窗体与WindowsFormsHost控件兼容问题的解决方法

    2022-09-26 12:47:19
  • Swagger2匹配多个controller代码实例

    2022-07-31 03:42:24
  • SpringBoot启动后启动内嵌浏览器的方法

    2023-02-27 17:42:53
  • 基于android实现五子棋开发

    2022-05-22 14:21:43
  • Android自定义View详解

    2023-01-22 07:23:38
  • 详解Android短信的发送和广播接收实现短信的监听

    2022-08-14 16:55:23
  • android 软键盘的POPUP布局的问题解决

    2022-03-22 17:53:30
  • 详解Spring Security如何配置JSON登录

    2023-02-08 17:39:07
  • Java SSH 秘钥连接mysql数据库的方法

    2022-07-11 21:23:18
  • Spring AOP在web应用中的使用方法实例

    2023-12-24 12:20:00
  • c#创建圆形类Circle、矩形类实现代码

    2023-08-18 19:59:12
  • C#语法糖(Csharp Syntactic sugar)大汇总

    2022-12-04 12:55:23
  • 字符串替换Replace仅替换第一个字符串匹配项

    2021-10-02 17:36:56
  • java pdf加水印的方法

    2022-09-03 06:06:50
  • asp之家 软件编程 m.aspxhome.com