【Android+OpenCV】Android Studio的安裝全過程+在Android Studio中配置OpenCV

版本:
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的整個過程,置於後續的使用和美化,需要進一步的學習。


十分有用的b站教程:
第一集
第二集

其餘參考文件(都沒能幫上啥忙):
android studio 使用 jni 編譯 opencv 完整實例 之 圖像邊緣檢測!從此在andrid中自由使用 圖像匹配、識別、檢測
opencv在android平臺下的開發【1】-android studio集成opencv-sdk
Android 接入 OpenCV庫的三種方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章