Как запустить вывод Tensorflow-Lite в (Android Studio) NDK (C / C ++ API)? - PullRequest
0 голосов
/ 30 апреля 2020

Информация

  • Я построил модель Tensorflow (TF) из Keras и преобразовал ее в Tensorflow-Lite (TFL)
  • Я создал приложение Android в Android Studio и использовал API Java для запуска модели TFL
  • . В приложении Java я использовал библиотеку поддержки TFL (см. здесь ) и TensorFlow Lite AAR из JCenter. включив implementation 'org.tensorflow:tensorflow-lite:+' в мои build.gradle зависимости

Время вывода не так велико, так что теперь я хочу использовать TFL в NDK Android.

Так что я собрал точную копию приложения Java в NDK Studio 1145 *, и теперь я пытаюсь включить библиотеки TFL в проект. Я следовал TensorFlow-Lite Android гиду и создал библиотеку TFL локально (и получил файл AAR) и включил библиотеку в свой проект NDK в Android Studio.

Сейчас Я пытаюсь использовать библиотеку TFL в своем файле C ++, пытаясь #include это в коде, но я получаю сообщение об ошибке: cannot find tensorflow (или любое другое имя, которое я пытаюсь использовать, в соответствии с именем Я даю это в моем CMakeLists.txt файле).

Файлы

Приложение build.gradle :

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.ndk.tflite"
        minSdkVersion 28
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }

        ndk {
            abiFilters 'arm64-v8a'
        }

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    // tf lite
    aaptOptions {
        noCompress "tflite"
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    // tflite build
    compile(name:'tensorflow-lite', ext:'aar')

}

Project build. gradle :

buildscript {

    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.2'

    }
}

allprojects {
    repositories {
        google()
        jcenter()

        // native tflite
        flatDir {
            dirs 'libs'
        }

    }

}


task clean(type: Delete) {
    delete rootProject.buildDir
}

CMakeLists.txt :

cmake_minimum_required(VERSION 3.4.1)

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 )

add_library( # Sets the name of the library.
        tensorflow-lite

        # Sets the library as a shared library.
        SHARED

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

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 )


target_link_libraries( # Specifies the target library.
                       native-lib tensorflow-lite

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

native-lib. cpp:

#include <jni.h>
#include <string>

#include "tensorflow"

extern "C" JNIEXPORT jstring JNICALL
Java_com_xvu_f32c_1jni_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

class FlatBufferModel {
    // Build a model based on a file. Return a nullptr in case of failure.
    static std::unique_ptr<FlatBufferModel> BuildFromFile(
            const char* filename,
            ErrorReporter* error_reporter);

    // Build a model based on a pre-loaded flatbuffer. The caller retains
    // ownership of the buffer and should keep it alive until the returned object
    // is destroyed. Return a nullptr in case of failure.
    static std::unique_ptr<FlatBufferModel> BuildFromBuffer(
            const char* buffer,
            size_t buffer_size,
            ErrorReporter* error_reporter);
};

Progress

Я также попытался выполнить следующие действия:

но в моем случае я использовал Bazel для сборки библиотек TFL.

Пытаясь создать классификационную демонстрацию ( label_image ), мне удалось собрать ее и adb push для моего устройства, но при попытке запустить я получил следующую ошибку:

ERROR: Could not open './mobilenet_quant_v1_224.tflite'.
Failed to mmap model ./mobilenet_quant_v1_224.tflite
  • Я следовал Пост zimenglyu : попытка установить android_sdk_repository / android_ndk_repository в WORKSPACE получил меня ошибка: WORKSPACE:149:1: Cannot redefine repository after any load statement in the WORKSPACE file (for repository 'androidsdk'), и размещение этих операторов в разных местах приводило к одной и той же ошибке.
  • Я удалил эти изменения в WORKSPACE и продолжил работу с постом zimenglyu: я скомпилировал libtensorflowLite.so и отредактировал CMakeLists.txt, чтобы на файл libtensorflowLite.so была ссылка, но часть FlatBuffer была исключена. Проект Android успешно скомпилирован, но очевидных изменений не произошло, я все еще не могу включить библиотеки TFLite.

Пытаясь скомпилировать TFL, я добавил cc_binary к tensorflow/tensorflow/lite/BUILD ( следуя примеру label_image ):

cc_binary(
    name = "native-lib",
    srcs = [
        "native-lib.cpp",
    ],
    linkopts = tflite_experimental_runtime_linkopts() + select({
        "//tensorflow:android": [
            "-pie",
            "-lm",
        ],
        "//conditions:default": [],
    }),
    deps = [
        "//tensorflow/lite/c:common",
        "//tensorflow/lite:framework",
        "//tensorflow/lite:string_util",
        "//tensorflow/lite/delegates/nnapi:nnapi_delegate",
        "//tensorflow/lite/kernels:builtin_ops",
        "//tensorflow/lite/profiling:profiler",
        "//tensorflow/lite/tools/evaluation:utils",
    ] + select({
        "//tensorflow:android": [
            "//tensorflow/lite/delegates/gpu:delegate",
        ],
        "//tensorflow:android_arm64": [
            "//tensorflow/lite/delegates/gpu:delegate",
        ],
        "//conditions:default": [],
    }),
)

и пытаясь построить его для x86_64, и arm64-v8a я получаю сообщение об ошибке: cc_toolchain_suite rule @local_config_cc//:toolchain: cc_toolchain_suite '@local_config_cc//:toolchain' does not contain a toolchain for cpu 'x86_64'.

Проверка external/local_config_cc/BUILD (которая вызвала ошибку) в строке 47:

cc_toolchain_suite(
    name = "toolchain",
    toolchains = {
        "k8|compiler": ":cc-compiler-k8",
        "k8": ":cc-compiler-k8",
        "armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a",
        "armeabi-v7a": ":cc-compiler-armeabi-v7a",
    },
)

, и это только 2 cc_toolchain s, найденных. При поиске в репозитории "cc -compiler-" я обнаружил только " aarch64 ", который, как я предполагал, предназначен для 64-разрядного ARM, но ничего с "x86_64". Есть "x64_ windows", хотя - и я на Linux.

Попытка собрать с помощью aarch64 следующим образом:

bazel build -c opt --fat_apk_cpu=aarch64 --cpu=aarch64 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain //tensorflow/lite/java:tensorflow-lite

приводит к ошибке:

ERROR: /.../external/local_config_cc/BUILD:47:1: in cc_toolchain_suite rule @local_config_cc//:toolchain: cc_toolchain_suite '@local_config_cc//:toolchain' does not contain a toolchain for cpu 'aarch64'

Я смог собрать библиотеку для архитектуры x86_64 и включить ее в Android Studio - добавив -soname в конфигурацию сборки и используя полные пути в CMakeLists.txt, но не смог использовать библиотека (#include "..." например). Сборка для ARM все еще не удалась.

Вопрос

В моем приложении (Android Studio) я получаю ошибки (1) Can't resolve type 'ErrorReporter' и (2) cannot find tensorflow из native-lib.cpp file.

Как мне выполнить вывод TFL из NDK?

...