android java opencv_OpenCV On Android最佳环境配置指南(Eclipse篇)

本文详细介绍了如何在Android Studio环境下配置OpenCV,包括导入OpenCV库、创建OpenCVDemo、使用Java库和NDK库的步骤,以及解决相关问题的方法。文章还提供了混合使用Java和C++的指导,旨在帮助开发者更高效地进行移动图像处理开发。
摘要由CSDN通过智能技术生成

注:本篇文章作者已不再维护,毕竟现在使用Eclipse的Android程序员少之又少,所以我将只维护Android Studio篇。如果你坚持用Eclipse,请确保所有环境与本文章一致。

简介

本教程是经过本人多次踩坑,并参考网上众多OpenCV On Android的配置教程总结而来,尽希望能帮助学习移动图像处理的朋友们少走弯路。

这也是本人第一次在简书上发布文章,如有不足,希望各位dalao能够指正,我也将及时修改。配置上如果遇到问题,也可以在评论里留言,我将尽力帮助解决。

OpenCV On Android最佳环境配置指南(Android studio篇)。

环境

电脑:Windows10

Java:jdk1.8.0_172

Eclipse:Photon Release (4.8.0)

ADT:ADT-24.0.2

NDK:Android Studio自带的最新NDK

OpenCV:V3.4.1

SDK:25.2.5(由24.4.1更新)

注:以上配置基本上为最新版本,其中,Eclipse可与Android Studio共用一个NDK,但SDK不能通用,否则你将不能在eclipse上正确创建Android项目。

一、创建OpenCV Demo

首先创建一个普通的Android应用,需要注意的是,我们需要将Minimum Required SDK设置为API15或以上,这样既能兼容市面上95%的Android手机,又不会引入潜在的错误。如果此处出现错误,请确保你的JDK、ADT和SDK是否配置正确。

这里我创建的是名为OpenCVDemo的项目,包名为com.demo.opencv,OK。

b260ebb1c180

1.png

二、OpenCV Java库使用指南

环境配置

第一步:Eclipse菜单->File->Import->Android->Existing Android Code Into Workspace,然后导入OpenCV Android SDK\ sdk\java这个项目。

b260ebb1c180

2.png

为了防止误操作OpenCV库,建议勾选Copy project into workspace,将该库copy到你的工作文件夹。然后Finish,如果导入后出现报错,请将Project build Target设置为Android5.0以上(因为一般是Camera2报错,Camera2只存在于Android5.0+),具体方法是项目鼠标右键,选择Properties,然后点击Android,选择Android5.0以上的版本即可,然后OK,这里我选择的是5.0.1。

b260ebb1c180

3.png

第二步:在你的项目右键也进入上图的页面,Library选择Add,添加OpenCV库,完成后,你的项目便可以调用OpenCV Java函数了。

b260ebb1c180

4.png

Demo编写

创建一个Java图像处理类OpenCV_Java .java(请忽略我的命名)

OpenCV_Java.java内容:

public class OpenCV_Java extends BaseLoaderCallback {

private boolean isInit = false;

private Context context;

public OpenCV_Java(Context context){

super(context);

this.context = context;

}

@Override

public void onManagerConnected(int status) {

switch (status) {

case LoaderCallbackInterface.SUCCESS:

isInit = true;

break;

default:

isInit = false;

super.onManagerConnected(status);

break;

}

}

public void toGary(Bitmap bitmap){

if(isInit){

Mat mat = new Mat();

Utils.bitmapToMat(bitmap, mat);

Imgproc.cvtColor(mat, mat,Imgproc.COLOR_RGBA2GRAY );

Utils.matToBitmap(mat, bitmap);

}else{

Toast.makeText(context, "OpenCV init error", Toast.LENGTH_LONG).show();

}

}

}

MainActivity.java内容:

public class MainActivity extends Activity implements OnClickListener {

private ImageView imageView;

private Bitmap bitmap;

private Button showBtn, processBtn;

private OpenCV_Java javaUtil = new OpenCV_Java(this);

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

imageView = (ImageView) findViewById(R.id.imageView);

showBtn = (Button) findViewById(R.id.show);

showBtn.setOnClickListener(this);

processBtn = (Button) findViewById(R.id.process);

processBtn.setOnClickListener(this);

}

@Override

public void onResume() {

super.onResume();

if (!OpenCVLoader.initDebug()) {

OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, javaUtil);

} else {

javaUtil.onManagerConnected(LoaderCallbackInterface.SUCCESS);

}

}

@Override

public void onClick(View v) {

if (v == showBtn) {

bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

imageView.setImageBitmap(bitmap);

} else {

if (bitmap != null) {//避免二次处理

javaUtil.toGary(bitmap);

imageView.setImageBitmap(bitmap);

bitmap = null;

}

}

}

}

布局内容:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/imageView"

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:orientation="horizontal" >

android:id="@+id/show"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_weight="1"

android:text="show"/>

android:id="@+id/process"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_weight="1"

android:text="process"/>

安装OpenCV Manager

其位置位于OpenCV-android-sdk\apk目录下,选择合适的apk程序,一般选择OpenCV_3.2.0_Manager_3.20_armeabi.apk即可。

运行Demo

将项目编译打包成apk,安装到手机,运行,点击按钮show后,其效果左所示,

点击process按钮后,将彩图灰度化,如右图所示:

b260ebb1c180

5.png

注意:

1、如果出现OpenCV was not initialised correctly.Application will be shut down,可能是你的OpenCV Manager程序与你的cpu架构不同,选择合适的apk即可。

2、如果是手机版本比较高,有可能手机会阻止你的应用去调用OpenCV Manager,其目的是防止恶意软件相互唤醒(比如百度全家桶),解决方法自行百度(因为没有统一的方法)。

抛弃OpenCV Manager:

安装一个额外的apk对用户来说非常不友好,但使用C/C++编程,对一些Java程序员又提高了实现难度,故我们应该想一个两全其美的方法,即帮助开发人员使用java快速开发,又给用户一良好体验。

思路:Java库实际上只是对NDK库进行java封装,将so文件放在OpenCV Manager内,通过AIDL进行数据交流,并实现图像处理。

解决办法:如果我们将OpenCV Manager里面的NDK库放到我们的应用里,不就能抛弃OpenCV Manager并实现图像处理了吗?答案是YES,我们将OpenCV-android-sdk\sdk\native\libs\[架构]目录下(这里选择合适的架构,一般用armeabi-v7a即可)的libopencv_java3.so放在你的项目libs\[架构]\目录(需自己手动创建)下,项目结构如图:

b260ebb1c180

6.png

然后在你的MainActivity.java里面静态加载这个so库

public class MainActivity extends Activity implements OnClickListener {

private ImageView imageView;

private Bitmap bitmap;

private Button showBtn, processBtn;

private OpenCV_Java javaUtil = new OpenCV_Java(this);

static{

System.loadLibrary("opencv_java3");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

......下面内容不变

编译并安装,这时候,你就可以将你的OpenCV Manager卸载掉了。运行结果与之前的无异。

此方法并不是完美的,因为在这个程序里,你只实现了彩色图像变灰度图像,但你却安装了这个原生库,apk足足有4.39M,相比之前的194k来说,接近增长了20倍。但如果你的应用比较大,而这个so文件的大小是固定的,此时采用此方法将是一个不错的选择。

四、OpenCV NDK库使用指南

环境配置

第一步:配置NDK环境

进入菜单->Window->Preferences->Android->NDK,设置NDK Location路径,注:请确保该路径下存在ndk-build.cmd文件。如下图:

b260ebb1c180

7.png

第二步:配置JNI环境

这里我将使用简便方法快速配置:

1、在你的项目右键Android Tools->Add native support->输入合适的名称->确定,这里我就直接使用默认的"OpenCVDemo"。

2、本地新建一个xml文件,将下面内容copy进去,修改其中的路径为你ndk库对应的路径。

D:\AndroidSDK\AndroidStudio\ndk-bundle\sysroot\usr\include

D:\AndroidSDK\AndroidStudio\ndk-bundle\sources\cxx-stl\gnu-libstdc++\4.9\include

D:\OpenCV\OpenCV-android-sdk\sdk\native\jni\include

D:\AndroidSDK\AndroidStudio\ndk-bundle\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.9.x\include

3、项目右键选择最后一个Properties,然后选择C/C++ General -> Path and Symbols,如图所示:

b260ebb1c180

8.png

点击Import Settings->Browse,在电脑本地选择上面的xml文件,点击Finish,环境就导入成功了。

接下来查看环境是否正确。

1、查看路径是否存在:按照下图,将编译器切换到C/C++编辑器模式:

b260ebb1c180

9.png

展开项目,查看Include目录下路径是否为灰色(如下图),并且都能展开,如果都满足,表示路径都存在。

b260ebb1c180

10.png

2、查看环境是否正常。进入jni目录,打开OpenCVDemo.cpp,在#include这句代码上使用Ctrl+鼠标左键,如果eclipse能打开jni.h这个文件,说明你的JNI环境就搭建成功了。

第二步:配置OpenCV NDK环境

1、将下面内容copy进Android.mk文件,其中OPENCV_ANDROID_SDK请设置为正确路径,同时请注意我在清单文件里的注释。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# ###########################################################

#这里改成你的路径,分割线内其余内容不变

OPENCV_ANDROID_SDK := D:/OpenCV/OpenCV-android-sdk

#OPENCV_BULID_TYPE := NDK #默认NDK环境,不会自动导入openCV_java3.so,故不支持OpenCV Java库

OPENCV_BULID_TYPE := JAVA_AND_NDK #将自动导入openCV_java3.so,来支持Java库(无需安装OpenCV Manager)

ifeq ($(OPENCV_BULID_TYPE), JAVA_AND_NDK)

OPENCV_LIB_TYPE := SHARED

OPENCV_INSTALL_MODULES := on

else

OPENCV_LIB_TYPE := STATIC

endif

ifdef OPENCV_ANDROID_SDK

ifneq ("","$(wildcard $(OPENCV_ANDROID_SDK)/OpenCV.mk)")

include ${OPENCV_ANDROID_SDK}/OpenCV.mk

else

include ${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk

endif

else

include ../../sdk/native/jni/OpenCV.mk

endif

# ###########################################################

#动态链接日志库

LOCAL_LDLIBS += -llog -ljnigraphics

LOCAL_MODULE := OpenCVDemo

LOCAL_SRC_FILES := OpenCVDemo.cpp

include $(BUILD_SHARED_LIBRARY)

2、在jni目录下增加Application.mk文件

其内容如下:

APP_STL := gnustl_static

APP_CPPFLAGS := -frtti -fexceptions

APP_ABI := all

APP_PLATFORM := android-15

APP_OPTIM := debug

到此为止,NDK环境配置完毕。

Demo编写

布局文件与上面的Java Demo无异,MainActivity.java内容如下:

public class MainActivity extends Activity implements OnClickListener {

private ImageView imageView;

private Bitmap bitmap;

private Button showBtn, processBtn;

private OpenCV_NDK nativeUtil = new OpenCV_NDK();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

imageView = (ImageView) findViewById(R.id.imageView);

showBtn = (Button) findViewById(R.id.show);

showBtn.setOnClickListener(this);

processBtn = (Button) findViewById(R.id.process);

processBtn.setOnClickListener(this);

}

@Override

public void onClick(View v) {

if (v == showBtn) {

bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

imageView.setImageBitmap(bitmap);

} else {

if (bitmap != null) {

nativeUtil.toGary(bitmap);

imageView.setImageBitmap(bitmap);

bitmap = null;

}

}

}

}

这里可以看出并无太大的改变。其中OpenCV_NDK.java内容如下:

public class OpenCV_NDK {

static{

System.loadLibrary("OpenCVDemo");

}

native void toGary(Object bitmap);

}

是不是特别简单^_^。然后在控制台使用javah命令将OpenCV_NDK.java生成.h的c/c++头文件,此处将生成com_demo_opencv_OpenCV_NDK.h(这个文件名跟你包名和类名有关,具体方法请百度)。

将OpenCVDemo.cpp修改为如下内容:

#include "com_demo_opencv_OpenCV_NDK.h"

#include

#include

using namespace cv;

JNIEXPORT void JNICALL Java_com_demo_opencv_OpenCV_1NDK_toGary

(JNIEnv *env, jobject thiz, jobject bitmap){

AndroidBitmapInfo bitmapInfo;

void* bitmapPixels;

int width, height, ret;

//解析bitmap

if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0) {

return;

}

if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {

return ;

}

if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) {

return;

}

width = bitmapInfo.width;

height = bitmapInfo.height;

Mat bgra(height, width, CV_8UC4, bitmapPixels);

Mat gary;

cvtColor(bgra,gary,COLOR_RGBA2GRAY);

cvtColor(gary,bgra,COLOR_GRAY2BGRA);

AndroidBitmap_unlockPixels(env, bitmap);

}

然后编译运行,结果与Java运行结果无异,无需安装OpenCV Manager,此方法编译的安装包只有951kb,图像处理时间本人并没有计算,应该相差无几。

五、OpenCV 混合使用指南

假设你已经看了前两种配置,习惯于Java开发,但又觉得OpenCV Java库提供的方法不够,希望使用混合开发,那恭喜你,这一部分就是你所需要的。这部分内容很少,总结起来就两部分:

1、导入OpenCV Java库并关联你的应用,参考OpenCV Java库使用指南(记得写静态加载so库的内容,但so文件不需要你手动导入)。

2、配置JNI环境与NDK环境,参考OpenCV NDK库使用指南。

3、修改Android.mk文件内容:OPENCV_BULID_TYPE := NDK为OPENCV_BULID_TYPE := JAVA_AND_NDK。

然后编译,这时候Android.mk会打包你的原生代码成libOpenCVDemo.so文件,并将其与libopencv_java3.so同时放入你的libs目录。

如图:

b260ebb1c180

12.png

这样就轻易实现免安装OpenCV Manager,进行java和c++混合处理图像,同时免于手动导入libopencv_java3.so,注意:静态导入so的代码必须有。

六、总结

本教程致力于帮助OpenCV新人快速配置,可能有不足之处,接受大家的建议与批评,后续将进行补充和改进。同时欢迎大家一起探讨Android图像处理的知识,共同进步。

b260ebb1c180

OpenCV On Android学习群.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值