真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

AndroidJNI開發(fā)調(diào)用Opencv的so庫-創(chuàng)新互聯(lián)

Android JNI 開發(fā) 調(diào)用Opencv 的so庫
  • Android JNI 開發(fā)
    • 簡介:
    • NDK 簡介
      • NDK 基礎(chǔ)概念
      • ABI 是什么
    • 在Android Studio中調(diào)用OpenCV的so庫
    • 補(bǔ)充圖文教程

成都創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)長葛,十載網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792Android JNI 開發(fā) 簡介:

JNI是Java Native Interface的縮寫,它提供了若干的API實(shí)現(xiàn)了Java和其他語言的通信(主要是C&C++)。從Java1.1開始,JNI標(biāo)準(zhǔn)成為Java平臺(tái)的一部分,它允許Java代碼和其他語言寫的代碼進(jìn)行交互。

這里是一篇關(guān)于JNI開發(fā)的基本知識(shí)的辨析,我覺得很不錯(cuò),講清楚了java,NDK, 安卓,JNI幾個(gè)的聯(lián)系與區(qū)別,但需要注意的是,這篇文章里主要講的是通過NDK來創(chuàng)建JNI調(diào)用,本文主要講的是通過cmake來完成JNI調(diào)用。但還是要做一下應(yīng)有的辨析。

NDK 簡介

這部分內(nèi)容參考了這里,在介紹 NDK 之前還是首推 Android 官方 NDK 文檔。
官方文檔分別從以下幾個(gè)方面介紹了 NDK

  • NDK 的基礎(chǔ)概念
  • 如何編譯 NDK 項(xiàng)目
  • ABI 是什么以及不同 CPU 指令集支持哪些 ABI
  • 如何使用您自己及其他預(yù)建的庫
NDK 基礎(chǔ)概念

首先先用簡單的話分別解釋下 JNI、NDK, 以及分別和 Android 開發(fā)、c/c++ 開發(fā)的配合。在解釋過程中會(huì)對(duì) Android.mk、Application.mk、ndk-build、CMake、CMakeList 這些常見名詞進(jìn)行掃盲。

JNI(Java Native Interface):Java本地接口。是為了方便Java調(diào)用c、c++等本地代碼所封裝的一層接口(也是一個(gè)標(biāo)準(zhǔn))。大家都知道,Java的優(yōu)點(diǎn)是跨平臺(tái),但是作為優(yōu)點(diǎn)的同時(shí),其在本地交互的時(shí)候就編程了缺點(diǎn)。Java的跨平臺(tái)特性導(dǎo)致其本地交互的能力不夠強(qiáng)大,一些和操作系統(tǒng)相關(guān)的特性Java無法完成,于是Java提供了jni專門用于和本地代碼交互,這樣就增強(qiáng)了Java語言的本地交互能力。

NDK(Native Development Kit) : 原生開發(fā)工具包,即幫助開發(fā)原生代碼的一系列工具,包括但不限于編譯工具、一些公共庫、開發(fā)IDE等。

NDK 工具包中提供了完整的一套將 c/c++ 代碼編譯成靜態(tài)/動(dòng)態(tài)庫的工具,而 Android.mk 和 Application.mk 你可以認(rèn)為是描述編譯參數(shù)和一些配置的文件。比如指定使用c++11還是c++14編譯,會(huì)引用哪些共享庫,并描述關(guān)系等,還會(huì)指定編譯的 abi。只有有了這些 NDK 中的編譯工具才能準(zhǔn)確的編譯 c/c++ 代碼。

ndk-build 文件是 Android NDK r4 中引入的一個(gè) shell 腳本。其用途是調(diào)用正確的 NDK 構(gòu)建腳本。其實(shí)最終還是會(huì)去調(diào)用 NDK 自己的編譯工具。

那 CMake 又是什么呢。脫離 Android 開發(fā)來看,c/c++ 的編譯文件在不同平臺(tái)是不一樣的。Unix 下會(huì)使用 makefile 文件編譯,Windows 下會(huì)使用 project 文件編譯。而 CMake 則是一個(gè)跨平臺(tái)的編譯工具,它并不會(huì)直接編譯出對(duì)象,而是根據(jù)自定義的語言規(guī)則(CMakeLists.txt)生成 對(duì)應(yīng) makefile 或 project 文件,然后再調(diào)用底層的編譯。

在Android Studio 2.2 之后,工具中增加了 CMake 的支持,你可以這么認(rèn)為,在 Android Studio 2.2 之后你有2種選擇來編譯你寫的 c/c++ 代碼。一個(gè)是 ndk-build + Android.mk + Application.mk 組合,另一個(gè)是 CMake + CMakeLists.txt 組合。這2個(gè)組合與Android代碼和c/c++代碼無關(guān),只是不同的構(gòu)建腳本和構(gòu)建命令。本篇文章主要會(huì)描述后者的組合。(也是Android現(xiàn)在主推的)

ABI 是什么

ABI(Application binary interface)應(yīng)用程序二進(jìn)制接口。不同的CPU 與指令集的每種組合都有定義的 ABI (應(yīng)用程序二進(jìn)制接口),一段程序只有遵循這個(gè)接口規(guī)范才能在該 CPU 上運(yùn)行,所以同樣的程序代碼為了兼容多個(gè)不同的CPU,需要為不同的 ABI 構(gòu)建不同的庫文件。當(dāng)然對(duì)于CPU來說,不同的架構(gòu)并不意味著一定互不兼容。

armeabi設(shè)備只兼容armeabi;
armeabi-v7a設(shè)備兼容armeabi-v7a、armeabi;
arm64-v8a設(shè)備兼容arm64-v8a、armeabi-v7a、armeabi;
X86設(shè)備兼容X86、armeabi;
X86_64設(shè)備兼容X86_64、X86、armeabi;
mips64設(shè)備兼容mips64、mips;
mips只兼容mips;
當(dāng)我們開發(fā) Android 應(yīng)用的時(shí)候,由于 Java 代碼運(yùn)行在虛擬機(jī)上,所以我們從來沒有關(guān)心過這方面的問題。但是當(dāng)我們開發(fā)或者使用原生代碼時(shí)就需要了解不同 ABI 以及為自己的程序選擇接入不同 ABI 的庫。(庫越多,包越大,所以要有選擇)

總結(jié)一下:
android 調(diào)用JNI 分為靜態(tài)調(diào)用與動(dòng)態(tài)調(diào)用(不論動(dòng)態(tài)還是靜態(tài)前提都是NDK環(huán)境已經(jīng)配置好的前提下)
一、靜態(tài)主要就是將c(.c)或者c++(cpp)的源文件直接加到項(xiàng)目中進(jìn)行調(diào)用,然后在CMakeLists.txt中進(jìn)行配置。
二、動(dòng)態(tài)調(diào)用
動(dòng)態(tài)調(diào)用使用已經(jīng)編譯好的動(dòng)態(tài)庫.so文件

在Android Studio中調(diào)用OpenCV的so庫

以下是創(chuàng)建具有Native OpenCV 支持的新 Android Studio 項(xiàng)目的步驟:

  1. 下載并安裝 Android Studio
  2. 安裝 NDK 和 CMake
  3. 創(chuàng)建一個(gè)新的 Native Android Studio 項(xiàng)目:
  • 從主菜單中選擇File ->New ->New Project...。

  • 單擊手機(jī)和平板選項(xiàng)卡,選擇Native C++,然后單擊下一步。

  • 選擇一個(gè)應(yīng)用程序名稱,選擇語言(Kotlin 或 Java),選擇最低 API 級(jí)別(此處為 28),然后選擇下一步。

  • 選擇 Toolchain default as C++ standard 并單擊 Finish。

  • 創(chuàng)建成功后,直接build運(yùn)行,手機(jī)界面出現(xiàn) Hello from C++

  • build后會(huì)生產(chǎn).so文件,一般在build->intermediates->cmake->debug->obj下,這里即為把本地的c++文件打包成了so庫

  1. 安裝 OpenCV Android 版本:
  • 下載 OpenCV 4.6.0 Android 版本或在 OpenCV 網(wǎng)站上下載最新可用的 Android 版本。
  • 解壓縮下載的文件并將 OpenCV-android-sdk 目錄放在您選擇的路徑上。
  1. 將 OpenCV Android SDK 作為模塊添加到您的項(xiàng)目中:
  • 打開 setting.gradle 文件并附加這兩行。
include ':opencv'
project(':opencv').projectDir = new File(opencvsdk + '/sdk')
  • 打開 gradle.properties 文件并附加以下行。不要忘記為您的機(jī)器使用剛才下載到本地的正確的 OpenCV Android SDK 路徑。
opencvsdk=/Users/Example/Downloads/OpenCV-android-sdk
  • 新增Module:File ->New ->Improt Module
    選擇opencv庫的路徑:D:\你的路徑\OpenCV-android-sdk\sdk
  • 打開 build.gradle 文件并將implementation project(path: ':opencv')添加到依賴項(xiàng)部分:
dependencies {...
    implementation project(path: ':opencv')
}

或者可以點(diǎn)擊File ->Project Structure ->Dependencies ->app ->+ ->Module Dependency ->opencv會(huì)自動(dòng)在build.gradle中添加依賴

  • 點(diǎn)擊File ->Sync Project with Gradle Files.
  1. 將以下配置添加到應(yīng)用程序 build.gradle 文件中:
  • android ->defaultConfig ->externalNativeBuild ->cmake部分,放入以下三行:
cppFlags "-frtti -fexceptions"
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
arguments "-DOpenCV_DIR=" + opencvsdk + "/sdk/native"
  1. 將以下配置添加到 CMakeLists.txt 文件:
  • add_library之前,添加以下三行:
include_directories(${OpenCV_DIR}/jni/include)
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)
  • target_link_libraries指令參數(shù)中,添加以下行:
lib_opencv
  • 最終的CMake文件如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# 引入頭文件搜索路徑,這里找到的是opencv2
# OpenCV_DIR在app的buildgradle設(shè)置的
include_directories(${OpenCV_DIR}/jni/include)
# 起名字為lib_opencv,SHARED,動(dòng)態(tài)庫 STATIC,靜態(tài)庫, IMPORTED外部導(dǎo)入
add_library( lib_opencv SHARED IMPORTED )
# 二進(jìn)制文件ANDROID_ABI也在app的buildgradle設(shè)置的
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

# 本地庫
add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

# link本地庫和動(dòng)態(tài)鏈接庫
target_link_libraries( # Specifies the target library.
        native-lib

        lib_opencv

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

如果你對(duì)其中的具體細(xì)節(jié)有不清楚的地方,這里的附錄是CMake的使用

  1. 將以下權(quán)限添加到您的 AndroidManifest.xml 文件中,這里主要是相機(jī)的使用權(quán)限。
  1. 創(chuàng)建您的 MainActivity :
    參考代碼:
package com.example.nativeopencvandroidtemplate;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import android.util.Log;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;

import org.jetbrains.annotations.NotNull;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;

public class MainActivity extends Activity implements CvCameraViewListener2 {private static final String TAG = "MainActivity";
    private static final int CAMERA_PERMISSION_REQUEST = 1;

    private CameraBridgeViewBase mOpenCvCameraView;

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {@Override
        public void onManagerConnected(int status) {if (status == LoaderCallbackInterface.SUCCESS) {Log.i(TAG, "OpenCV loaded successfully");

                // Load native library after(!) OpenCV initialization
                System.loadLibrary("native-lib");

                mOpenCvCameraView.enableView();
            } else {super.onManagerConnected(status);
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        // Permissions for Android 6+
        ActivityCompat.requestPermissions(
                this,
                new String[]{Manifest.permission.CAMERA},
                CAMERA_PERMISSION_REQUEST
        );

        setContentView(R.layout.activity_main);

        mOpenCvCameraView = findViewById(R.id.main_surface);

        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);

        mOpenCvCameraView.setCvCameraViewListener(this);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NotNull String[] permissions, @NotNull int[] grantResults) {if (requestCode == CAMERA_PERMISSION_REQUEST) {if (grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {mOpenCvCameraView.setCameraPermissionGranted();
            } else {String message = "Camera permission was not granted";
                Log.e(TAG, message);
                Toast.makeText(this, message, Toast.LENGTH_LONG).show();
            }
        } else {Log.e(TAG, "Unexpected permission request");
        }
    }

    @Override
    public void onPause() {super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume() {super.onResume();
        if (!OpenCVLoader.initDebug()) {Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, mLoaderCallback);
        } else {Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    @Override
    public void onDestroy() {super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onCameraViewStarted(int width, int height) {}

    @Override
    public void onCameraViewStopped() {}

    @Override
    public Mat onCameraFrame(CvCameraViewFrame frame) {// get current camera frame as OpenCV Mat object
        Mat mat = frame.gray();

        // native call to process current camera frame
        adaptiveThresholdFromJNI(mat.getNativeObjAddr());

        // return processed frame for live preview
        return mat;
    }

    private native void adaptiveThresholdFromJNI(long mat);
}
  1. 創(chuàng)建您的 activity_main.xml :
  1. 在 native-lib.cpp 中添加原生代碼:
#include#include#include#include#define TAG "NativeLib"

using namespace std;
using namespace cv;

extern "C" {void JNICALL
Java_com_example_nativeopencvandroidtemplate_MainActivity_adaptiveThresholdFromJNI(JNIEnv *env,
                                                                                   jobject instance,
                                                                                   jlong matAddr) {// get Mat from raw address
    Mat &mat = *(Mat *) matAddr;

    clock_t begin = clock();

    cv::adaptiveThreshold(mat, mat, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 21, 5);

    // log computation time to Android Logcat
    double totalTime = double(clock() - begin) / CLOCKS_PER_SEC;
    __android_log_print(ANDROID_LOG_INFO, TAG, "adaptiveThreshold computation time = %f seconds\n",
                        totalTime);
}
}
補(bǔ)充圖文教程

關(guān)于圖文教程,網(wǎng)上有很多,但是隨著opencv和android studio的更新,有一些已經(jīng)不適用了,所以上面主要寫的著重于Cmakelist.txt的配置,build.gradle對(duì)于cmake配置,gradle.properties的配置以及它們之間的關(guān)系,學(xué)會(huì)了之后就不是照搬,可以舉一反三。

具體的圖文教程我覺得也有一篇不錯(cuò)的,但是肯定會(huì)遇到問題,所以在那邊遇到問題的時(shí)候可以到這邊來參考。

OpenCV 在 Android Studio 的使用教程

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站欄目:AndroidJNI開發(fā)調(diào)用Opencv的so庫-創(chuàng)新互聯(lián)
網(wǎng)址分享:http://weahome.cn/article/cooesc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部