OpenCV On Android开发 - Android Studio上环境配置

本文详细介绍如何在AndroidStudio2.2环境下集成OpenCV4AndroidSDK,包括准备工作、配置步骤及测试程序实现,让应用程序直接使用OpenCV而无需依赖额外组件。

在Android Studio 2.2上集成OpenCV4Android SDK

OpenCV官方的教程是基于Eclipse配置开发环境,但是Eclipse已经被Google抛弃了,所以我是写这篇文章的前三天刚刚开始用Android Studio 2.2版本,很多Gradle脚本也不熟悉,只能各种查找。经过一番痛苦的领悟终于把OpenCV4Android集成到我在Android Studio中创建的项目上了,并且写了测试程序。下面说一下如何实现集成步骤,首先是准备工作要做好:

  • 下载好Android Studio 2.2版本
  • 下载好OpenCV4AndroidSDK - 去OpenCV社区官网即可得到。
  • 下载之后解压缩到D:\OpenCV-2.4.11-android-sdk\OpenCV-android-sdk
    这里写图片描述
  • apk目录里面放的是OpenCV Manager的安装文件,是不同CPU版本要选择不同apk安装文件,这种方式调用OpenCV比较麻烦。不推荐!

  • doc目录里面放的是相关文档与OpenCV的LOGO

  • samples里面放的是OpenCV4Android的演示代码,参考价值很大,值得关注

  • sdk里面放内容就是我们要重点关注的,集成到Android Studio中的项目上去的东西。
    双击打开sdk文件夹就会看到:
    这里写图片描述

准备工作做好之后,首先就是要在Android Studio中创建一个Android项目,创建好之后,选择File->New->Import Module
这里写图片描述
然后选择到SDK路径下的JAVA
这里写图片描述
导入之后,你就会看到
这里写图片描述
就说明成功导入了,然后打开Module Settings
这里写图片描述

添加依赖之后,就可以在项目中引用OpenCV相关API代码了,如果你此刻运行测试apk程序,它就会提示你安装OpenCV Manager这个东西。对多数开发者来说这不算配置成功,这样自己的APP就无法独立安装,必须依赖OpenCV Manager这个apk文件才可以运行,这个时候就该放大招来解决这个问题,首先把我们准备阶段看到SDK下面native文件下所有的文件都copy到你创建好的项目libs目录下,然后在gradle中加上如下一段脚本:
这里写图片描述

task nativeLibsToJar(type: Jar, description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

然后还要加上这句话:

compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')

最后一步,检查一下gradle文件:
这里写图片描述
如此配置之后你就再也不需要其它任何配置了,这样既避免了NDK繁琐又不用依赖OpenCV Manager第三方APP,你的APP就可以直接使用OpenCV了。

特别说明:
此配置方式OpenCV加载必须通过静态加载方式,以下为Demo测试程序代码:

package com.example.administrator.helloworld;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.view.ActionMode;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import java.io.InputStream;

import static android.widget.Toast.makeText;

public class MainActivity extends AppCompatActivity {
    private double max_size = 1024;
    private int PICK_IMAGE_REQUEST = 1;
    private ImageView myImageView;
    private Bitmap selectbp;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        staticLoadCVLibraries();
        myImageView = (ImageView)findViewById(R.id.imageView);
        myImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        Button selectImageBtn = (Button)findViewById(R.id.select_btn);
        selectImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // makeText(MainActivity.this.getApplicationContext(), "start to browser image", Toast.LENGTH_SHORT).show();
                selectImage();
            }
        });

        Button processBtn = (Button)findViewById(R.id.process_btn);
        processBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // makeText(MainActivity.this.getApplicationContext(), "hello, image process", Toast.LENGTH_SHORT).show();
                convertGray();
            }
        });

    }

    //OpenCV库静态加载并初始化
    private void staticLoadCVLibraries(){
        boolean load = OpenCVLoader.initDebug();
        if(load) {
            Log.i("CV", "Open CV Libraries loaded...");
        }
    }

    private void convertGray() {
        Mat src = new Mat();
        Mat temp = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(selectbp, src);
        Imgproc.cvtColor(src, temp, Imgproc.COLOR_BGRA2BGR);
        Log.i("CV", "image type:" + (temp.type() == CvType.CV_8UC3));
        Imgproc.cvtColor(temp, dst, Imgproc.COLOR_BGR2GRAY);
        Utils.matToBitmap(dst, selectbp);
        myImageView.setImageBitmap(selectbp);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
            Uri uri = data.getData();
            try {
                Log.d("image-tag", "start to decode selected image now...");
                InputStream input = getContentResolver().openInputStream(uri);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(input, null, options);
                int raw_width = options.outWidth;
                int raw_height = options.outHeight;
                int max = Math.max(raw_width, raw_height);
                int newWidth = raw_width;
                int newHeight = raw_height;
                int inSampleSize = 1;
                if(max > max_size) {
                    newWidth = raw_width / 2;
                    newHeight = raw_height / 2;
                    while((newWidth/inSampleSize) > max_size || (newHeight/inSampleSize) > max_size) {
                        inSampleSize *=2;
                    }
                }

                options.inSampleSize = inSampleSize;
                options.inJustDecodeBounds = false;
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                selectbp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);

                myImageView.setImageBitmap(selectbp);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void selectImage() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent,"选择图像..."), PICK_IMAGE_REQUEST);
    }
}

选择一张图像加载之后显示:
这里写图片描述

点击【处理】之后,通过调用OpenCV API实现了灰度转换
这里写图片描述

特别说明:这种方式调用OpenCV无需NKD以及安装OpenCV Manager。应该是广大Android开发人员最喜欢的一种方式。
免费环境搭建视频查看
OpenCV For Android 基础入门视频

要使用 JDK 21 编译 OpenCV 4.11.0 的 Android SDK,需要确保构建环境的兼容性,并正确配置 Android NDK 和 SDK。以下是详细的步骤和注意事项: ### 环境准备 1. **安装 JDK 21** 确保已安装 JDK 21,并设置 `JAVA_HOME` 环境变量指向 JDK 21 的安装目录。可以通过以下命令验证安装: ```bash java -version ``` 2. **安装 Android SDK 和 NDK** 使用 Android Studio 安装最新版本的 Android SDK 和 NDK(建议使用 NDK r25 或更高版本)。确保 `ANDROID_SDK_ROOT` 和 `ANDROID_NDK_ROOT` 环境变量已正确配置。 3. **安装 CMake 和构建工具** 确保安装了 CMake 3.22 或更高版本,并安装必要的构建工具(如 `ninja`)。 4. **获取 OpenCV 4.11.0 源码** 从 OpenCV 的 GitHub 仓库克隆或下载 OpenCV 4.11.0 的源码: ```bash git clone https://github.com/opencv/opencv.git cd opencv git checkout 4.11.0 ``` ### 构建 OpenCV Android SDK 1. **配置构建脚本** 在 OpenCV 源码目录中,进入 `opencv/platforms/android` 目录,并运行构建脚本 `build_sdk.py`: ```bash cd platforms/android python build_sdk.py --help ``` 该命令将显示可用的构建选项。 2. **执行构建命令** 使用以下命令开始构建 OpenCV Android SDK: ```bash python build_sdk.py --no-samples --build-root=build_opencv --output=opencv-android-sdk ../.. ``` 其中: - `--no-samples` 表示不构建示例代码。 - `--build-root` 指定中间构建文件的存储目录。 - `--output` 指定最终输出的 SDK 目录。 3. **验证构建结果** 构建完成后,生成的 Android SDK 将位于指定的输出目录中(如 `opencv-android-sdk`)。该目录包含 `sdk/native/jni`、`sdk/java` 等子目录,可用于集成到 Android 项目中。 ### 配置 Gradle 构建文件 1. **在 Android 项目中集成 OpenCV SDK** 将生成的 OpenCV SDK 复制到 Android 项目的 `app/libs` 目录中,并在 `build.gradle` 文件中添加依赖项: ```gradle android { ... sourceSets { main { jniLibs.srcDirs = ['libs'] } } } dependencies { implementation files('libs/opencv-android-sdk/sdk/java/opencv-java4110') } ``` 2. **配置 CMakeLists.txt(如果使用 C++ 代码)** 如果项目中包含 C++ 代码,确保在 `CMakeLists.txt` 中正确引用 OpenCV 的 JNI 库: ```cmake include_directories(${CMAKE_SOURCE_DIR}/../jni/opencv-android-sdk/sdk/native/jni/include) add_library(opencv_java4 SHARED IMPORTED) set_target_properties(opencv_java4 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jni/opencv-android-sdk/sdk/native/libs/${ANDROID_ABI}/libopencv_java4110.so) target_link_libraries(native-lib opencv_java4) ``` ### 注意事项 - **JDK 兼容性** OpenCV 的构建脚本通常使用 Python 编写,对 JDK 的版本要求较低。尽管如此,确保构建脚本与 JDK 21 的兼容性仍然非常重要。如果遇到兼容性问题,可以尝试更新 Python 脚本或使用兼容模式运行 JDK。 - **NDK 构建配置** 确保 `Android.mk` 文件中正确引用 OpenCV 的 JNI 库。例如: ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) OPENCVROOT:= /path/to/opencv-android-sdk OPENCV_CAMERA_MODULES:=on OPENCV_INSTALL_MODULES:=on OPENCV_LIB_TYPE:=SHARED include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk LOCAL_SRC_FILES := main.c LOCAL_LDLIBS += -llog LOCAL_MODULE := hello include $(BUILD_SHARED_LIBRARY) ``` - **测试 OpenCV 集成** 在 Android 项目中,确保可以正确加载 OpenCV 库并调用相关函数。例如: ```java static { System.loadLibrary("opencv_java4110"); System.loadLibrary("hello"); } ``` ### 示例代码 以下是一个简单的 JNI 函数调用示例: ```cpp #include <jni.h> #include <opencv2/core/core.hpp> extern "C" JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv *env, jobject /* this */) { cv::Mat mat = cv::Mat::eye(3, 3, CV_8UC1); return env->NewStringUTF("OpenCV Mat created successfully!"); } ``` ###
评论 32
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gloomyfish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值