版本:
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模式,點擊右側小象按鈕,開始解壓剛剛下載的gradle壓縮包…
此時可以做其他工作(也可以不做,純看個人偏好):
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,再重新打開AS,打開剛剛的項目後,點擊小象按鈕,一切正常:
1.4 修改項目的NDK版本
官方給的版本過高r20,需要調整爲r16。
File—>Project Structure—>SDK Location—> 選擇本地的NDK,然後點擊Apply和OK。又開始一輪編譯,等完成。
2、使用OpenCV在安卓端處理圖片
參考牛人鏈接:OpenCV On Android最佳環境配置指南(Android Studio篇)
總共有這麼幾個文件需要修改,修改順序如下,其中,JAVA中,cat是張圖片。
2.1 CMakeLists.txt文件
直接複製下面的代碼替換原本CMakeLists.txt
文件的所有內容,將代碼中OpenCV的路徑修改爲你自己的路徑,路徑修改方法見這段代碼下面:
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路徑的修改,參考的是本地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);
}
2.4 原生層操作
應用層寫好了,現在開始原生層操作:
2.4.1 生成頭文件 並 剪切到cpp文件夾
打開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
目錄下。
將生成的這個.h頭文件從main/java
文件夾剪切到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"
}
}
...
app
中完整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-sdk
Android 接入 OpenCV庫的三種方式