opencv for android 生成.so的问题,1.通过opencv源码编译Android上可以使用的库

前提是你已经安装了安卓ndk和cmake

1. 下载opencv源码

git clone https://github.com/opencv/opencv.git opencv

2. 您应该创建一个输出目录(在上面opencv的源码目录),因为OpenCV不允许进行源内构建

mkdir android_build

cd android_build

3.要使用cmake创建必要的构建结构,您需要在ANDROID_NDK变量中提供NDK的路径。也许这个问题已经得到解决,但是OpenCV使用的.cmake文件在Android上无法正常工作。幸运的是,NDK提供了位于build / cmake中某个位置的android.toolchain.cmake文件。我通过定义-DCMAKE_TOOLCHAIN_FILE变量来强制cmake使用此文件。

其他一些调整是我禁用了Java东西的构建,并且还指定了我要使用的STL运行时(尽管可能默认情况下已经设置了相同的运行时)。

我还指定了安装前缀。这是所有输出文件(包括.so库和头文件)将被复制到的目录。

您应该指定的另一个变量是ANDROID_ABI,否则默认情况下会选择不推荐使用的armeabi。对于其他项目,通常将使用CMAKE_ANDROID_ARCH_ABI,但是在使用NDK提供的.cmake文件时,似乎会忽略此标志。

您的cmake shell命令应如下所示

cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/ndk/build/cmake/android.toolchain.cmake -DANDROID_NDK=/path/to/ndk -DANDROID_NATIVE_API_LEVEL=android-21 -DBUILD_JAVA=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DBUILD_ANDROID_PROJECTS=OFF -DANDROID_STL=c++_shared -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX:PATH=/absolute/path/to/opencv/android_build/out -DANDROID_ABI=arm64-v8a

请注意,我首先将当前工作目录更改为在上一步中创建的目录(android_build /),然后执行了shell命令。

在某些情况下,您只需要某些模块特定功能的一小部分。为了减少构建时间和最终大小,OpenCV的构建系统允许您在构建过程中禁用某些模块和功能。

cmake .. \

-DBUILD_opencv_ittnotify=OFF -DBUILD_ITT=OFF -DCV_DISABLE_OPTIMIZATION=ON -DWITH_CUDA=OFF -DWITH_OPENCL=OFF -DWITH_OPENCLAMDFFT=OFF -DWITH_OPENCLAMDBLAS=OFF -DWITH_VA_INTEL=OFF -DCPU_BASELINE_DISABLE=ON -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DBUILD_TESTING=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DBUILD_opencv_apps=OFF -DBUILD_SHARED_LIBS=OFF -DOpenCV_STATIC=ON -DWITH_1394=OFF -DWITH_ARITH_DEC=OFF -DWITH_ARITH_ENC=OFF -DWITH_CUBLAS=OFF -DWITH_CUFFT=OFF -DWITH_FFMPEG=OFF -DWITH_GDAL=OFF -DWITH_GSTREAMER=OFF -DWITH_GTK=OFF -DWITH_HALIDE=OFF -DWITH_JASPER=OFF -DWITH_NVCUVID=OFF -DWITH_OPENEXR=OFF -DWITH_PROTOBUF=OFF -DWITH_PTHREADS_PF=OFF -DWITH_QUIRC=OFF -DWITH_V4L=OFF -DWITH_WEBP=OFF \

-DBUILD_LIST=core,features2d,flann,imgcodecs,imgproc,stitching \

-DANDROID_NDK=/path/to/ndk -DCMAKE_TOOLCHAIN_FILE=/path/to/ndk/build/cmake/android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=android-21 -DBUILD_JAVA=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DBUILD_ANDROID_PROJECTS=OFF -DANDROID_STL=c++_shared -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX:PATH=/absolute/path/to/opencv/android_build/out -DANDROID_ABI=arm64-v8a

这是在为Pano Stitch&Crop App编译OpenCV时禁用某些模块和功能的方式。请注意我如何禁用某些功能,然后使用它来指定所需的模块。OFF``-DBUILD_LIST

您可能需要针对特定​​情况更改一些其他选项。您可以使用以下命令来检查哪些变量可用

cmake -LA

如果出现一些错误,并且您更改了一些选项来修复这些错误,则可能还需要先删除CMakeCache.txt文件,然后才能成功运行cmake。

最后建立项目执行

make

make install

我们将在Android应用程序中使用的.so库应位于out / sdk / native / libs /目录内。

CMake使得交叉编译Android项目变得非常容易。您可以使用上面显示的相同方法来交叉编译另一个相关的库dlib。

4.准备要构建的Android Studio项目

在这里,我假设您已经创建了一个新的启用了C ++支持的Android Studio项目。

为了正确地将我们的本机代码与OpenCV库链接,您应该在应用程序模块文件夹中更改CMakeLists.txt文件

# Configure path to include directories

include_directories(SYSTEM $ENV{VENDOR}/opencv/include )

# Set up OpenCV shared .so library so that it can

# be linked to your app

add_library( cv_core-lib SHARED IMPORTED)

set_target_properties( cv_core-lib

PROPERTIES IMPORTED_LOCATION

$ENV{VENDOR}/opencv/lib/${ANDROID_ABI}/libopencv_core.so )

add_library( cv_imgproc-lib SHARED IMPORTED)

set_target_properties( cv_imgproc-lib

PROPERTIES IMPORTED_LOCATION

$ENV{VENDOR}/opencv/lib/${ANDROID_ABI}/libopencv_imgproc.so )

add_library( cv_imgcodecs-lib SHARED IMPORTED)

set_target_properties( cv_imgcodecs-lib

PROPERTIES IMPORTED_LOCATION

$ENV{VENDOR}/opencv/lib/${ANDROID_ABI}/libopencv_imgcodecs.so )

...

# jnigraphics lib from NDK is used for Bitmap manipulation in native code

find_library( jnigraphics-lib jnigraphics )

# Link to your native app library

target_link_libraries( my_native-lib ${jnigraphics-lib} cv_core-lib cv_imgproc-lib cv_imgcodecs-lib other-libs...)

在这里,我链接了core,imgproc和imgcodecs模块。您可能需要根据使用的功能添加其他OpenCV库。

我决定在这种情况下使用共享库,但是静态链接也应该起作用。

我还链接了NDK的jnigraphics库。在我的示例代码中,我使用一些位图操作方法,因此这是必需的。

接下来,您应该更改模块级别的build.gradle文件

android {

...

defaultConfig {

...

sourceSets {

main {

jniLibs.srcDirs = [

System.getenv('VENDOR') + '/opencv/lib'

]

}

}

这将确保gradle将lib文件夹中的OpenCV .so库打包到最终的APK中。该LIB /文件夹应包含每个支持的体系结构,例如,armeabi,armeabi-V7A,...我通常至少包括子文件夹armeabi-V7A和86的最终APK进行发布,但测试你可以只包括ABI支持由您测试设备

此外,在模块级别的build.gradle文件中,我通常还会指定要为其构建的ABI,要使用的C ++运行时,C ++异常支持以及其他一些东西

在以下代码中,我将对来自克尔克岛的一张度假照片使用Canny边缘检测。首先,我将JPEG图像加载到Kotlin的位图中,然后使用本机代码中的位图像素来执行Canny边缘检测。

考虑到您可以使用OpenCV进行的所有操作,此示例似乎有些la脚,但是我试图将其简化。如果您对Android上的某些低延迟/实时Camera图像处理感兴趣。

始终可以直接使用本机C ++代码打开图像文件。但是,Android的Java API 在许多其他图像处理和图形相关功能中使用Bitmap类。因此,我认为在本地代码中显示如何访问Bitmap的像素缓冲区而不进行不必要的复制会很有用。

始终可以直接使用本机C ++代码打开图像文件。但是,Android的Java API 在许多其他图像处理和图形相关功能中使用Bitmap类。因此,我认为在本地代码中显示如何访问Bitmap的像素缓冲区而不进行不必要的复制会很有用。

首先,我们创建一个本机C ++函数,该函数将通过JNI从我们的Kotlin类中调用。该函数接受一个输入bitmap,该输入将用于检测精明边缘。该功能会将检测到的边缘写入给定destination文件。

#include

#include

#include

#include

#include

using namespace cv;

extern "C" {

JNIEXPORT void JNICALL

Java_eu_sisik_opencvsample_MainActivity_canny(

JNIEnv *env,

jobject /* this */,

jobject bitmap,

jstring destination) {

// Get information about format and size

AndroidBitmapInfo info;

AndroidBitmap_getInfo(env, bitmap, &info);

// Get pointer to pixel buffer

void *pixels = 0;

AndroidBitmap_lockPixels(env, bitmap, &pixels);

// I create separate scope for input Mat here

// to make sure it is destroyed before unlocking

// pixels

{

// Check the format info before you pick the CV_ type

// for OpenCV Mat

// info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 -> CV_8UC4

// Now create the mat

Mat input(info.height, info.width, CV_8UC4, pixels);

// Perform canny edge detection

Mat edges;

Canny(input, edges, 200.0, 600.0, 600.0);

// Save to destination

const char *dest = env->GetStringUTFChars(destination, 0);

imwrite(dest, edges);

env->ReleaseStringUTFChars(destination, dest);

}

// Release the Bitmap buffer once we have it inside our Mat

AndroidBitmap_unlockPixels(env, bitmap);

}

}

在上面的代码中,我从位图像素缓冲区构造了一个OpenCV Mat。我为inputMat对象创建了一个单独的作用域,以确保它在调用之前被破坏AndroidBitmap_unlockPixels()。

在Kotlin代码中,您应确保加载了本地.so库System.loadLibrary()。本机方法用external关键字声明

class MainActivity : AppCompatActivity() {

...

external fun canny(src: Bitmap?, destinationPath: String): Void

companion object {

init {

System.loadLibrary("native-lib")

}

}

...

要使用Kotlin的本机C ++函数

var bitmap: Bitmap? = null

assets.open("pinezici_krk_island.JPG").use {

bitmap = BitmapFactory.decodeStream(it)

}

// Store result inside of app's cache folder

var dest = cacheDir.absolutePath + "/canny.JPG"

// Pass the bitmap to native C++ code and perform canny edge detection

canny(bitmap, dest)

// Show the processed image

ivPhoto.setImageBitmap(BitmapFactory.decodeFile(dest))

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值