版本:
Android 3.5.2
SDK 28.0.2
opencv 3.4.10
ndk r16b
1、安装Android Studio 以及 OpenCV
1.1 下载安装包:
(1)去Android Studio中文社区下载android-studio-ide-191.5977832-windows.exe
(2)去OpenCV官网,下载OpenCV-3.4.10-android-sdk
(3)去NDK官网下载 android-ndk-r16b-windows-x86_64
1.2 安装Android Studio
双击android-studio-ide-191.5977832-windows.exe
开始安装,过程如下:
把两个都勾上,下一步:
改成自己的文件夹,注意路径中务必不能有空格:
直接下一步:
继续下一步:
点击finish,同时开启AS:
启动界面如下:
弹出如下报错框,正常,点击Cancel取消该框:
选Custom:
勾上,更改SDK位置,点next:
点finish:
出现如下界面,点击Configure按钮:
选择SDK Manager:
我的电脑内存8G,所选的默认虚拟机内存大小2G:
点击finish:
下载好了之后,点finish:
1.3 第一次新建工程项目
在下面这个界面里,点击第一项 Start a new Android Studio project
:
滑到最后,选择原生C++模板:
改名后,选择java模板,next:
修改为C++14,finish:
这里,正在下载gradle,如果网不好,可以叉掉整个界面,等会用离线方式下载gradle。
在gradle官网下载gradle-5.4.1-all.zip
:
下载好后,把压缩包文件gradle-5.4.1-all.zip
拷贝到文件夹,删除文件夹中原来的两个半成品文件,最后如图所示:
打开AS:
将左侧Android模式切换成Project模式,点击右侧小象按钮,开始解压…
此时可以做其他工作:
File—>Settings—>Appearance & Behavior—>System Settings—>取消勾选Reopen last project on startup(省的每次都打开最近项目,勾掉后,每次打开启动页面,进入选择页面而非项目页面)
做好了其他工作回来发现报错了:ERROR: Failed to install the following Android SDK packages as some licences have not been accepted.
解决办法:进入SDK的目录,在目录的地址栏D:\Android2\SDK\tools\bin
输入cmd,回车打开命令行终端,这里面有个windows批处理文件sdkmanager.bat
。运行下面的命令,然后就有一大堆的 license 等着你输入yes,统计了一下,总共要输入8个y:
sdkmanager --licenses
关闭命令行终端窗口,重新点击AS中的右上角小象图标。开始重新解压缩,解压缩完毕后是下面这样:
继续报错:ERROR: CMake ‘3.10.2’ was not found in PATH or by cmake.dir property.
报错原因是没有安装cmake工具,在如下位置安装即可:(File—>Settings)
等着下载结束,安装完成后,点finish。此时重新点小象按钮重新解压,还是会出错。关掉整个AS,重新打开项目,点击小象按钮,一切正常:
1.4 修改项目的NDK版本
官方给的版本过高r20,需要调整为r16
File—>Project Structure—>SDK Location—> 选择本地的NDK,然后点击Apply和OK。又开始一轮编译,等完成。
2、使用OpenCV在安卓端处理图片
参考牛人链接:OpenCV On Android最佳环境配置指南(Android Studio篇)
2.1 CMake文件
cmake_minimum_required(VERSION 3.4.1)
# ##################### OpenCV 环境 ############################
#设置OpenCV-android-sdk路径
set( OpenCV_DIR D:/AndroidData/opencv-3.4.10-android-sdk/OpenCV-android-sdk/sdk/native/jni )
find_package(OpenCV REQUIRED )
if(OpenCV_FOUND)
include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
else(OpenCV_FOUND)
message(FATAL_ERROR "OpenCV library not found")
endif(OpenCV_FOUND)
# ###################### 项目原生模块 ###########################
add_library( native-lib
SHARED
native-lib.cpp)
target_link_libraries( native-lib
${OpenCV_LIBS}
log
jnigraphics)
路径的修改参考的是本地OpenCV包中的以下位置:
2.2 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="show" />
<Button
android:id="@+id/process"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="process" />
</LinearLayout>
</RelativeLayout>
2.3 MainActivity.java
package com.example.opencvdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView imageView;
static {//加载so库
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
findViewById(R.id.show).setOnClickListener(this);
findViewById(R.id.process).setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.show) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat);
imageView.setImageBitmap(bitmap);
} else {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat);
getEdge(bitmap);
imageView.setImageBitmap(bitmap);
}
}
//获得Canny边缘
native void getEdge(Object bitmap);
}
这几个文件的修改顺序如下,其中,JAVA中,cat是张图片。
2.4 原生层操作
应用层写好了,现在开始原生层操作:
2.4.1 生成头文件
打开Android Studio下方Terminal
栏,输入cd app\src\main\java
(所有应用都一样,进入java文件夹即可),回车。然后输入javah -encoding UTF-8 包名.类名
,这里输入的是
javah -encoding UTF-8 com.example.opencv.MainActivity
回车后,将在app\src\main\java
目录下生成一个头文件,如下图所示,之后将该头文件移动到app\src\main\cpp
目录下。
2.4.2 native-lib.cpp
修改native-lib.cpp
内容,最终结果如下面代码所示:
#include "com_example_opencvdemo_MainActivity.h"
#include <android/bitmap.h>
#include <opencv2/opencv.hpp>
using namespace cv;
extern "C" JNIEXPORT void
JNICALL Java_com_demo_opencv_NativeActivity_getEdge
(JNIEnv *env, jobject obj, jobject bitmap) {
AndroidBitmapInfo info;
void *pixels;
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
Mat temp(info.height, info.width, CV_8UC4, pixels);
Mat gray;
cvtColor(temp, gray, COLOR_RGBA2GRAY);
Canny(gray, gray, 45, 75);
cvtColor(gray, temp, COLOR_GRAY2RGBA);
} else {
Mat temp(info.height, info.width, CV_8UC2, pixels);
Mat gray;
cvtColor(temp, gray, COLOR_RGB2GRAY);
Canny(gray, gray, 45, 75);
cvtColor(gray, temp, COLOR_GRAY2RGB);
}
AndroidBitmap_unlockPixels(env, bitmap);
}
2.4.3 build.gradle
修改app
下的build.gradle
,部分内容需要修改成:
...
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -frtti -fexceptions"
arguments "-DANDROID_STL=gnustl_shared"
}
}
...
完整build.gradle如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.opencvdemo"
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -frtti -fexceptions"
arguments "-DANDROID_STL=gnustl_shared"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
点击右上角sync now
,重新编译一下。
2.4.4 CMakeLists.txt(这里仅做展示,不要实践这个步骤)
编译完成后,为了增加兼容性,在已有的CMakeLists.txt
文件中,添加如下语句,增加兼容性:
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a") #增加兼容性
添加完后的完整CMakeLists.txt
文件:
cmake_minimum_required(VERSION 3.4.1)
# ##################### OpenCV 环境 ############################
#设置OpenCV-android-sdk路径
set( OpenCV_DIR D:/AndroidData/opencv-3.4.10-android-sdk/OpenCV-android-sdk/sdk/native/jni )
find_package(OpenCV REQUIRED )
if(OpenCV_FOUND)
include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
else(OpenCV_FOUND)
message(FATAL_ERROR "OpenCV library not found")
endif(OpenCV_FOUND)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a") #增加兼容性
# ###################### 项目原生模块 ###########################
add_library( native-lib
SHARED
native-lib.cpp)
target_link_libraries( native-lib
${OpenCV_LIBS}
log
jnigraphics)
有的时候,做的多了未必是好事,比如这里就是,加上这句看似能增加兼容性的代码,反而各种报错,我现在能力不足以解决这个问题,先放在这,后面在解决。
2.4.5 安装更多组件
Tools—>SDK Manager—>Appearance & Behavior–>System Settings—>Android SDK—>SDK Tools—>在右下角勾上Show Package Details—>选中:
Android SDK 28.0.2
NDK(Side By Side)16.1.4479499
CMake3.6.4111459
点击Apply,安装完成:
3 结果展示
运行程序,安装在真机上:点击show,出现喵喵小可爱!
点击处理按钮,出现喵喵小可爱的轮廓:
至此,完成在Android Studio中配置OpenCV的整个过程,置于后续的使用和美化,需要进一步的学习。
其余参考文件(都没能帮上啥忙):
android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测opencv在android平台下的开发【1】-android studio集成opencv-sdkAndroid 接入 OpenCV库的三种方式