car classification init
|
@ -0,0 +1,83 @@
|
||||||
|
# MindSpore
|
||||||
|
build/
|
||||||
|
mindspore/lib
|
||||||
|
app/src/main/assets/model/
|
||||||
|
app/src/main/cpp/mindspore-lite-*
|
||||||
|
output
|
||||||
|
*.ir
|
||||||
|
mindspore/ccsrc/schema/inner/*
|
||||||
|
|
||||||
|
# Cmake files
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
CMakeCache.txt
|
||||||
|
Makefile
|
||||||
|
cmake-build-debug
|
||||||
|
|
||||||
|
# Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Static libraries
|
||||||
|
*.la
|
||||||
|
*.lai
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Protocol buffers
|
||||||
|
*_pb2.py
|
||||||
|
*.pb.h
|
||||||
|
*.pb.cc
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
|
||||||
|
# Editor
|
||||||
|
.vscode
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Cquery
|
||||||
|
.cquery_cached_index/
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# Ctags and cscope
|
||||||
|
tags
|
||||||
|
TAGS
|
||||||
|
CTAGS
|
||||||
|
GTAGS
|
||||||
|
GRTAGS
|
||||||
|
GSYMS
|
||||||
|
GPATH
|
||||||
|
cscope.*
|
||||||
|
|
||||||
|
# Python files
|
||||||
|
*__pycache__*
|
||||||
|
.pytest_cache
|
||||||
|
|
||||||
|
# Mac files
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
# Test results
|
||||||
|
test_temp_summary_event_file/
|
||||||
|
*.dot
|
||||||
|
*.dat
|
||||||
|
*.svg
|
||||||
|
*.perf
|
||||||
|
*.info
|
||||||
|
*.ckpt
|
||||||
|
*.shp
|
||||||
|
*.pkl
|
||||||
|
.clangd
|
||||||
|
mindspore/version.py
|
||||||
|
mindspore/default_config.py
|
||||||
|
mindspore/.commit_id
|
||||||
|
onnx.proto
|
||||||
|
mindspore/ccsrc/onnx.proto
|
||||||
|
|
||||||
|
# Android
|
||||||
|
local.properties
|
||||||
|
.gradle
|
||||||
|
sdk/build
|
||||||
|
sdk/.cxx
|
||||||
|
app/.cxx
|
|
@ -0,0 +1,6 @@
|
||||||
|
/build
|
||||||
|
!/libs/
|
||||||
|
!/src/main/assets/model/
|
||||||
|
!/src/main/cpp/mindspore-lite-1.0.1-runtime-arm64-cpu/
|
||||||
|
|
||||||
|
/src/main/cpp/mindspore-lite-1.0.1-runtime-arm64-cpu/
|
|
@ -0,0 +1,86 @@
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI})
|
||||||
|
|
||||||
|
set(MINDSPORELITE_VERSION mindspore-lite-1.0.1-runtime-arm64-cpu)
|
||||||
|
|
||||||
|
# ============== Set MindSpore Dependencies. =============
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/third_party/flatbuffers/include)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION})
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include/ir/dtype)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include/schema)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/minddata/include)
|
||||||
|
|
||||||
|
add_library(mindspore-lite SHARED IMPORTED )
|
||||||
|
add_library(minddata-lite SHARED IMPORTED )
|
||||||
|
add_library(libmindspore-lite-fp16 SHARED IMPORTED )
|
||||||
|
|
||||||
|
set_target_properties(mindspore-lite PROPERTIES IMPORTED_LOCATION
|
||||||
|
${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/lib/libmindspore-lite.so)
|
||||||
|
set_target_properties(minddata-lite PROPERTIES IMPORTED_LOCATION
|
||||||
|
${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/minddata/lib/libminddata-lite.so)
|
||||||
|
set_target_properties(libmindspore-lite-fp16 PROPERTIES IMPORTED_LOCATION
|
||||||
|
${CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/lib/libmindspore-lite-fp16.so)
|
||||||
|
# --------------- MindSpore Lite set End. --------------------
|
||||||
|
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
file(GLOB_RECURSE cpp_src "src/main/cpp/*.cpp" "src/main/cpp/*.h")
|
||||||
|
|
||||||
|
add_library( # Sets the name of the library.
|
||||||
|
mlkit-label-MS
|
||||||
|
|
||||||
|
# Sets the library as a shared library.
|
||||||
|
SHARED
|
||||||
|
|
||||||
|
# Provides a relative path to your source file(s).
|
||||||
|
${cpp_src})
|
||||||
|
|
||||||
|
|
||||||
|
# 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 )
|
||||||
|
|
||||||
|
|
||||||
|
find_library( jnigraphics-lib jnig·raphics )
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
add_definitions(-DMNN_USE_LOGCAT)
|
||||||
|
target_link_libraries( # Specifies the target library.
|
||||||
|
mlkit-label-MS
|
||||||
|
|
||||||
|
# --- mindspore ---
|
||||||
|
minddata-lite
|
||||||
|
mindspore-lite
|
||||||
|
libmindspore-lite-fp16
|
||||||
|
|
||||||
|
# --- other dependencies.---
|
||||||
|
-ljnigraphics
|
||||||
|
android
|
||||||
|
|
||||||
|
# Links the target library to the log library
|
||||||
|
${log-lib}
|
||||||
|
)
|
|
@ -0,0 +1,78 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 30
|
||||||
|
buildToolsVersion "30.0.1"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.mindspore.classificationforcar"
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 30
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
arguments "-DANDROID_STL=c++_shared"
|
||||||
|
cppFlags "-std=c++17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ndk {
|
||||||
|
abiFilters 'arm64-v8a'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aaptOptions {
|
||||||
|
noCompress '.so', 'ms'
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path file('CMakeLists.txt')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ndkVersion '21.3.6528147'
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packagingOptions {
|
||||||
|
pickFirst 'lib/arm64-v8a/libmlkit-label-MS.so'
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Before gradle build.
|
||||||
|
// To download some necessary libraries.
|
||||||
|
apply from: 'download.gradle'
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
|
// implementation project(path: ':sdk')
|
||||||
|
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
|
|
||||||
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
|
androidTestImplementation 'com.android.support.test:rules:1.0.2'
|
||||||
|
androidTestImplementation 'com.google.truth:truth:1.0.1'
|
||||||
|
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||||
|
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/**
|
||||||
|
* To download necessary library from HuaWei server.
|
||||||
|
* Including mindspore-lite .so file, minddata-lite .so file and model file.
|
||||||
|
* The libraries can be downloaded manually.
|
||||||
|
*/
|
||||||
|
def targetMindSporeInclude = "src/main/cpp/"
|
||||||
|
def mindsporeLite_Version = "mindspore-lite-1.0.1-runtime-arm64-cpu"
|
||||||
|
|
||||||
|
def targetModelFile = "src/main/assets/model/mobilenetv2.ms"
|
||||||
|
def mindSporeLibrary_arm64 = "src/main/cpp/${mindsporeLite_Version}.tar.gz"
|
||||||
|
|
||||||
|
def modelDownloadUrl = "https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite/mobilenetv2.ms"
|
||||||
|
def mindsporeLiteDownloadUrl = "https://ms-release.obs.cn-north-4.myhuaweicloud.com/1.0.1/lite/android_aarch64/${mindsporeLite_Version}.tar.gz"
|
||||||
|
|
||||||
|
def cleantargetMindSporeInclude = "src/main/cpp"
|
||||||
|
|
||||||
|
task cleanCmakeCache(type: Delete) {
|
||||||
|
delete '.cxx/cmake/debug'
|
||||||
|
delete '.cxx/cmake/release'
|
||||||
|
}
|
||||||
|
|
||||||
|
task downloadModelFile(type: DownloadUrlTask) {
|
||||||
|
doFirst {
|
||||||
|
println "Downloading ${modelDownloadUrl}"
|
||||||
|
}
|
||||||
|
sourceUrl = "${modelDownloadUrl}"
|
||||||
|
target = file("${targetModelFile}")
|
||||||
|
}
|
||||||
|
|
||||||
|
task downloadMindSporeLibrary(type: DownloadUrlTask) {
|
||||||
|
doFirst {
|
||||||
|
println "Downloading ${mindsporeLiteDownloadUrl}"
|
||||||
|
}
|
||||||
|
sourceUrl = "${mindsporeLiteDownloadUrl}"
|
||||||
|
target = file("${mindSporeLibrary_arm64}")
|
||||||
|
}
|
||||||
|
|
||||||
|
task unzipMindSporeInclude(type: Copy, dependsOn: 'downloadMindSporeLibrary') {
|
||||||
|
doFirst {
|
||||||
|
println "Unzipping ${mindSporeLibrary_arm64}"
|
||||||
|
}
|
||||||
|
from tarTree(resources.gzip("${mindSporeLibrary_arm64}"))
|
||||||
|
into "${targetMindSporeInclude}"
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanUnusedmindsporeFiles(type: Delete, dependsOn: ['unzipMindSporeInclude']) {
|
||||||
|
delete fileTree("${cleantargetMindSporeInclude}").matching {
|
||||||
|
include "*.tar.gz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Using preBuild to download mindspore library and model file.
|
||||||
|
* Run before gradle build.
|
||||||
|
*/
|
||||||
|
if (file("src/main/cpp/${mindsporeLite_Version}/lib/libmindspore-lite.so").exists()){
|
||||||
|
downloadMindSporeLibrary.enabled = false
|
||||||
|
unzipMindSporeInclude.enabled = false
|
||||||
|
cleanUnusedmindsporeFiles.enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file("src/main/assets/model/mobilenetv2.ms").exists()){
|
||||||
|
downloadModelFile.enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
preBuild.dependsOn cleanCmakeCache
|
||||||
|
preBuild.dependsOn downloadModelFile
|
||||||
|
preBuild.dependsOn downloadMindSporeLibrary
|
||||||
|
preBuild.dependsOn unzipMindSporeInclude
|
||||||
|
preBuild.dependsOn cleanUnusedmindsporeFiles
|
||||||
|
|
||||||
|
class DownloadUrlTask extends DefaultTask {
|
||||||
|
@Input
|
||||||
|
String sourceUrl
|
||||||
|
|
||||||
|
@OutputFile
|
||||||
|
File target
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
void download() {
|
||||||
|
ant.get(src: sourceUrl, dest: target)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||||
|
assertEquals("com.mindspore.classification", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="com.mindspore.classificationforcar"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEM" />
|
||||||
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
<activity android:name="com.mindspore.classificationforcar.widget.MainActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name="com.mindspore.classificationforcar.widget.CameraActivity"
|
||||||
|
android:screenOrientation="portrait">
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="com.mindspore.classificationforcar.fileprovider"
|
||||||
|
android:exported="false"
|
||||||
|
tools:replace="android:authorities"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
tools:replace="android:resource"
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths" />
|
||||||
|
</provider>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
|
@ -0,0 +1,812 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android/bitmap.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
#include "include/errorcode.h"
|
||||||
|
#include "include/ms_tensor.h"
|
||||||
|
#include "ImageMindSporeNetnative.h"
|
||||||
|
#include "MSNetWork.h"
|
||||||
|
#include "lite_cv/lite_mat.h"
|
||||||
|
#include "lite_cv/image_process.h"
|
||||||
|
#include "mindspore-lite-1.0.1-runtime-arm64-cpu/minddata/include/lite_cv/lite_mat.h"
|
||||||
|
|
||||||
|
using mindspore::dataset::LiteMat;
|
||||||
|
using mindspore::dataset::LPixelType;
|
||||||
|
using mindspore::dataset::LDataType;
|
||||||
|
#define MS_PRINT(format, ...) __android_log_print(ANDROID_LOG_INFO, "MSJNI", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
static const int RET_CATEGORY_SUM = 410;
|
||||||
|
static const char *labels_name_map[RET_CATEGORY_SUM] = {
|
||||||
|
"Herd",
|
||||||
|
"Safari",
|
||||||
|
"Bangle",
|
||||||
|
"Cushion",
|
||||||
|
"Countertop",
|
||||||
|
"Prom",
|
||||||
|
"Branch",
|
||||||
|
"Sports",
|
||||||
|
"Sky",
|
||||||
|
"Community",
|
||||||
|
"Wheel",
|
||||||
|
"Cola",
|
||||||
|
"Tuxedo",
|
||||||
|
"Flowerpot",
|
||||||
|
"Team",
|
||||||
|
"Computer",
|
||||||
|
"Unicycle",
|
||||||
|
"Brig",
|
||||||
|
"Aerospace engineering",
|
||||||
|
"Scuba diving",
|
||||||
|
"Goggles",
|
||||||
|
"Fruit",
|
||||||
|
"Badminton",
|
||||||
|
"Horse",
|
||||||
|
"Sunglasses",
|
||||||
|
"Fun",
|
||||||
|
"Prairie",
|
||||||
|
"Poster",
|
||||||
|
"Flag",
|
||||||
|
"Speedboat",
|
||||||
|
"Eyelash",
|
||||||
|
"Veil",
|
||||||
|
"Mobile phone",
|
||||||
|
"Wheelbarrow",
|
||||||
|
"Saucer",
|
||||||
|
"Leather",
|
||||||
|
"Drawer",
|
||||||
|
"Paper",
|
||||||
|
"Pier",
|
||||||
|
"Waterfowl",
|
||||||
|
"Tights",
|
||||||
|
"Rickshaw",
|
||||||
|
"Vegetable",
|
||||||
|
"Handrail",
|
||||||
|
"Ice",
|
||||||
|
"Metal",
|
||||||
|
"Flower",
|
||||||
|
"Wing",
|
||||||
|
"Silverware",
|
||||||
|
"Event",
|
||||||
|
"Skyline",
|
||||||
|
"Money",
|
||||||
|
"Comics",
|
||||||
|
"Handbag",
|
||||||
|
"Porcelain",
|
||||||
|
"Rodeo",
|
||||||
|
"Curtain",
|
||||||
|
"Tile",
|
||||||
|
"Human mouth",
|
||||||
|
"Army",
|
||||||
|
"Menu",
|
||||||
|
"Boat",
|
||||||
|
"Snowboarding",
|
||||||
|
"Cairn terrier",
|
||||||
|
"Net",
|
||||||
|
"Pasteles",
|
||||||
|
"Cup",
|
||||||
|
"Rugby",
|
||||||
|
"Pho",
|
||||||
|
"Cap",
|
||||||
|
"Human hair",
|
||||||
|
"Surfing",
|
||||||
|
"Loveseat",
|
||||||
|
"Museum",
|
||||||
|
"Shipwreck",
|
||||||
|
"Trunk (Tree)",
|
||||||
|
"Plush",
|
||||||
|
"Monochrome",
|
||||||
|
"Volcano",
|
||||||
|
"Rock",
|
||||||
|
"Pillow",
|
||||||
|
"Presentation",
|
||||||
|
"Nebula",
|
||||||
|
"Subwoofer",
|
||||||
|
"Lake",
|
||||||
|
"Sledding",
|
||||||
|
"Bangs",
|
||||||
|
"Tablecloth",
|
||||||
|
"Necklace",
|
||||||
|
"Swimwear",
|
||||||
|
"Standing",
|
||||||
|
"Jeans",
|
||||||
|
"Carnival",
|
||||||
|
"Softball",
|
||||||
|
"Centrepiece",
|
||||||
|
"Skateboarder",
|
||||||
|
"Cake",
|
||||||
|
"Dragon",
|
||||||
|
"Aurora",
|
||||||
|
"Skiing",
|
||||||
|
"Bathroom",
|
||||||
|
"Dog",
|
||||||
|
"Needlework",
|
||||||
|
"Umbrella",
|
||||||
|
"Church",
|
||||||
|
"Fire",
|
||||||
|
"Piano",
|
||||||
|
"Denim",
|
||||||
|
"Bridle",
|
||||||
|
"Cabinetry",
|
||||||
|
"Lipstick",
|
||||||
|
"Ring",
|
||||||
|
"Television",
|
||||||
|
"Roller",
|
||||||
|
"Seal",
|
||||||
|
"Concert",
|
||||||
|
"Product",
|
||||||
|
"News",
|
||||||
|
"Fast food",
|
||||||
|
"Horn (Animal)",
|
||||||
|
"Tattoo",
|
||||||
|
"Bird",
|
||||||
|
"Bridegroom",
|
||||||
|
"Love",
|
||||||
|
"Helmet",
|
||||||
|
"Dinosaur",
|
||||||
|
"Icing",
|
||||||
|
"Miniature",
|
||||||
|
"Tire",
|
||||||
|
"Toy",
|
||||||
|
"Icicle",
|
||||||
|
"Jacket",
|
||||||
|
"Coffee",
|
||||||
|
"Mosque",
|
||||||
|
"Rowing",
|
||||||
|
"Wetsuit",
|
||||||
|
"Camping",
|
||||||
|
"Underwater",
|
||||||
|
"Christmas",
|
||||||
|
"Gelato",
|
||||||
|
"Whiteboard",
|
||||||
|
"Field",
|
||||||
|
"Ragdoll",
|
||||||
|
"Construction",
|
||||||
|
"Lampshade",
|
||||||
|
"Palace",
|
||||||
|
"Meal",
|
||||||
|
"Factory",
|
||||||
|
"Cage",
|
||||||
|
"Clipper (Boat)",
|
||||||
|
"Gymnastics",
|
||||||
|
"Turtle",
|
||||||
|
"Human foot",
|
||||||
|
"Marriage",
|
||||||
|
"Web page",
|
||||||
|
"Human beard",
|
||||||
|
"Fog",
|
||||||
|
"Wool",
|
||||||
|
"Cappuccino",
|
||||||
|
"Lighthouse",
|
||||||
|
"Lego",
|
||||||
|
"Sparkler",
|
||||||
|
"Sari",
|
||||||
|
"Model",
|
||||||
|
"Temple",
|
||||||
|
"Beanie",
|
||||||
|
"Building",
|
||||||
|
"Waterfall",
|
||||||
|
"Penguin",
|
||||||
|
"Cave",
|
||||||
|
"Stadium",
|
||||||
|
"Smile",
|
||||||
|
"Human hand",
|
||||||
|
"Park",
|
||||||
|
"Desk",
|
||||||
|
"Shetland sheepdog",
|
||||||
|
"Bar",
|
||||||
|
"Eating",
|
||||||
|
"Neon",
|
||||||
|
"Dalmatian",
|
||||||
|
"Crocodile",
|
||||||
|
"Wakeboarding",
|
||||||
|
"Longboard",
|
||||||
|
"Road",
|
||||||
|
"Race",
|
||||||
|
"Kitchen",
|
||||||
|
"Odometer",
|
||||||
|
"Cliff",
|
||||||
|
"Fiction",
|
||||||
|
"School",
|
||||||
|
"Interaction",
|
||||||
|
"Bullfighting",
|
||||||
|
"Boxer",
|
||||||
|
"Gown",
|
||||||
|
"Aquarium",
|
||||||
|
"Superhero",
|
||||||
|
"Pie",
|
||||||
|
"Asphalt",
|
||||||
|
"Surfboard",
|
||||||
|
"Cheeseburger",
|
||||||
|
"Screenshot",
|
||||||
|
"Supper",
|
||||||
|
"Laugh",
|
||||||
|
"Lunch",
|
||||||
|
"Party ",
|
||||||
|
"Glacier",
|
||||||
|
"Bench",
|
||||||
|
"Grandparent",
|
||||||
|
"Sink",
|
||||||
|
"Pomacentridae",
|
||||||
|
"Blazer",
|
||||||
|
"Brick",
|
||||||
|
"Space",
|
||||||
|
"Backpacking",
|
||||||
|
"Stuffed toy",
|
||||||
|
"Sushi",
|
||||||
|
"Glitter",
|
||||||
|
"Bonfire",
|
||||||
|
"Castle",
|
||||||
|
"Marathon",
|
||||||
|
"Pizza",
|
||||||
|
"Beach",
|
||||||
|
"Human ear",
|
||||||
|
"Racing",
|
||||||
|
"Sitting",
|
||||||
|
"Iceberg",
|
||||||
|
"Shelf",
|
||||||
|
"Vehicle",
|
||||||
|
"Pop music",
|
||||||
|
"Playground",
|
||||||
|
"Clown",
|
||||||
|
"Car",
|
||||||
|
"Rein",
|
||||||
|
"Fur",
|
||||||
|
"Musician",
|
||||||
|
"Casino",
|
||||||
|
"Baby",
|
||||||
|
"Alcohol",
|
||||||
|
"Strap",
|
||||||
|
"Reef",
|
||||||
|
"Balloon",
|
||||||
|
"Outerwear",
|
||||||
|
"Cathedral",
|
||||||
|
"Competition",
|
||||||
|
"Joker",
|
||||||
|
"Blackboard",
|
||||||
|
"Bunk bed",
|
||||||
|
"Bear",
|
||||||
|
"Moon",
|
||||||
|
"Archery",
|
||||||
|
"Polo",
|
||||||
|
"River",
|
||||||
|
"Fishing",
|
||||||
|
"Ferris wheel",
|
||||||
|
"Mortarboard",
|
||||||
|
"Bracelet",
|
||||||
|
"Flesh",
|
||||||
|
"Statue",
|
||||||
|
"Farm",
|
||||||
|
"Desert",
|
||||||
|
"Chain",
|
||||||
|
"Aircraft",
|
||||||
|
"Textile",
|
||||||
|
"Hot dog",
|
||||||
|
"Knitting",
|
||||||
|
"Singer",
|
||||||
|
"Juice",
|
||||||
|
"Circus",
|
||||||
|
"Chair",
|
||||||
|
"Musical instrument",
|
||||||
|
"Room",
|
||||||
|
"Crochet",
|
||||||
|
"Sailboat",
|
||||||
|
"Newspaper",
|
||||||
|
"Santa claus",
|
||||||
|
"Swamp",
|
||||||
|
"Skyscraper",
|
||||||
|
"Skin",
|
||||||
|
"Rocket",
|
||||||
|
"Aviation",
|
||||||
|
"Airliner",
|
||||||
|
"Garden",
|
||||||
|
"Ruins",
|
||||||
|
"Storm",
|
||||||
|
"Glasses",
|
||||||
|
"Balance",
|
||||||
|
"Nail (Body part)",
|
||||||
|
"Rainbow",
|
||||||
|
"Soil ",
|
||||||
|
"Vacation ",
|
||||||
|
"Moustache",
|
||||||
|
"Doily",
|
||||||
|
"Food",
|
||||||
|
"Bride ",
|
||||||
|
"Cattle",
|
||||||
|
"Pocket",
|
||||||
|
"Infrastructure",
|
||||||
|
"Train",
|
||||||
|
"Gerbil",
|
||||||
|
"Fireworks",
|
||||||
|
"Pet",
|
||||||
|
"Dam",
|
||||||
|
"Crew",
|
||||||
|
"Couch",
|
||||||
|
"Bathing",
|
||||||
|
"Quilting",
|
||||||
|
"Motorcycle",
|
||||||
|
"Butterfly",
|
||||||
|
"Sled",
|
||||||
|
"Watercolor paint",
|
||||||
|
"Rafting",
|
||||||
|
"Monument",
|
||||||
|
"Lightning",
|
||||||
|
"Sunset",
|
||||||
|
"Bumper",
|
||||||
|
"Shoe",
|
||||||
|
"Waterskiing",
|
||||||
|
"Sneakers",
|
||||||
|
"Tower",
|
||||||
|
"Insect",
|
||||||
|
"Pool",
|
||||||
|
"Placemat",
|
||||||
|
"Airplane",
|
||||||
|
"Plant",
|
||||||
|
"Jungle",
|
||||||
|
"Armrest",
|
||||||
|
"Duck",
|
||||||
|
"Dress",
|
||||||
|
"Tableware",
|
||||||
|
"Petal",
|
||||||
|
"Bus",
|
||||||
|
"Hanukkah",
|
||||||
|
"Forest",
|
||||||
|
"Hat",
|
||||||
|
"Barn",
|
||||||
|
"Tubing",
|
||||||
|
"Snorkeling",
|
||||||
|
"Cool",
|
||||||
|
"Cookware and bakeware",
|
||||||
|
"Cycling",
|
||||||
|
"Swing (Seat)",
|
||||||
|
"Muscle",
|
||||||
|
"Cat",
|
||||||
|
"Skateboard",
|
||||||
|
"Star",
|
||||||
|
"Toe",
|
||||||
|
"Junk",
|
||||||
|
"Bicycle",
|
||||||
|
"Bedroom",
|
||||||
|
"Person",
|
||||||
|
"Sand",
|
||||||
|
"Canyon",
|
||||||
|
"Tie",
|
||||||
|
"Twig",
|
||||||
|
"Sphynx",
|
||||||
|
"Supervillain",
|
||||||
|
"Nightclub",
|
||||||
|
"Ranch",
|
||||||
|
"Pattern",
|
||||||
|
"Shorts",
|
||||||
|
"Himalayan",
|
||||||
|
"Wall",
|
||||||
|
"Leggings",
|
||||||
|
"Windsurfing",
|
||||||
|
"Deejay",
|
||||||
|
"Dance",
|
||||||
|
"Van",
|
||||||
|
"Bento",
|
||||||
|
"Sleep",
|
||||||
|
"Wine",
|
||||||
|
"Picnic",
|
||||||
|
"Leisure",
|
||||||
|
"Dune",
|
||||||
|
"Crowd",
|
||||||
|
"Kayak",
|
||||||
|
"Ballroom",
|
||||||
|
"Selfie",
|
||||||
|
"Graduation",
|
||||||
|
"Frigate",
|
||||||
|
"Mountain",
|
||||||
|
"Dude",
|
||||||
|
"Windshield",
|
||||||
|
"Skiff",
|
||||||
|
"Class",
|
||||||
|
"Scarf",
|
||||||
|
"Bull",
|
||||||
|
"Soccer",
|
||||||
|
"Bag",
|
||||||
|
"Basset hound",
|
||||||
|
"Tractor",
|
||||||
|
"Swimming",
|
||||||
|
"Running",
|
||||||
|
"Track",
|
||||||
|
"Helicopter",
|
||||||
|
"Pitch",
|
||||||
|
"Clock",
|
||||||
|
"Song",
|
||||||
|
"Jersey",
|
||||||
|
"Stairs",
|
||||||
|
"Flap",
|
||||||
|
"Jewellery",
|
||||||
|
"Bridge",
|
||||||
|
"Cuisine",
|
||||||
|
"Bread",
|
||||||
|
"Caving",
|
||||||
|
"Shell",
|
||||||
|
"Wreath",
|
||||||
|
"Roof",
|
||||||
|
"Cookie",
|
||||||
|
"Canoe"};
|
||||||
|
|
||||||
|
static float g_thres_map[RET_CATEGORY_SUM] = {
|
||||||
|
0.23, 0.03, 0.10, 0.13, 0.03,
|
||||||
|
0.10, 0.06, 0.09, 0.09, 0.05,
|
||||||
|
0.01, 0.04, 0.01, 0.27, 0.05,
|
||||||
|
0.16, 0.01, 0.16, 0.04, 0.13,
|
||||||
|
0.09, 0.18, 0.10, 0.65, 0.08,
|
||||||
|
0.04, 0.08, 0.01, 0.05, 0.20,
|
||||||
|
0.01, 0.16, 0.10, 0.10, 0.10,
|
||||||
|
0.02, 0.24, 0.08, 0.10, 0.53,
|
||||||
|
0.07, 0.05, 0.07, 0.27, 0.02,
|
||||||
|
0.01, 0.71, 0.01, 0.06, 0.06,
|
||||||
|
0.03, 0.96, 0.03, 0.94, 0.05,
|
||||||
|
0.03, 0.14, 0.09, 0.03, 0.11,
|
||||||
|
0.50, 0.16, 0.07, 0.07, 0.06,
|
||||||
|
0.07, 0.08, 0.10, 0.29, 0.03,
|
||||||
|
0.05, 0.11, 0.03, 0.03, 0.03,
|
||||||
|
0.01, 0.11, 0.07, 0.03, 0.49,
|
||||||
|
0.12, 0.30, 0.10, 0.15, 0.02,
|
||||||
|
0.06, 0.17, 0.01, 0.04, 0.07,
|
||||||
|
0.06, 0.02, 0.19, 0.20, 0.14,
|
||||||
|
0.35, 0.15, 0.01, 0.10, 0.13,
|
||||||
|
0.43, 0.11, 0.12, 0.32, 0.01,
|
||||||
|
0.22, 0.51, 0.02, 0.04, 0.14,
|
||||||
|
0.04, 0.35, 0.35, 0.01, 0.54,
|
||||||
|
0.04, 0.02, 0.03, 0.02, 0.38,
|
||||||
|
0.13, 0.19, 0.06, 0.01, 0.02,
|
||||||
|
0.06, 0.03, 0.04, 0.01, 0.10,
|
||||||
|
0.01, 0.07, 0.07, 0.07, 0.33,
|
||||||
|
0.08, 0.04, 0.06, 0.07, 0.07,
|
||||||
|
0.11, 0.02, 0.32, 0.48, 0.14,
|
||||||
|
0.01, 0.01, 0.04, 0.05, 0.04,
|
||||||
|
0.16, 0.50, 0.11, 0.03, 0.04,
|
||||||
|
0.02, 0.55, 0.17, 0.13, 0.84,
|
||||||
|
0.18, 0.03, 0.16, 0.02, 0.06,
|
||||||
|
0.03, 0.11, 0.96, 0.36, 0.68,
|
||||||
|
0.02, 0.08, 0.02, 0.01, 0.03,
|
||||||
|
0.05, 0.14, 0.09, 0.06, 0.03,
|
||||||
|
0.20, 0.15, 0.62, 0.03, 0.10,
|
||||||
|
0.08, 0.02, 0.02, 0.06, 0.03,
|
||||||
|
0.04, 0.01, 0.10, 0.05, 0.04,
|
||||||
|
0.02, 0.07, 0.03, 0.32, 0.11,
|
||||||
|
0.03, 0.02, 0.03, 0.01, 0.03,
|
||||||
|
0.03, 0.25, 0.20, 0.19, 0.03,
|
||||||
|
0.11, 0.03, 0.02, 0.03, 0.15,
|
||||||
|
0.14, 0.06, 0.11, 0.03, 0.02,
|
||||||
|
0.02, 0.52, 0.03, 0.02, 0.02,
|
||||||
|
0.02, 0.09, 0.56, 0.01, 0.22,
|
||||||
|
0.01, 0.48, 0.14, 0.10, 0.08,
|
||||||
|
0.73, 0.39, 0.09, 0.10, 0.85,
|
||||||
|
0.31, 0.03, 0.05, 0.01, 0.01,
|
||||||
|
0.01, 0.10, 0.28, 0.02, 0.03,
|
||||||
|
0.04, 0.03, 0.07, 0.14, 0.20,
|
||||||
|
0.10, 0.01, 0.05, 0.37, 0.12,
|
||||||
|
0.04, 0.44, 0.04, 0.26, 0.08,
|
||||||
|
0.07, 0.27, 0.10, 0.03, 0.01,
|
||||||
|
0.03, 0.16, 0.41, 0.16, 0.34,
|
||||||
|
0.04, 0.30, 0.04, 0.05, 0.18,
|
||||||
|
0.33, 0.03, 0.21, 0.03, 0.04,
|
||||||
|
0.22, 0.01, 0.04, 0.02, 0.01,
|
||||||
|
0.06, 0.02, 0.08, 0.87, 0.11,
|
||||||
|
0.15, 0.05, 0.14, 0.09, 0.08,
|
||||||
|
0.22, 0.09, 0.07, 0.06, 0.06,
|
||||||
|
0.05, 0.43, 0.70, 0.03, 0.07,
|
||||||
|
0.06, 0.07, 0.14, 0.04, 0.01,
|
||||||
|
0.03, 0.05, 0.65, 0.06, 0.04,
|
||||||
|
0.23, 0.06, 0.75, 0.10, 0.01,
|
||||||
|
0.63, 0.41, 0.09, 0.01, 0.01,
|
||||||
|
0.18, 0.10, 0.03, 0.01, 0.05,
|
||||||
|
0.13, 0.18, 0.03, 0.23, 0.01,
|
||||||
|
0.04, 0.03, 0.38, 0.90, 0.21,
|
||||||
|
0.18, 0.10, 0.48, 0.08, 0.46,
|
||||||
|
0.03, 0.01, 0.02, 0.03, 0.10,
|
||||||
|
0.01, 0.09, 0.01, 0.01, 0.01,
|
||||||
|
0.10, 0.41, 0.01, 0.06, 0.75,
|
||||||
|
0.08, 0.01, 0.01, 0.08, 0.21,
|
||||||
|
0.06, 0.02, 0.05, 0.02, 0.05,
|
||||||
|
0.09, 0.12, 0.03, 0.06, 0.11,
|
||||||
|
0.03, 0.01, 0.01, 0.06, 0.84,
|
||||||
|
0.04, 0.81, 0.39, 0.02, 0.29,
|
||||||
|
0.77, 0.07, 0.06, 0.22, 0.23,
|
||||||
|
0.23, 0.01, 0.02, 0.13, 0.04,
|
||||||
|
0.19, 0.04, 0.08, 0.27, 0.09,
|
||||||
|
0.06, 0.01, 0.03, 0.21, 0.04,
|
||||||
|
};
|
||||||
|
|
||||||
|
char *ImageCreateLocalModelBuffer(JNIEnv *env, jobject modelBuffer) {
|
||||||
|
jbyte *modelAddr = static_cast<jbyte *>(env->GetDirectBufferAddress(modelBuffer));
|
||||||
|
int modelLen = static_cast<int>(env->GetDirectBufferCapacity(modelBuffer));
|
||||||
|
char *buffer(new char[modelLen]);
|
||||||
|
memcpy(buffer, modelAddr, modelLen);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To process the result of mindspore inference.
|
||||||
|
* @param msOutputs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string ImageProcessRunnetResult(const int RET_CATEGORY_SUM, const char *const labels_name_map[],
|
||||||
|
std::unordered_map<std::string, mindspore::tensor::MSTensor *> msOutputs) {
|
||||||
|
// Get the branch of the model output.
|
||||||
|
// Use iterators to get map elements.
|
||||||
|
std::unordered_map<std::string, mindspore::tensor::MSTensor *>::iterator iter;
|
||||||
|
iter = msOutputs.begin();
|
||||||
|
|
||||||
|
// The mobilenetv2.ms model output just one branch.
|
||||||
|
auto outputTensor = iter->second;
|
||||||
|
|
||||||
|
int tensorNum = outputTensor->ElementsNum();
|
||||||
|
MS_PRINT("Number of tensor elements:%d", tensorNum);
|
||||||
|
|
||||||
|
// Get a pointer to the first score.
|
||||||
|
float *temp_scores = static_cast<float *>(outputTensor->MutableData());
|
||||||
|
float scores[RET_CATEGORY_SUM];
|
||||||
|
for (int i = 0; i < RET_CATEGORY_SUM; ++i) {
|
||||||
|
scores[i] = temp_scores[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const float unifiedThre = 0.5;
|
||||||
|
const float probMax = 1.0;
|
||||||
|
for (size_t i = 0; i < RET_CATEGORY_SUM; ++i) {
|
||||||
|
float threshold = g_thres_map[i];
|
||||||
|
float tmpProb = scores[i];
|
||||||
|
if (tmpProb < threshold) {
|
||||||
|
tmpProb = tmpProb / threshold * unifiedThre;
|
||||||
|
} else {
|
||||||
|
tmpProb = (tmpProb - threshold) / (probMax - threshold) * unifiedThre + unifiedThre;
|
||||||
|
}
|
||||||
|
scores[i] = tmpProb;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < RET_CATEGORY_SUM; ++i) {
|
||||||
|
if (scores[i] > 0.5) {
|
||||||
|
MS_PRINT("MindSpore scores[%d] : [%f]", i, scores[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Score for each category.
|
||||||
|
// Converted to text information that needs to be displayed in the APP.
|
||||||
|
std::string categoryScore = "";
|
||||||
|
for (int i = 0; i < RET_CATEGORY_SUM; ++i) {
|
||||||
|
categoryScore += labels_name_map[i];
|
||||||
|
categoryScore += ":";
|
||||||
|
std::string score_str = std::to_string(scores[i]);
|
||||||
|
categoryScore += score_str;
|
||||||
|
categoryScore += ";";
|
||||||
|
}
|
||||||
|
return categoryScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImageBitmapToLiteMat(JNIEnv *env, const jobject &srcBitmap, LiteMat *lite_mat) {
|
||||||
|
bool ret = false;
|
||||||
|
AndroidBitmapInfo info;
|
||||||
|
void *pixels = nullptr;
|
||||||
|
LiteMat &lite_mat_bgr = *lite_mat;
|
||||||
|
AndroidBitmap_getInfo(env, srcBitmap, &info);
|
||||||
|
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
|
||||||
|
MS_PRINT("Image Err, Request RGBA");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AndroidBitmap_lockPixels(env, srcBitmap, &pixels);
|
||||||
|
if (info.stride == info.width * 4) {
|
||||||
|
ret = InitFromPixel(reinterpret_cast<const unsigned char *>(pixels),
|
||||||
|
LPixelType::RGBA2RGB, LDataType::UINT8,
|
||||||
|
info.width, info.height, lite_mat_bgr);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("Init From RGBA error");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned char *pixels_ptr = new unsigned char[info.width * info.height * 4];
|
||||||
|
unsigned char *ptr = pixels_ptr;
|
||||||
|
unsigned char *data = reinterpret_cast<unsigned char *>(pixels);
|
||||||
|
for (int i = 0; i < info.height; i++) {
|
||||||
|
memcpy(ptr, data, info.width * 4);
|
||||||
|
ptr += info.width * 4;
|
||||||
|
data += info.stride;
|
||||||
|
}
|
||||||
|
ret = InitFromPixel(reinterpret_cast<const unsigned char *>(pixels_ptr),
|
||||||
|
LPixelType::RGBA2RGB, LDataType::UINT8,
|
||||||
|
info.width, info.height, lite_mat_bgr);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("Init From RGBA error");
|
||||||
|
}
|
||||||
|
delete[] (pixels_ptr);
|
||||||
|
}
|
||||||
|
AndroidBitmap_unlockPixels(env, srcBitmap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImagePreProcessImageData(const LiteMat &lite_mat_bgr, LiteMat *lite_norm_mat_ptr) {
|
||||||
|
bool ret = false;
|
||||||
|
LiteMat lite_mat_resize;
|
||||||
|
LiteMat &lite_norm_mat_cut = *lite_norm_mat_ptr;
|
||||||
|
ret = ResizeBilinear(lite_mat_bgr, lite_mat_resize, 256, 256);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("ResizeBilinear error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LiteMat lite_mat_convert_float;
|
||||||
|
ret = ConvertTo(lite_mat_resize, lite_mat_convert_float, 1.0 / 255.0);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("ConvertTo error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LiteMat lite_mat_cut;
|
||||||
|
ret = Crop(lite_mat_convert_float, lite_mat_cut, 16, 16, 224, 224);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("Crop error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<float> means = {0.485, 0.456, 0.406};
|
||||||
|
std::vector<float> stds = {0.229, 0.224, 0.225};
|
||||||
|
SubStractMeanNormalize(lite_mat_cut, lite_norm_mat_cut, means, stds);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Java layer reads the model into MappedByteBuffer or ByteBuffer to load the model.
|
||||||
|
*/
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
Java_com_mindspore_classificationforcar_gallery_classify_ImageTrackingMobile_loadModel(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jobject model_buffer,
|
||||||
|
jint num_thread) {
|
||||||
|
if (nullptr == model_buffer) {
|
||||||
|
MS_PRINT("error, buffer is nullptr!");
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
jlong bufferLen = env->GetDirectBufferCapacity(model_buffer);
|
||||||
|
if (0 == bufferLen) {
|
||||||
|
MS_PRINT("error, bufferLen is 0!");
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *modelBuffer = ImageCreateLocalModelBuffer(env, model_buffer);
|
||||||
|
if (modelBuffer == nullptr) {
|
||||||
|
MS_PRINT("modelBuffer create failed!");
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To create a mindspore network inference environment.
|
||||||
|
void **labelEnv = new void *;
|
||||||
|
MSNetWork *labelNet = new MSNetWork;
|
||||||
|
*labelEnv = labelNet;
|
||||||
|
|
||||||
|
mindspore::lite::Context *context = new mindspore::lite::Context;
|
||||||
|
context->thread_num_ = num_thread;
|
||||||
|
|
||||||
|
labelNet->CreateSessionMS(modelBuffer, bufferLen, context);
|
||||||
|
delete context;
|
||||||
|
|
||||||
|
if (labelNet->session() == nullptr) {
|
||||||
|
MS_PRINT("MindSpore create session failed!.");
|
||||||
|
delete labelNet;
|
||||||
|
delete labelEnv;
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model_buffer != nullptr) {
|
||||||
|
env->DeleteLocalRef(model_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (jlong) labelEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After the inference environment is successfully created,
|
||||||
|
* sending a picture to the model and run inference.
|
||||||
|
*/
|
||||||
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
|
Java_com_mindspore_classificationforcar_gallery_classify_ImageTrackingMobile_runNet(JNIEnv *env,
|
||||||
|
jclass type,
|
||||||
|
jlong netEnv,
|
||||||
|
jobject srcBitmap) {
|
||||||
|
LiteMat lite_mat_bgr, lite_norm_mat_cut;
|
||||||
|
|
||||||
|
if (!ImageBitmapToLiteMat(env, srcBitmap, &lite_mat_bgr)) {
|
||||||
|
MS_PRINT("ImageBitmapToLiteMat error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!ImagePreProcessImageData(lite_mat_bgr, &lite_norm_mat_cut)) {
|
||||||
|
MS_PRINT("ImagePreProcessImageData error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImgDims inputDims;
|
||||||
|
inputDims.channel = lite_norm_mat_cut.channel_;
|
||||||
|
inputDims.width = lite_norm_mat_cut.width_;
|
||||||
|
inputDims.height = lite_norm_mat_cut.height_;
|
||||||
|
|
||||||
|
// Get the mindsore inference environment which created in loadModel().
|
||||||
|
void **labelEnv = reinterpret_cast<void **>(netEnv);
|
||||||
|
if (labelEnv == nullptr) {
|
||||||
|
MS_PRINT("MindSpore error, labelEnv is a nullptr.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MSNetWork *labelNet = static_cast<MSNetWork *>(*labelEnv);
|
||||||
|
|
||||||
|
auto mSession = labelNet->session();
|
||||||
|
if (mSession == nullptr) {
|
||||||
|
MS_PRINT("MindSpore error, Session is a nullptr.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MS_PRINT("MindSpore get session.");
|
||||||
|
|
||||||
|
auto msInputs = mSession->GetInputs();
|
||||||
|
if (msInputs.size() == 0) {
|
||||||
|
MS_PRINT("MindSpore error, msInputs.size() equals 0.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
auto inTensor = msInputs.front();
|
||||||
|
|
||||||
|
float *dataHWC = reinterpret_cast<float *>(lite_norm_mat_cut.data_ptr_);
|
||||||
|
// Copy dataHWC to the model input tensor.
|
||||||
|
memcpy(inTensor->MutableData(), dataHWC,
|
||||||
|
inputDims.channel * inputDims.width * inputDims.height * sizeof(float));
|
||||||
|
|
||||||
|
// After the model and image tensor data is loaded, run inference.
|
||||||
|
auto status = mSession->RunGraph();
|
||||||
|
|
||||||
|
if (status != mindspore::lite::RET_OK) {
|
||||||
|
MS_PRINT("MindSpore run net error.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mindspore inference results.
|
||||||
|
* Return the map of output node name and MindSpore Lite MSTensor.
|
||||||
|
*/
|
||||||
|
auto names = mSession->GetOutputTensorNames();
|
||||||
|
std::unordered_map<std::string, mindspore::tensor::MSTensor *> msOutputs;
|
||||||
|
for (const auto &name : names) {
|
||||||
|
auto temp_dat = mSession->GetOutputByTensorName(name);
|
||||||
|
msOutputs.insert(std::pair<std::string, mindspore::tensor::MSTensor *>{name, temp_dat});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string resultStr = ImageProcessRunnetResult(::RET_CATEGORY_SUM,
|
||||||
|
::labels_name_map, msOutputs);
|
||||||
|
|
||||||
|
const char *resultCharData = resultStr.c_str();
|
||||||
|
return (env)->NewStringUTF(resultCharData);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_mindspore_classificationforcar_gallery_classify_ImageTrackingMobile_unloadModel(JNIEnv *env,
|
||||||
|
jclass type,
|
||||||
|
jlong netEnv) {
|
||||||
|
MS_PRINT("MindSpore release net.");
|
||||||
|
void **labelEnv = reinterpret_cast<void **>(netEnv);
|
||||||
|
if (labelEnv == nullptr) {
|
||||||
|
MS_PRINT("MindSpore error, labelEnv is a nullptr.");
|
||||||
|
}
|
||||||
|
MSNetWork *labelNet = static_cast<MSNetWork *>(*labelEnv);
|
||||||
|
|
||||||
|
labelNet->ReleaseNets();
|
||||||
|
|
||||||
|
return (jboolean) true;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
|
||||||
|
#define IMAGE_MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MSNetWork.h"
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include "include/errorcode.h"
|
||||||
|
|
||||||
|
#define MS_PRINT(format, ...) __android_log_print(ANDROID_LOG_INFO, "MSJNI", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
MSNetWork::MSNetWork(void) : session_(nullptr), model_(nullptr) {}
|
||||||
|
|
||||||
|
MSNetWork::~MSNetWork(void) {}
|
||||||
|
|
||||||
|
void MSNetWork::CreateSessionMS(char *modelBuffer, size_t bufferLen, mindspore::lite::Context *ctx) {
|
||||||
|
session_ = mindspore::session::LiteSession::CreateSession(ctx);
|
||||||
|
if (session_ == nullptr) {
|
||||||
|
MS_PRINT("Create Session failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile model.
|
||||||
|
model_ = mindspore::lite::Model::Import(modelBuffer, bufferLen);
|
||||||
|
if (model_ == nullptr) {
|
||||||
|
ReleaseNets();
|
||||||
|
MS_PRINT("Import model failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = session_->CompileGraph(model_);
|
||||||
|
if (ret != mindspore::lite::RET_OK) {
|
||||||
|
ReleaseNets();
|
||||||
|
MS_PRINT("CompileGraph failed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MSNetWork::ReleaseNets(void) {
|
||||||
|
if (model_ != nullptr) {
|
||||||
|
model_->Free();
|
||||||
|
delete model_;
|
||||||
|
model_ = nullptr;
|
||||||
|
}
|
||||||
|
if (session_ != nullptr) {
|
||||||
|
delete session_;
|
||||||
|
session_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MSNETWORK_H
|
||||||
|
#define MSNETWORK_H
|
||||||
|
|
||||||
|
#include <context.h>
|
||||||
|
#include <lite_session.h>
|
||||||
|
#include <model.h>
|
||||||
|
#include <errorcode.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
struct ImgDims {
|
||||||
|
int channel = 0;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*struct SessIterm {
|
||||||
|
std::shared_ptr<mindspore::session::LiteSession> sess = nullptr;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
class MSNetWork {
|
||||||
|
public:
|
||||||
|
MSNetWork();
|
||||||
|
|
||||||
|
~MSNetWork();
|
||||||
|
|
||||||
|
void CreateSessionMS(char *modelBuffer, size_t bufferLen, mindspore::lite::Context *ctx);
|
||||||
|
|
||||||
|
void ReleaseNets(void);
|
||||||
|
|
||||||
|
mindspore::session::LiteSession *session() const { return session_; }
|
||||||
|
private:
|
||||||
|
mindspore::session::LiteSession *session_;
|
||||||
|
mindspore::lite::Model *model_;
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,304 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android/bitmap.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
#include "include/errorcode.h"
|
||||||
|
#include "include/ms_tensor.h"
|
||||||
|
#include "MindSporeNetnative.h"
|
||||||
|
#include "MSNetWork.h"
|
||||||
|
#include "lite_cv/lite_mat.h"
|
||||||
|
#include "lite_cv/image_process.h"
|
||||||
|
|
||||||
|
using mindspore::dataset::LiteMat;
|
||||||
|
using mindspore::dataset::LPixelType;
|
||||||
|
using mindspore::dataset::LDataType;
|
||||||
|
#define MS_PRINT(format, ...) __android_log_print(ANDROID_LOG_INFO, "MSJNI", format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
static const int RET_CAR_DETAILED_SUM = 10;
|
||||||
|
static const char *labels_name_car_detailed_map[RET_CAR_DETAILED_SUM] = {
|
||||||
|
{"大客车"},
|
||||||
|
{"出租车"},
|
||||||
|
{"中小型货车"},
|
||||||
|
{"小轿车"},
|
||||||
|
{"面包车"},
|
||||||
|
{"越野车"},
|
||||||
|
{"SUV"},
|
||||||
|
{"卡车"},
|
||||||
|
{"赛车"},
|
||||||
|
{"消防车"},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char *CreateLocalModelBuffer(JNIEnv *env, jobject modelBuffer) {
|
||||||
|
jbyte *modelAddr = static_cast<jbyte *>(env->GetDirectBufferAddress(modelBuffer));
|
||||||
|
int modelLen = static_cast<int>(env->GetDirectBufferCapacity(modelBuffer));
|
||||||
|
char *buffer(new char[modelLen]);
|
||||||
|
memcpy(buffer, modelAddr, modelLen);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To process the result of mindspore inference.
|
||||||
|
* @param msOutputs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
std::string ProcessRunnetResult(const int RET_CATEGORY_SUM, const char *const labels_name_map[],
|
||||||
|
std::unordered_map<std::string, mindspore::tensor::MSTensor *> msOutputs) {
|
||||||
|
// Get the branch of the model output.
|
||||||
|
// Use iterators to get map elements.
|
||||||
|
std::unordered_map<std::string, mindspore::tensor::MSTensor *>::iterator iter;
|
||||||
|
iter = msOutputs.begin();
|
||||||
|
|
||||||
|
// The mobilenetv2.ms model output just one branch.
|
||||||
|
auto outputTensor = iter->second;
|
||||||
|
|
||||||
|
// Get a pointer to the first score.
|
||||||
|
float *temp_scores = static_cast<float *>(outputTensor->MutableData());
|
||||||
|
float max = 0.0;
|
||||||
|
int maxIndex = 0;
|
||||||
|
for (int i = 0; i < RET_CAR_DETAILED_SUM; ++i) {
|
||||||
|
if (temp_scores[i] > max) {
|
||||||
|
max = temp_scores[i];
|
||||||
|
maxIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Score for each category.
|
||||||
|
// Converted to text information that needs to be displayed in the APP.
|
||||||
|
std::string categoryScore = "";
|
||||||
|
categoryScore += labels_name_map[maxIndex];
|
||||||
|
return categoryScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BitmapToLiteMat(JNIEnv *env, const jobject &srcBitmap, LiteMat *lite_mat) {
|
||||||
|
bool ret = false;
|
||||||
|
AndroidBitmapInfo info;
|
||||||
|
void *pixels = nullptr;
|
||||||
|
LiteMat &lite_mat_bgr = *lite_mat;
|
||||||
|
AndroidBitmap_getInfo(env, srcBitmap, &info);
|
||||||
|
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
|
||||||
|
MS_PRINT("Image Err, Request RGBA");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AndroidBitmap_lockPixels(env, srcBitmap, &pixels);
|
||||||
|
if (info.stride == info.width * 4) {
|
||||||
|
ret = InitFromPixel(reinterpret_cast<const unsigned char *>(pixels),
|
||||||
|
LPixelType::RGBA2RGB, LDataType::UINT8,
|
||||||
|
info.width, info.height, lite_mat_bgr);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("Init From RGBA error");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned char *pixels_ptr = new unsigned char[info.width * info.height * 4];
|
||||||
|
unsigned char *ptr = pixels_ptr;
|
||||||
|
unsigned char *data = reinterpret_cast<unsigned char *>(pixels);
|
||||||
|
for (int i = 0; i < info.height; i++) {
|
||||||
|
memcpy(ptr, data, info.width * 4);
|
||||||
|
ptr += info.width * 4;
|
||||||
|
data += info.stride;
|
||||||
|
}
|
||||||
|
ret = InitFromPixel(reinterpret_cast<const unsigned char *>(pixels_ptr),
|
||||||
|
LPixelType::RGBA2RGB, LDataType::UINT8,
|
||||||
|
info.width, info.height, lite_mat_bgr);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("Init From RGBA error");
|
||||||
|
}
|
||||||
|
delete[] (pixels_ptr);
|
||||||
|
}
|
||||||
|
AndroidBitmap_unlockPixels(env, srcBitmap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreProcessImageData(const LiteMat &lite_mat_bgr, LiteMat *lite_norm_mat_ptr) {
|
||||||
|
bool ret = false;
|
||||||
|
LiteMat lite_mat_resize;
|
||||||
|
LiteMat &lite_norm_mat_cut = *lite_norm_mat_ptr;
|
||||||
|
ret = ResizeBilinear(lite_mat_bgr, lite_mat_resize, 256, 256);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("ResizeBilinear error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LiteMat lite_mat_convert_float;
|
||||||
|
ret = ConvertTo(lite_mat_resize, lite_mat_convert_float, 1.0 / 255.0);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("ConvertTo error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LiteMat lite_mat_cut;
|
||||||
|
ret = Crop(lite_mat_convert_float, lite_mat_cut, 16, 16, 224, 224);
|
||||||
|
if (!ret) {
|
||||||
|
MS_PRINT("Crop error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<float> means = {0.485, 0.456, 0.406};
|
||||||
|
std::vector<float> stds = {0.229, 0.224, 0.225};
|
||||||
|
SubStractMeanNormalize(lite_mat_cut, lite_norm_mat_cut, means, stds);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Java layer reads the model into MappedByteBuffer or ByteBuffer to load the model.
|
||||||
|
*/
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
Java_com_mindspore_classificationforcar_gallery_classify_TrackingMobile_loadModel(JNIEnv *env,
|
||||||
|
jobject thiz,
|
||||||
|
jobject model_buffer,
|
||||||
|
jint num_thread) {
|
||||||
|
if (nullptr == model_buffer) {
|
||||||
|
MS_PRINT("error, buffer is nullptr!");
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
jlong bufferLen = env->GetDirectBufferCapacity(model_buffer);
|
||||||
|
if (0 == bufferLen) {
|
||||||
|
MS_PRINT("error, bufferLen is 0!");
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *modelBuffer = CreateLocalModelBuffer(env, model_buffer);
|
||||||
|
if (modelBuffer == nullptr) {
|
||||||
|
MS_PRINT("modelBuffer create failed!");
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To create a mindspore network inference environment.
|
||||||
|
void **labelEnv = new void *;
|
||||||
|
MSNetWork *labelNet = new MSNetWork;
|
||||||
|
*labelEnv = labelNet;
|
||||||
|
|
||||||
|
mindspore::lite::Context *context = new mindspore::lite::Context;
|
||||||
|
context->thread_num_ = num_thread;
|
||||||
|
|
||||||
|
labelNet->CreateSessionMS(modelBuffer, bufferLen, context);
|
||||||
|
delete context;
|
||||||
|
|
||||||
|
if (labelNet->session() == nullptr) {
|
||||||
|
MS_PRINT("MindSpore create session failed!.");
|
||||||
|
delete labelNet;
|
||||||
|
delete labelEnv;
|
||||||
|
return (jlong) nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model_buffer != nullptr) {
|
||||||
|
env->DeleteLocalRef(model_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (jlong) labelEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After the inference environment is successfully created,
|
||||||
|
* sending a picture to the model and run inference.
|
||||||
|
*/
|
||||||
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
|
Java_com_mindspore_classificationforcar_gallery_classify_TrackingMobile_runNet(JNIEnv *env, jclass type,
|
||||||
|
jlong netEnv,
|
||||||
|
jobject srcBitmap) {
|
||||||
|
LiteMat lite_mat_bgr, lite_norm_mat_cut;
|
||||||
|
|
||||||
|
if (!BitmapToLiteMat(env, srcBitmap, &lite_mat_bgr)) {
|
||||||
|
MS_PRINT("BitmapToLiteMat error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PreProcessImageData(lite_mat_bgr, &lite_norm_mat_cut)) {
|
||||||
|
MS_PRINT("PreProcessImageData error");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImgDims inputDims;
|
||||||
|
inputDims.channel = lite_norm_mat_cut.channel_;
|
||||||
|
inputDims.width = lite_norm_mat_cut.width_;
|
||||||
|
inputDims.height = lite_norm_mat_cut.height_;
|
||||||
|
|
||||||
|
// Get the mindsore inference environment which created in loadModel().
|
||||||
|
void **labelEnv = reinterpret_cast<void **>(netEnv);
|
||||||
|
if (labelEnv == nullptr) {
|
||||||
|
MS_PRINT("MindSpore error, labelEnv is a nullptr.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MSNetWork *labelNet = static_cast<MSNetWork *>(*labelEnv);
|
||||||
|
|
||||||
|
auto mSession = labelNet->session();
|
||||||
|
if (mSession == nullptr) {
|
||||||
|
MS_PRINT("MindSpore error, Session is a nullptr.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MS_PRINT("MindSpore get session.");
|
||||||
|
|
||||||
|
auto msInputs = mSession->GetInputs();
|
||||||
|
if (msInputs.size() == 0) {
|
||||||
|
MS_PRINT("MindSpore error, msInputs.size() equals 0.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
auto inTensor = msInputs.front();
|
||||||
|
|
||||||
|
float *dataHWC = reinterpret_cast<float *>(lite_norm_mat_cut.data_ptr_);
|
||||||
|
// Copy dataHWC to the model input tensor.
|
||||||
|
memcpy(inTensor->MutableData(), dataHWC,
|
||||||
|
inputDims.channel * inputDims.width * inputDims.height * sizeof(float));
|
||||||
|
|
||||||
|
// After the model and image tensor data is loaded, run inference.
|
||||||
|
auto status = mSession->RunGraph();
|
||||||
|
|
||||||
|
if (status != mindspore::lite::RET_OK) {
|
||||||
|
MS_PRINT("MindSpore run net error.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mindspore inference results.
|
||||||
|
* Return the map of output node name and MindSpore Lite MSTensor.
|
||||||
|
*/
|
||||||
|
auto names = mSession->GetOutputTensorNames();
|
||||||
|
|
||||||
|
std::unordered_map<std::string, mindspore::tensor::MSTensor *> msOutputs;
|
||||||
|
for (const auto &name : names) {
|
||||||
|
auto temp_dat = mSession->GetOutputByTensorName(name);
|
||||||
|
msOutputs.insert(std::pair<std::string, mindspore::tensor::MSTensor *>{name, temp_dat});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string resultStr = ProcessRunnetResult(::RET_CAR_DETAILED_SUM,
|
||||||
|
::labels_name_car_detailed_map, msOutputs);
|
||||||
|
|
||||||
|
const char *resultCharData = resultStr.c_str();
|
||||||
|
return (env)->NewStringUTF(resultCharData);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_mindspore_classificationforcar_gallery_classify_TrackingMobile_unloadModel(JNIEnv *env,
|
||||||
|
jclass type,
|
||||||
|
jlong netEnv) {
|
||||||
|
MS_PRINT("MindSpore release net.");
|
||||||
|
void **labelEnv = reinterpret_cast<void **>(netEnv);
|
||||||
|
if (labelEnv == nullptr) {
|
||||||
|
MS_PRINT("MindSpore error, labelEnv is a nullptr.");
|
||||||
|
}
|
||||||
|
MSNetWork *labelNet = static_cast<MSNetWork *>(*labelEnv);
|
||||||
|
|
||||||
|
labelNet->ReleaseNets();
|
||||||
|
|
||||||
|
return (jboolean) true;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
|
||||||
|
#define MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
|
|
@ -0,0 +1,165 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.mindspore.classificationforcar.gallery.classify;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.media.ExifInterface;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class BitmapUtils {
|
||||||
|
private static final String TAG = "BitmapUtils";
|
||||||
|
|
||||||
|
public static void recycleBitmap(Bitmap... bitmaps) {
|
||||||
|
for (Bitmap bitmap : bitmaps) {
|
||||||
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap getBitmapFormUri(Activity ac, Uri uri) {
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
try {
|
||||||
|
InputStream input = ac.getContentResolver().openInputStream(uri);
|
||||||
|
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
|
||||||
|
onlyBoundsOptions.inJustDecodeBounds = true;
|
||||||
|
onlyBoundsOptions.inDither = true;//optional
|
||||||
|
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
|
||||||
|
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
|
||||||
|
input.close();
|
||||||
|
int originalWidth = onlyBoundsOptions.outWidth;
|
||||||
|
int originalHeight = onlyBoundsOptions.outHeight;
|
||||||
|
if ((originalWidth == -1) || (originalHeight == -1))
|
||||||
|
return null;
|
||||||
|
float hh = 1920f;
|
||||||
|
float ww = 1080f;
|
||||||
|
int be = 1;
|
||||||
|
if (originalWidth > originalHeight && originalWidth > ww) {
|
||||||
|
be = (int) (originalWidth / ww);
|
||||||
|
} else if (originalWidth < originalHeight && originalHeight > hh) {
|
||||||
|
be = (int) (originalHeight / hh);
|
||||||
|
}
|
||||||
|
if (be <= 0) {
|
||||||
|
be = 1;
|
||||||
|
}
|
||||||
|
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
|
||||||
|
bitmapOptions.inSampleSize = be;
|
||||||
|
bitmapOptions.inDither = true;//optional
|
||||||
|
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
|
||||||
|
input = ac.getContentResolver().openInputStream(uri);
|
||||||
|
bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
|
||||||
|
input.close();
|
||||||
|
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return compressImage(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Bitmap compressImage(Bitmap image) {
|
||||||
|
if (image != null) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
|
||||||
|
int options = 100;
|
||||||
|
while (baos.toByteArray().length / 1024 > 100) {
|
||||||
|
baos.reset();
|
||||||
|
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
|
||||||
|
options -= 10;
|
||||||
|
}
|
||||||
|
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
|
||||||
|
return bitmap;
|
||||||
|
}else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getFileFromMediaUri(Context ac, Uri uri) {
|
||||||
|
if (uri.getScheme().toString().compareTo("content") == 0) {
|
||||||
|
ContentResolver cr = ac.getContentResolver();
|
||||||
|
Cursor cursor = cr.query(uri, null, null, null, null);
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.moveToFirst();
|
||||||
|
String filePath = cursor.getString(cursor.getColumnIndex("_data"));
|
||||||
|
cursor.close();
|
||||||
|
if (filePath != null) {
|
||||||
|
return new File(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (uri.getScheme().toString().compareTo("file") == 0) {
|
||||||
|
return new File(uri.toString().replace("file://", ""));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getBitmapDegree(String path) {
|
||||||
|
int degree = 0;
|
||||||
|
try {
|
||||||
|
ExifInterface exifInterface = new ExifInterface(path);
|
||||||
|
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
|
||||||
|
ExifInterface.ORIENTATION_NORMAL);
|
||||||
|
switch (orientation) {
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
degree = 90;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
degree = 180;
|
||||||
|
break;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
degree = 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
|
||||||
|
Bitmap returnBm = null;
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postRotate(degree);
|
||||||
|
try {
|
||||||
|
returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
}
|
||||||
|
if (returnBm == null) {
|
||||||
|
returnBm = bm;
|
||||||
|
}
|
||||||
|
if (bm != returnBm) {
|
||||||
|
bm.recycle();
|
||||||
|
}
|
||||||
|
return returnBm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar.gallery.classify;
|
||||||
|
|
||||||
|
import android.util.Size;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data comparator.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CompareSizesByArea implements Comparator<Size> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Size lhs, Size rhs) {
|
||||||
|
// We cast here to ensure the multiplications won't overflow
|
||||||
|
return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar.gallery.classify;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the MindSpore interface API in the Java layer.
|
||||||
|
*/
|
||||||
|
public class ImageTrackingMobile {
|
||||||
|
private final static String TAG = "ImageTrackingMobile";
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("mlkit-label-MS");
|
||||||
|
Log.i(TAG, "load libiMindSpore.so successfully.");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
Log.e(TAG, "UnsatisfiedLinkError >>>>>>" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The address of the running inference environment.
|
||||||
|
private long netEnv = 0;
|
||||||
|
|
||||||
|
private final Context mActivity;
|
||||||
|
|
||||||
|
public ImageTrackingMobile(Context activity) {
|
||||||
|
this.mActivity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JNI load model and also create model inference environment.
|
||||||
|
*
|
||||||
|
* @param modelBuffer Model buffer.
|
||||||
|
* @param numThread The num of thread.
|
||||||
|
* @return MindSpore Inference environment address.
|
||||||
|
*/
|
||||||
|
public native long loadModel(ByteBuffer modelBuffer, int numThread);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Running model.
|
||||||
|
*
|
||||||
|
* @param netEnv Inference environment address.
|
||||||
|
* @param img A picture to be inferred.
|
||||||
|
* @return Inference result
|
||||||
|
*/
|
||||||
|
public native String runNet(long netEnv, Bitmap img);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbind model data.
|
||||||
|
*
|
||||||
|
* @param netEnv Inference environment address.
|
||||||
|
* @return Unbound state.
|
||||||
|
*/
|
||||||
|
public native boolean unloadModel(long netEnv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The C++ side is encapsulated into a method of the MSNetWorks class
|
||||||
|
*
|
||||||
|
* @param modelPath Model file location
|
||||||
|
* @return Load model file status
|
||||||
|
*/
|
||||||
|
public boolean loadModelFromBuf(String modelPath) {
|
||||||
|
ByteBuffer buffer = loadModelFile(modelPath);
|
||||||
|
netEnv = loadModel(buffer, 2); //numThread's default setting is 2.
|
||||||
|
if (netEnv == 0) { // Loading model failed.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run MindSpore inference.
|
||||||
|
*/
|
||||||
|
public String MindSpore_runnet(Bitmap img) {
|
||||||
|
String ret_str = runNet(netEnv, img);
|
||||||
|
return ret_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unload model.
|
||||||
|
*
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
|
public boolean unloadModel() {
|
||||||
|
unloadModel(netEnv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load model file stream.
|
||||||
|
*
|
||||||
|
* @param modelPath Model file path.
|
||||||
|
* @return Model ByteBuffer.
|
||||||
|
*/
|
||||||
|
public ByteBuffer loadModelFile(String modelPath) {
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = mActivity.getAssets().open(modelPath);
|
||||||
|
byte[] bytes = new byte[is.available()];
|
||||||
|
is.read(bytes);
|
||||||
|
return ByteBuffer.allocateDirect(bytes.length).put(bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d("loadModelFile", " Exception occur. ");
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.mindspore.classificationforcar.gallery.classify;
|
||||||
|
|
||||||
|
public class RecognitionImageBean {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private float score;
|
||||||
|
|
||||||
|
public RecognitionImageBean(String name, float score) {
|
||||||
|
this.name = name;
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScore(float score) {
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar.gallery.classify;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the MindSpore interface API in the Java layer.
|
||||||
|
*/
|
||||||
|
public class TrackingMobile {
|
||||||
|
private final static String TAG = "TrackingMobile";
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("mlkit-label-MS");
|
||||||
|
Log.i(TAG, "load libiMindSpore.so successfully.");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
Log.e(TAG, "UnsatisfiedLinkError " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The address of the running inference environment.
|
||||||
|
private long netEnv = 0;
|
||||||
|
|
||||||
|
private final Context mActivity;
|
||||||
|
|
||||||
|
public TrackingMobile(Context activity) {
|
||||||
|
this.mActivity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JNI load model and also create model inference environment.
|
||||||
|
*
|
||||||
|
* @param modelBuffer Model buffer.
|
||||||
|
* @param numThread The num of thread.
|
||||||
|
* @return MindSpore Inference environment address.
|
||||||
|
*/
|
||||||
|
public native long loadModel(ByteBuffer modelBuffer, int numThread);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Running model.
|
||||||
|
*
|
||||||
|
* @param netEnv Inference environment address.
|
||||||
|
* @param img A picture to be inferred.
|
||||||
|
* @return Inference result
|
||||||
|
*/
|
||||||
|
public native String runNet(long netEnv, Bitmap img);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbind model data.
|
||||||
|
*
|
||||||
|
* @param netEnv Inference environment address.
|
||||||
|
* @return Unbound state.
|
||||||
|
*/
|
||||||
|
public native boolean unloadModel(long netEnv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The C++ side is encapsulated into a method of the MSNetWorks class
|
||||||
|
*
|
||||||
|
* @param modelPath Model file location
|
||||||
|
* @return Load model file status
|
||||||
|
*/
|
||||||
|
public boolean loadModelFromBuf(String modelPath) {
|
||||||
|
ByteBuffer buffer = loadModelFile(modelPath);
|
||||||
|
netEnv = loadModel(buffer, 2); //numThread's default setting is 2.
|
||||||
|
if (netEnv == 0){ // Loading model failed.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run MindSpore inference.
|
||||||
|
*/
|
||||||
|
public String MindSpore_runnet(Bitmap img) {
|
||||||
|
String ret_str = runNet(netEnv, img);
|
||||||
|
return ret_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unload model.
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
|
public boolean unloadModel() {
|
||||||
|
unloadModel(netEnv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load model file stream.
|
||||||
|
* @param modelPath Model file path.
|
||||||
|
* @return Model ByteBuffer.
|
||||||
|
*/
|
||||||
|
public ByteBuffer loadModelFile(String modelPath) {
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = new FileInputStream(modelPath);
|
||||||
|
// is = mActivity.getAssets().open(modelPath);
|
||||||
|
byte[] bytes = new byte[is.available()];
|
||||||
|
is.read(bytes);
|
||||||
|
return ByteBuffer.allocateDirect(bytes.length).put(bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d("loadModelFile", " Exception occur. ");
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.TextureView;
|
||||||
|
|
||||||
|
public class AutoFitTextureView extends TextureView {
|
||||||
|
|
||||||
|
private int mRatioWidth = 0;
|
||||||
|
private int mRatioHeight = 0;
|
||||||
|
|
||||||
|
public AutoFitTextureView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoFitTextureView(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
|
||||||
|
* calculated from the parameters. Note that the actual sizes of parameters don't matter, that
|
||||||
|
* is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
|
||||||
|
*
|
||||||
|
* @param width Relative horizontal size
|
||||||
|
* @param height Relative vertical size
|
||||||
|
*/
|
||||||
|
public void setAspectRatio(int width, int height) {
|
||||||
|
if (width < 0 || height < 0) {
|
||||||
|
throw new IllegalArgumentException("Size cannot be negative.");
|
||||||
|
}
|
||||||
|
mRatioWidth = width;
|
||||||
|
mRatioHeight = height;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
|
||||||
|
if (0 == mRatioWidth || 0 == mRatioHeight) {
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
} else {
|
||||||
|
if (width > height * mRatioWidth / mRatioHeight) {
|
||||||
|
setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
|
||||||
|
} else {
|
||||||
|
setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar.widget;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.UiThread;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.mindspore.classificationforcar.R;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.ImageTrackingMobile;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.RecognitionImageBean;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.TrackingMobile;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main interface of camera preview.
|
||||||
|
* Using Camera 2 API.
|
||||||
|
*/
|
||||||
|
public class CameraActivity extends AppCompatActivity {
|
||||||
|
private static final String TAG = "CameraActivity";
|
||||||
|
private static final String IMAGE_SCENE_MS = "model/mobilenetv2.ms";
|
||||||
|
|
||||||
|
private String filePath;
|
||||||
|
private boolean isCarModel;
|
||||||
|
private TrackingMobile trackingMobile;
|
||||||
|
private ImageTrackingMobile imageTrackingMobile;
|
||||||
|
|
||||||
|
private TextView resultText;
|
||||||
|
private List<RecognitionImageBean> recognitionObjectBeanList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Log.d(TAG, "onCreate");
|
||||||
|
setContentView(R.layout.activity_camera);
|
||||||
|
|
||||||
|
filePath = getIntent().getStringExtra("FILEPATH");
|
||||||
|
isCarModel = getIntent().getBooleanExtra("ISHASCARMODELFILE", false);
|
||||||
|
resultText = findViewById(R.id.textResult);
|
||||||
|
|
||||||
|
if (isCarModel) {
|
||||||
|
trackingMobile = new TrackingMobile(this);
|
||||||
|
boolean ret = trackingMobile.loadModelFromBuf(filePath);
|
||||||
|
if (!ret) {
|
||||||
|
Log.e(TAG, "Load model error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
imageTrackingMobile = new ImageTrackingMobile(this);
|
||||||
|
boolean ret = imageTrackingMobile.loadModelFromBuf(IMAGE_SCENE_MS);
|
||||||
|
if (!ret) {
|
||||||
|
Log.e(TAG, "Load model error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addCameraFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addCameraFragment() {
|
||||||
|
CameraFragment cameraFragment = CameraFragment.newInstance(bitmap -> {
|
||||||
|
runOnUiThread(() -> initMindspore(bitmap));
|
||||||
|
});
|
||||||
|
|
||||||
|
getSupportFragmentManager().beginTransaction()
|
||||||
|
.replace(R.id.container, cameraFragment)
|
||||||
|
.commitAllowingStateLoss();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initMindspore(Bitmap bitmap) {
|
||||||
|
// run net.
|
||||||
|
if (isCarModel) {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
String result = trackingMobile.MindSpore_runnet(bitmap);
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
resultText.setText(TextUtils.isEmpty(result) ? "正在识别..." : result);
|
||||||
|
Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
|
||||||
|
Log.d(TAG, "result:" + result);
|
||||||
|
} else {
|
||||||
|
if (recognitionObjectBeanList != null) {
|
||||||
|
recognitionObjectBeanList.clear();
|
||||||
|
} else {
|
||||||
|
recognitionObjectBeanList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
String result = imageTrackingMobile.MindSpore_runnet(bitmap);
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
|
||||||
|
Log.d(TAG, "result:" + result);
|
||||||
|
if (!TextUtils.isEmpty(result)) {
|
||||||
|
String[] resultArray = result.split(";");
|
||||||
|
for (String singleRecognitionResult : resultArray) {
|
||||||
|
String[] singleResult = singleRecognitionResult.split(":");
|
||||||
|
float score = Float.parseFloat(singleResult[1]);
|
||||||
|
if (score > 0.5) {
|
||||||
|
recognitionObjectBeanList.add(new RecognitionImageBean(singleResult[0], score));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(recognitionObjectBeanList, (t1, t2) -> Float.compare(t2.getScore(), t1.getScore()));
|
||||||
|
showResultsInBottomSheet(recognitionObjectBeanList, (endTime - startTime) + "ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
protected void showResultsInBottomSheet(List<RecognitionImageBean> list, String time) {
|
||||||
|
if (list == null || list.size() < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
RecognitionImageBean bean = list.get(i);
|
||||||
|
stringBuilder.append(bean.getName()).append("\r:\r").append(String.format("%.2f", (100 * bean.getScore())) + "%").append("\r\n");
|
||||||
|
if (i > 3) { // set maximum display is 3.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultText.setText(stringBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (trackingMobile != null) {
|
||||||
|
trackingMobile.unloadModel();
|
||||||
|
}
|
||||||
|
if (imageTrackingMobile != null) {
|
||||||
|
imageTrackingMobile.unloadModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,782 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar.widget;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.ImageFormat;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.SurfaceTexture;
|
||||||
|
import android.hardware.camera2.CameraAccessException;
|
||||||
|
import android.hardware.camera2.CameraCaptureSession;
|
||||||
|
import android.hardware.camera2.CameraCharacteristics;
|
||||||
|
import android.hardware.camera2.CameraDevice;
|
||||||
|
import android.hardware.camera2.CameraManager;
|
||||||
|
import android.hardware.camera2.CameraMetadata;
|
||||||
|
import android.hardware.camera2.CaptureRequest;
|
||||||
|
import android.hardware.camera2.CaptureResult;
|
||||||
|
import android.hardware.camera2.TotalCaptureResult;
|
||||||
|
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||||
|
import android.media.Image;
|
||||||
|
import android.media.ImageReader;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Size;
|
||||||
|
import android.util.SparseIntArray;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.TextureView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.mindspore.classificationforcar.R;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.CompareSizesByArea;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.TrackingMobile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class CameraFragment extends Fragment {
|
||||||
|
|
||||||
|
private static final String TAG = "CameraFragment";
|
||||||
|
|
||||||
|
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ORIENTATIONS.append(Surface.ROTATION_0, 90);
|
||||||
|
ORIENTATIONS.append(Surface.ROTATION_90, 0);
|
||||||
|
ORIENTATIONS.append(Surface.ROTATION_180, 270);
|
||||||
|
ORIENTATIONS.append(Surface.ROTATION_270, 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int MAX_PREVIEW_WIDTH = 1920;
|
||||||
|
|
||||||
|
private static final int MAX_PREVIEW_HEIGHT = 1280;
|
||||||
|
|
||||||
|
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
|
||||||
|
|
||||||
|
private int mState = STATE_PREVIEW;
|
||||||
|
|
||||||
|
private static final int STATE_PREVIEW = 0;
|
||||||
|
|
||||||
|
private static final int STATE_WAITING_LOCK = 1;
|
||||||
|
|
||||||
|
private static final int STATE_WAITING_PRECAPTURE = 2;
|
||||||
|
|
||||||
|
private static final int STATE_WAITING_NON_PRECAPTURE = 3;
|
||||||
|
|
||||||
|
private static final int STATE_PICTURE_TAKEN = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data interface returned after identification.
|
||||||
|
*/
|
||||||
|
private RecognitionDataCallBack recognitionDataCallBack;
|
||||||
|
|
||||||
|
private AutoFitTextureView mTextureView;
|
||||||
|
|
||||||
|
private boolean mFlashSupported;
|
||||||
|
|
||||||
|
private boolean isPreBackgroundThreadPause;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HandlerThread and Handler of camera and algorithm.
|
||||||
|
*/
|
||||||
|
private HandlerThread mCameraHandlerThread, mMindsporeHandlerThread;
|
||||||
|
|
||||||
|
private Handler mCameraHandler, mMindsporeHandler;
|
||||||
|
|
||||||
|
private CameraManager mCameraManager;
|
||||||
|
|
||||||
|
private CameraCaptureSession mCaptureSession;
|
||||||
|
|
||||||
|
private CameraDevice mCameraDevice;
|
||||||
|
|
||||||
|
private String mCameraId;
|
||||||
|
|
||||||
|
private ImageReader mImageReader;
|
||||||
|
|
||||||
|
private CaptureRequest.Builder mPreviewRequestBuilder;
|
||||||
|
|
||||||
|
private CaptureRequest mPreviewRequest;
|
||||||
|
|
||||||
|
private File mFile;
|
||||||
|
|
||||||
|
private Size mPreviewSize;
|
||||||
|
|
||||||
|
private int mSensorOrientation;
|
||||||
|
|
||||||
|
private CameraDevice.StateCallback mCameraDeviceStateCallback;
|
||||||
|
|
||||||
|
|
||||||
|
private CameraFragment(RecognitionDataCallBack recognitionDataCallBack) {
|
||||||
|
this.recognitionDataCallBack = recognitionDataCallBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton.
|
||||||
|
*
|
||||||
|
* @param recognitionDataCallBack Identify data return interface.
|
||||||
|
* @return Construction method.
|
||||||
|
*/
|
||||||
|
public static CameraFragment newInstance(RecognitionDataCallBack recognitionDataCallBack) {
|
||||||
|
return new CameraFragment(recognitionDataCallBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data interface returned after identification.
|
||||||
|
*/
|
||||||
|
public interface RecognitionDataCallBack {
|
||||||
|
|
||||||
|
void onRecognitionDataCallBack(Bitmap bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_camera, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
initChildThread();
|
||||||
|
initCameraManager();
|
||||||
|
initSelectCamera();
|
||||||
|
initHandlerMatchingSize();
|
||||||
|
initImageReader();
|
||||||
|
initTextureViewListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
closeCamera();
|
||||||
|
stopBackgroundThread();
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initChildThread() {
|
||||||
|
mCameraHandlerThread = new HandlerThread("CAMERA2");
|
||||||
|
mCameraHandlerThread.start();
|
||||||
|
mCameraHandler = new Handler(mCameraHandlerThread.getLooper());
|
||||||
|
|
||||||
|
mMindsporeHandlerThread = new HandlerThread("MINDSPORE");
|
||||||
|
mMindsporeHandlerThread.start();
|
||||||
|
mMindsporeHandler = new Handler(mMindsporeHandlerThread.getLooper());
|
||||||
|
mMindsporeHandler.postDelayed(classifyRunnable, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect time-consuming threads
|
||||||
|
*/
|
||||||
|
private Runnable classifyRunnable = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (CameraFragment.this) {
|
||||||
|
Bitmap bitmap = mTextureView.getBitmap();
|
||||||
|
if (bitmap != null) {
|
||||||
|
if (recognitionDataCallBack != null) {
|
||||||
|
// Interface returns data。
|
||||||
|
recognitionDataCallBack.onRecognitionDataCallBack(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mMindsporeHandler != null && !isPreBackgroundThreadPause) {
|
||||||
|
mMindsporeHandler.postDelayed(classifyRunnable, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void initCameraManager() {
|
||||||
|
mCameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSelectCamera() {
|
||||||
|
try {
|
||||||
|
String[] cameraIdArray = mCameraManager.getCameraIdList();
|
||||||
|
for (String itemId : cameraIdArray) {
|
||||||
|
CameraCharacteristics itemCharacteristics = mCameraManager.getCameraCharacteristics(itemId);
|
||||||
|
Integer facing = itemCharacteristics.get(CameraCharacteristics.LENS_FACING);
|
||||||
|
if (facing == CameraCharacteristics.LENS_FACING_BACK) {
|
||||||
|
mCameraId = itemId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (mCameraId == null) {
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.camera_error), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StreamConfigurationMap streamConfigurationMap;
|
||||||
|
private Size largest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the camera resolution suitable for the current screen resolution.
|
||||||
|
*/
|
||||||
|
private void initHandlerMatchingSize() {
|
||||||
|
try {
|
||||||
|
CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
|
||||||
|
streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||||
|
|
||||||
|
Size[] sizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
|
||||||
|
largest = Collections.max(Arrays.asList(sizes), new CompareSizesByArea());
|
||||||
|
|
||||||
|
Boolean available = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
|
||||||
|
mFlashSupported = available == null ? false : available;
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the picture.
|
||||||
|
*/
|
||||||
|
private void initImageReader() {
|
||||||
|
final int W = 640;
|
||||||
|
final int H = 480;
|
||||||
|
|
||||||
|
mImageReader = ImageReader.newInstance(W, H, ImageFormat.JPEG, 30);
|
||||||
|
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
|
||||||
|
@Override
|
||||||
|
public void onImageAvailable(ImageReader reader) {
|
||||||
|
mFile = new File(getActivity().getExternalFilesDir(null), System.currentTimeMillis() + ".jpg");
|
||||||
|
// Get the data frame and start the algorithm processing.
|
||||||
|
try {
|
||||||
|
// Get the next image from the ImageReader queue.
|
||||||
|
Image image = reader.acquireNextImage();
|
||||||
|
image.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "onImageAvailable: " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, mCameraHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextureView.SurfaceTextureListener
|
||||||
|
*/
|
||||||
|
private void initTextureViewListener() {
|
||||||
|
if (mTextureView.isAvailable()) {
|
||||||
|
openCamera(mTextureView.getMeasuredWidth(), mTextureView.getMeasuredHeight());
|
||||||
|
Log.d(TAG, "isAvailable: " + mTextureView.getWidth() + "--" + mTextureView.getHeight());
|
||||||
|
} else {
|
||||||
|
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
|
||||||
|
openCamera(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
|
||||||
|
configureTransform(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
private void openCamera(int width, int height) {
|
||||||
|
setPreviewSize(width, height, streamConfigurationMap, largest);
|
||||||
|
configureTransform(width, height);
|
||||||
|
|
||||||
|
mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
|
||||||
|
@Override
|
||||||
|
public void onOpened(@NonNull CameraDevice cameraDevice) {
|
||||||
|
if (cameraDevice != null) {
|
||||||
|
mCameraOpenCloseLock.release();
|
||||||
|
mCameraDevice = cameraDevice;
|
||||||
|
createCameraPreviewSession();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
||||||
|
if (cameraDevice != null) {
|
||||||
|
mCameraOpenCloseLock.release();
|
||||||
|
cameraDevice.close();
|
||||||
|
mCameraDevice = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull CameraDevice cameraDevice, int i) {
|
||||||
|
if (cameraDevice != null) {
|
||||||
|
mCameraOpenCloseLock.release();
|
||||||
|
cameraDevice.close();
|
||||||
|
mCameraDevice = null;
|
||||||
|
if (null != getActivity()) {
|
||||||
|
getActivity().finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
||||||
|
throw new RuntimeException("Time out waiting to lock ic_launcher opening.");
|
||||||
|
}
|
||||||
|
mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mCameraHandler);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException("Interrupted while trying to lock ic_launcher opening.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open camera preview.
|
||||||
|
*/
|
||||||
|
private void createCameraPreviewSession() {
|
||||||
|
try {
|
||||||
|
SurfaceTexture texture = mTextureView.getSurfaceTexture();
|
||||||
|
// Set preview size.
|
||||||
|
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||||
|
// This is the output Surface we need to start preview.
|
||||||
|
Surface surface = new Surface(texture);
|
||||||
|
|
||||||
|
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
||||||
|
mPreviewRequestBuilder.addTarget(surface);
|
||||||
|
// Here, we create a CameraCaptureSession for ic_launcher preview.
|
||||||
|
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
|
||||||
|
new CameraCaptureSession.StateCallback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||||
|
// The ic_launcher is already closed
|
||||||
|
if (null == mCameraDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the session is ready, we start displaying the preview.
|
||||||
|
mCaptureSession = cameraCaptureSession;
|
||||||
|
try {
|
||||||
|
// Auto focus should be continuous for ic_launcher preview.
|
||||||
|
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
|
||||||
|
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||||
|
// Flash is automatically enabled when necessary.
|
||||||
|
setAutoFlash(mPreviewRequestBuilder);
|
||||||
|
// Finally, we start displaying the ic_launcher preview.
|
||||||
|
mPreviewRequest = mPreviewRequestBuilder.build();
|
||||||
|
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mCameraHandler);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
|
||||||
|
Toast.makeText(getActivity(), "Failed", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
|
||||||
|
|
||||||
|
private void process(CaptureResult result) {
|
||||||
|
switch (mState) {
|
||||||
|
case STATE_PREVIEW: {
|
||||||
|
// We have nothing to do when the ic_launcher preview is working normally.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_WAITING_LOCK: {
|
||||||
|
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
|
||||||
|
if (afState == null) {
|
||||||
|
captureStillPicture();
|
||||||
|
} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState
|
||||||
|
|| CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
|
||||||
|
// CONTROL_AE_STATE can be null on some devices
|
||||||
|
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
|
||||||
|
if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
|
||||||
|
mState = STATE_PICTURE_TAKEN;
|
||||||
|
captureStillPicture();
|
||||||
|
} else {
|
||||||
|
runPrecaptureSequence();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_WAITING_PRECAPTURE: {
|
||||||
|
// CONTROL_AE_STATE can be null on some devices
|
||||||
|
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
|
||||||
|
if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE
|
||||||
|
|| aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
|
||||||
|
mState = STATE_WAITING_NON_PRECAPTURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_WAITING_NON_PRECAPTURE: {
|
||||||
|
// CONTROL_AE_STATE can be null on some devices
|
||||||
|
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
|
||||||
|
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
|
||||||
|
mState = STATE_PICTURE_TAKEN;
|
||||||
|
captureStillPicture();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,
|
||||||
|
@NonNull CaptureResult partialResult) {
|
||||||
|
process(partialResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,
|
||||||
|
@NonNull TotalCaptureResult result) {
|
||||||
|
process(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the precapture sequence for capturing a still image. This method should be called when
|
||||||
|
* we get a response in.
|
||||||
|
*/
|
||||||
|
private void runPrecaptureSequence() {
|
||||||
|
try {
|
||||||
|
// This is how to tell the ic_launcher to trigger.
|
||||||
|
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
|
||||||
|
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
|
||||||
|
// Tell #mCaptureCallback to wait for the precapture sequence to be set.
|
||||||
|
mState = STATE_WAITING_PRECAPTURE;
|
||||||
|
mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mCameraHandler);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture a still picture. This method should be called when we get a response in
|
||||||
|
* {@link #mCaptureCallback} from both
|
||||||
|
*/
|
||||||
|
private void captureStillPicture() {
|
||||||
|
try {
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
if (null == activity || null == mCameraDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// This is the CaptureRequest.Builder that we use to take a picture.
|
||||||
|
final CaptureRequest.Builder captureBuilder =
|
||||||
|
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
|
||||||
|
captureBuilder.addTarget(mImageReader.getSurface());
|
||||||
|
|
||||||
|
// Use the same AE and AF modes as the preview.
|
||||||
|
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||||
|
setAutoFlash(captureBuilder);
|
||||||
|
|
||||||
|
// Orientation
|
||||||
|
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||||
|
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
|
||||||
|
|
||||||
|
CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,
|
||||||
|
@NonNull TotalCaptureResult result) {
|
||||||
|
showToast("Saved: " + mFile);
|
||||||
|
Log.d(TAG, mFile.toString());
|
||||||
|
unlockFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mCaptureSession.stopRepeating();
|
||||||
|
mCaptureSession.abortCaptures();
|
||||||
|
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the JPEG orientation from the specified screen rotation.
|
||||||
|
*
|
||||||
|
* @param rotation The screen rotation.
|
||||||
|
* @return The JPEG orientation (one of 0, 90, 270, and 360)
|
||||||
|
*/
|
||||||
|
private int getOrientation(int rotation) {
|
||||||
|
return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock the focus. This method should be called when still image capture sequence is
|
||||||
|
* finished.
|
||||||
|
*/
|
||||||
|
private void unlockFocus() {
|
||||||
|
try {
|
||||||
|
// Reset the auto-focus trigger
|
||||||
|
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
|
||||||
|
setAutoFlash(mPreviewRequestBuilder);
|
||||||
|
mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mCameraHandler);
|
||||||
|
// After this, the ic_launcher will go back to the normal state of preview.
|
||||||
|
mState = STATE_PREVIEW;
|
||||||
|
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mCameraHandler);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
|
||||||
|
if (mFlashSupported) {
|
||||||
|
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showToast(final String text) {
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
if (activity != null) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the necessary {@link Matrix} transformation to `mTextureView`.
|
||||||
|
* This method should be called after the ic_launcher preview size is determined in
|
||||||
|
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
|
||||||
|
*
|
||||||
|
* @param viewWidth The width of `mTextureView`
|
||||||
|
* @param viewHeight The height of `mTextureView`
|
||||||
|
*/
|
||||||
|
protected void configureTransform(int viewWidth, int viewHeight) {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (null == mTextureView || null == mPreviewSize || null == activity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
|
||||||
|
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
|
||||||
|
float centerX = viewRect.centerX();
|
||||||
|
float centerY = viewRect.centerY();
|
||||||
|
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
|
||||||
|
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
|
||||||
|
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
|
||||||
|
float scale =
|
||||||
|
Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
|
||||||
|
matrix.postScale(scale, scale, centerX, centerY);
|
||||||
|
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
|
||||||
|
} else if (Surface.ROTATION_180 == rotation) {
|
||||||
|
matrix.postRotate(180, centerX, centerY);
|
||||||
|
}
|
||||||
|
mTextureView.setTransform(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set preview image size and positioning.
|
||||||
|
*
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
* @param map StreamConfigurationMap, the manager of all output formats and sizes supported by the camera.
|
||||||
|
* @param largest The max size
|
||||||
|
*/
|
||||||
|
private void setPreviewSize(int width, int height, StreamConfigurationMap map, Size largest) {
|
||||||
|
// Find out if we need to swap dimension to get the preview size relative to sensor coordinate.
|
||||||
|
int displayRotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
|
||||||
|
Log.d(TAG, "displayRotation: " + displayRotation);
|
||||||
|
|
||||||
|
boolean swappedDimensions = false;
|
||||||
|
if (Surface.ROTATION_0 == displayRotation || Surface.ROTATION_180 == displayRotation) {
|
||||||
|
if (mSensorOrientation == 90 || mSensorOrientation == 270) {
|
||||||
|
swappedDimensions = true;
|
||||||
|
}
|
||||||
|
} else if (Surface.ROTATION_90 == displayRotation || Surface.ROTATION_270 == displayRotation) {
|
||||||
|
if (mSensorOrientation == 0 || mSensorOrientation == 180) {
|
||||||
|
swappedDimensions = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point displaySize = new Point();
|
||||||
|
getActivity().getWindowManager().getDefaultDisplay().getSize(displaySize);
|
||||||
|
int rotatedPreviewWidth = width;
|
||||||
|
int rotatedPreviewHeight = height;
|
||||||
|
int maxPreviewWidth = displaySize.x;
|
||||||
|
int maxPreviewHeight = displaySize.y;
|
||||||
|
|
||||||
|
if (swappedDimensions) {
|
||||||
|
rotatedPreviewWidth = height;
|
||||||
|
rotatedPreviewHeight = width;
|
||||||
|
maxPreviewWidth = displaySize.y;
|
||||||
|
maxPreviewHeight = displaySize.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
|
||||||
|
maxPreviewWidth = MAX_PREVIEW_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
|
||||||
|
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Danger, W.R.! Attempting to use too large a preview size could exceed the ic_launcher
|
||||||
|
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
|
||||||
|
// garbage capture data.
|
||||||
|
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedPreviewWidth,
|
||||||
|
rotatedPreviewHeight, maxPreviewWidth, maxPreviewHeight, largest);
|
||||||
|
|
||||||
|
// We fit the aspect ratio of TextureView to the size of preview we picked.
|
||||||
|
int orientation = getResources().getConfiguration().orientation;// manifest中方向已经写死
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||||
|
} else {
|
||||||
|
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given {@code choices} of {@code Size}s supported by a ic_launcher, choose the smallest one that
|
||||||
|
* is at least as large as the respective texture view size, and that is at most as large as the
|
||||||
|
* respective max size, and whose aspect ratio matches with the specified value. If such size
|
||||||
|
* doesn't exist, choose the largest one that is at most as large as the respective max size,
|
||||||
|
* and whose aspect ratio matches with the specified value.
|
||||||
|
*
|
||||||
|
* @param choices The list of sizes that the ic_launcher supports for the intended output
|
||||||
|
* class
|
||||||
|
* @param textureViewWidth The width of the texture view relative to sensor coordinate
|
||||||
|
* @param textureViewHeight The height of the texture view relative to sensor coordinate
|
||||||
|
* @param maxWidth The maximum width that can be chosen
|
||||||
|
* @param maxHeight The maximum height that can be chosen
|
||||||
|
* @param aspectRatio The aspect ratio
|
||||||
|
* @return The optimal {@code Size}, or an arbitrary one if none were big enough
|
||||||
|
*/
|
||||||
|
protected Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight, int maxWidth,
|
||||||
|
int maxHeight, Size aspectRatio) {
|
||||||
|
|
||||||
|
// Collect the supported resolutions that are at least as big as the preview Surface
|
||||||
|
List<Size> bigEnough = new ArrayList<>();
|
||||||
|
// Collect the supported resolutions that are smaller than the preview Surface
|
||||||
|
List<Size> notBigEnough = new ArrayList<>();
|
||||||
|
int w = aspectRatio.getWidth();
|
||||||
|
int h = aspectRatio.getHeight();
|
||||||
|
for (Size option : choices) {
|
||||||
|
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight
|
||||||
|
&& option.getHeight() == option.getWidth() * h / w) {
|
||||||
|
// if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight) {
|
||||||
|
if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
|
||||||
|
bigEnough.add(option);
|
||||||
|
} else {
|
||||||
|
notBigEnough.add(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bigEnough.size() > 0) {
|
||||||
|
return Collections.min(bigEnough, new CompareSizesByArea());
|
||||||
|
} else if (notBigEnough.size() > 0) {
|
||||||
|
return Collections.max(notBigEnough, new CompareSizesByArea());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Couldn't find any suitable preview size");
|
||||||
|
return choices[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the current {@link CameraDevice}.
|
||||||
|
*/
|
||||||
|
private void closeCamera() {
|
||||||
|
try {
|
||||||
|
mCameraOpenCloseLock.acquire();
|
||||||
|
if (null != mCaptureSession) {
|
||||||
|
mCaptureSession.close();
|
||||||
|
mCaptureSession = null;
|
||||||
|
}
|
||||||
|
if (null != mCameraDevice) {
|
||||||
|
mCameraDevice.close();
|
||||||
|
mCameraDevice = null;
|
||||||
|
}
|
||||||
|
if (null != mImageReader) {
|
||||||
|
mImageReader.close();
|
||||||
|
mImageReader = null;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException("Interrupted while trying to lock ic_launcher closing.", e);
|
||||||
|
} finally {
|
||||||
|
mCameraOpenCloseLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopBackgroundThread() {
|
||||||
|
isPreBackgroundThreadPause = true;
|
||||||
|
mCameraHandlerThread.quitSafely();
|
||||||
|
mMindsporeHandlerThread.quitSafely();
|
||||||
|
try {
|
||||||
|
mCameraHandlerThread.join();
|
||||||
|
mCameraHandlerThread = null;
|
||||||
|
mCameraHandler.removeCallbacksAndMessages(null);
|
||||||
|
mCameraHandler = null;
|
||||||
|
|
||||||
|
mMindsporeHandlerThread.join();
|
||||||
|
mMindsporeHandlerThread = null;
|
||||||
|
mMindsporeHandler.removeCallbacksAndMessages(null);
|
||||||
|
mMindsporeHandler = null;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,341 @@
|
||||||
|
package com.mindspore.classificationforcar.widget;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.UiThread;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.mindspore.classificationforcar.R;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.BitmapUtils;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.ImageTrackingMobile;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.RecognitionImageBean;
|
||||||
|
import com.mindspore.classificationforcar.gallery.classify.TrackingMobile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity implements OnBackgroundImageListener {
|
||||||
|
|
||||||
|
private static final String TAG = "MainActivity";
|
||||||
|
|
||||||
|
private static final String[] PERMISSIONS = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
|
Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA};
|
||||||
|
private static final int REQUEST_PERMISSION = 0;
|
||||||
|
|
||||||
|
private static final int[] IMAGES = {R.drawable.style0, R.drawable.style1, R.drawable.style2, R.drawable.style3, R.drawable.style4,
|
||||||
|
R.drawable.style5, R.drawable.style6, R.drawable.style7, R.drawable.style8, R.drawable.style9,
|
||||||
|
R.drawable.style10, R.drawable.style11, R.drawable.style12, R.drawable.style13, R.drawable.style14,
|
||||||
|
R.drawable.style15, R.drawable.style16, R.drawable.style17, R.drawable.style18, R.drawable.style19};
|
||||||
|
|
||||||
|
private static final int RC_CHOOSE_PHOTO = 1;
|
||||||
|
private static final int RC_CHOOSE_CAMERA = 2;
|
||||||
|
private static final String IMAGE_SCENE_MS = "model/mobilenetv2.ms";
|
||||||
|
|
||||||
|
private boolean isAllGranted;
|
||||||
|
private static final String CAR_MS = "car.ms";
|
||||||
|
private File ROOT_FILE = new File(Environment.getExternalStorageDirectory().getAbsoluteFile(), "CarClassification");
|
||||||
|
private File DIR_FILE = new File(ROOT_FILE, CAR_MS);
|
||||||
|
|
||||||
|
private ImageView imgPreview;
|
||||||
|
private Uri imageUri;
|
||||||
|
private TextView textResult;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
private RecyclerView recyclerView;
|
||||||
|
private TrackingMobile trackingMobile;
|
||||||
|
private ImageTrackingMobile imageTrackingMobile;
|
||||||
|
private List<RecognitionImageBean> recognitionObjectBeanList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
init();
|
||||||
|
requestPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
imgPreview = findViewById(R.id.img_origin);
|
||||||
|
textResult = findViewById(R.id.tv_image);
|
||||||
|
progressBar = findViewById(R.id.progress);
|
||||||
|
recyclerView = findViewById(R.id.recyclerview);
|
||||||
|
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
|
||||||
|
recyclerView.setAdapter(new RecyclerViewAdapter(this, IMAGES, this));
|
||||||
|
trackingMobile = new TrackingMobile(this);
|
||||||
|
imageTrackingMobile = new ImageTrackingMobile(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestPermissions() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
isAllGranted = checkPermissionAllGranted(PERMISSIONS);
|
||||||
|
if (!isAllGranted) {
|
||||||
|
ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isAllGranted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkPermissionAllGranted(String[] permissions) {
|
||||||
|
for (String permission : permissions) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authority application result callback
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
if (REQUEST_PERMISSION == requestCode) {
|
||||||
|
isAllGranted = true;
|
||||||
|
for (int grant : grantResults) {
|
||||||
|
if (grant != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
isAllGranted = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isAllGranted) {
|
||||||
|
openAppDetails();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openAppDetails() {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setMessage("HiMindSpore需要访问 “相机” 和 “外部存储器”,请到 “应用信息 -> 权限” 中授予!");
|
||||||
|
builder.setPositiveButton("去手动授权", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
intent.setData(Uri.parse("package:" + getPackageName()));
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton("取消", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasCarModelFile() {
|
||||||
|
if (DIR_FILE.exists()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (!ROOT_FILE.exists()) {
|
||||||
|
ROOT_FILE.mkdirs();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClickPhoto(View view) {
|
||||||
|
if (isAllGranted) {
|
||||||
|
openGallay();
|
||||||
|
} else {
|
||||||
|
requestPermissions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClickCamera(View view) {
|
||||||
|
if (isAllGranted) {
|
||||||
|
openCamera();
|
||||||
|
} else {
|
||||||
|
requestPermissions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClickScene(View view) {
|
||||||
|
Intent intent = new Intent(MainActivity.this, CameraActivity.class);
|
||||||
|
intent.putExtra("FILEPATH", DIR_FILE.getPath());
|
||||||
|
intent.putExtra("ISHASCARMODELFILE", isHasCarModelFile());
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackImageSelected(int position) {
|
||||||
|
imgPreview.setImageResource(IMAGES[position]);
|
||||||
|
initMindspore(BitmapFactory.decodeResource(getResources(), IMAGES[position]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openGallay() {
|
||||||
|
Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
|
||||||
|
intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
|
||||||
|
startActivityForResult(intentToPickPic, RC_CHOOSE_PHOTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openCamera() {
|
||||||
|
Intent intentToTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||||
|
String mTempPhotoPath = Environment.getExternalStorageDirectory() + File.separator + "photo22.jpeg";
|
||||||
|
imageUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".fileprovider", new File(mTempPhotoPath));
|
||||||
|
intentToTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
|
||||||
|
startActivityForResult(intentToTakePhoto, RC_CHOOSE_CAMERA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
if (RC_CHOOSE_PHOTO == requestCode) {
|
||||||
|
if (null != data && null != data.getData()) {
|
||||||
|
this.imageUri = data.getData();
|
||||||
|
showOriginImage();
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
} else if (RC_CHOOSE_CAMERA == requestCode) {
|
||||||
|
showOriginCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showOriginImage() {
|
||||||
|
File file = BitmapUtils.getFileFromMediaUri(this, imageUri);
|
||||||
|
Bitmap photoBmp = BitmapUtils.getBitmapFormUri(this, Uri.fromFile(file));
|
||||||
|
int degree = BitmapUtils.getBitmapDegree(file.getAbsolutePath());
|
||||||
|
Bitmap originBitmap = BitmapUtils.rotateBitmapByDegree(photoBmp, degree);
|
||||||
|
if (originBitmap != null) {
|
||||||
|
imgPreview.setImageBitmap(originBitmap);
|
||||||
|
initMindspore(originBitmap.copy(Bitmap.Config.ARGB_8888, true));
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.image_invalid, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showOriginCamera() {
|
||||||
|
try {
|
||||||
|
Bitmap originBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
|
||||||
|
if (originBitmap != null) {
|
||||||
|
imgPreview.setImageBitmap(originBitmap);
|
||||||
|
initMindspore(originBitmap.copy(Bitmap.Config.ARGB_8888, true));
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.image_invalid, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMindspore(Bitmap bitmap) {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (isHasCarModelFile()) {
|
||||||
|
boolean ret = trackingMobile.loadModelFromBuf(DIR_FILE.getPath());
|
||||||
|
if (!ret) {
|
||||||
|
textResult.setText("Load model error.");
|
||||||
|
Log.e(TAG, "Load model error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// run net.
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
String result = trackingMobile.MindSpore_runnet(bitmap);
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
textResult.setText(result);
|
||||||
|
Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
|
||||||
|
Log.d(TAG, "result:" + result);
|
||||||
|
} else {
|
||||||
|
if (recognitionObjectBeanList != null) {
|
||||||
|
recognitionObjectBeanList.clear();
|
||||||
|
} else {
|
||||||
|
recognitionObjectBeanList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean ret = imageTrackingMobile.loadModelFromBuf(IMAGE_SCENE_MS);
|
||||||
|
if (!ret) {
|
||||||
|
textResult.setText("Load model error.");
|
||||||
|
Log.e(TAG, "Load model error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// run net.
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
String result = imageTrackingMobile.MindSpore_runnet(bitmap);
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
|
||||||
|
Log.d(TAG, "result:" + result);
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(result)) {
|
||||||
|
String[] resultArray = result.split(";");
|
||||||
|
for (String singleRecognitionResult : resultArray) {
|
||||||
|
String[] singleResult = singleRecognitionResult.split(":");
|
||||||
|
float score = Float.parseFloat(singleResult[1]);
|
||||||
|
if (score > 0.5) {
|
||||||
|
recognitionObjectBeanList.add(new RecognitionImageBean(singleResult[0], score));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(recognitionObjectBeanList, (t1, t2) -> Float.compare(t2.getScore(), t1.getScore()));
|
||||||
|
showResultsInBottomSheet(recognitionObjectBeanList, (endTime - startTime) + "ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!bitmap.isRecycled()) {
|
||||||
|
bitmap.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
protected void showResultsInBottomSheet(List<RecognitionImageBean> list, String time) {
|
||||||
|
if (list == null || list.size() < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
RecognitionImageBean bean = list.get(i);
|
||||||
|
stringBuilder.append(bean.getName()).append("\r:\r").append(String.format("%.2f", (100 * bean.getScore())) + "%").append("\r\n");
|
||||||
|
if (i > 3) { // set maximum display is 3.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textResult.setText(stringBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (trackingMobile != null) {
|
||||||
|
trackingMobile.unloadModel();
|
||||||
|
}
|
||||||
|
if (imageTrackingMobile != null) {
|
||||||
|
imageTrackingMobile.unloadModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.mindspore.classificationforcar.widget;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
public interface OnBackgroundImageListener {
|
||||||
|
void onBackImageSelected(int position);
|
||||||
|
|
||||||
|
// void onImageAdd(View view);
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.mindspore.classificationforcar.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.mindspore.classificationforcar.R;
|
||||||
|
|
||||||
|
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.StyleItemViewHolder> {
|
||||||
|
|
||||||
|
private final int[] IMAGES;
|
||||||
|
private final Context context;
|
||||||
|
private final OnBackgroundImageListener mListener;
|
||||||
|
|
||||||
|
public RecyclerViewAdapter(Context context, int[] IMAGES, OnBackgroundImageListener mListener) {
|
||||||
|
this.IMAGES = IMAGES;
|
||||||
|
this.context = context;
|
||||||
|
this.mListener = mListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public StyleItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(context)
|
||||||
|
.inflate(R.layout.image_item, parent, false);
|
||||||
|
return new StyleItemViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull StyleItemViewHolder holder, int position) {
|
||||||
|
Glide.with(context).
|
||||||
|
load(IMAGES[position]).
|
||||||
|
into(holder.getImageView());
|
||||||
|
|
||||||
|
View view = holder.getMView();
|
||||||
|
view.setTag(IMAGES[position]);
|
||||||
|
view.setOnClickListener(view1 -> {
|
||||||
|
if (mListener != null) {
|
||||||
|
// if (IMAGES.length - 1 == position) {
|
||||||
|
// mListener.onImageAdd(holder.getImageView());
|
||||||
|
// } else {
|
||||||
|
mListener.onBackImageSelected(position);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return IMAGES == null ? 0 : IMAGES.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class StyleItemViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private ImageView imageView;
|
||||||
|
private final View mView;
|
||||||
|
|
||||||
|
public final ImageView getImageView() {
|
||||||
|
return this.imageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setImageView(ImageView imageView) {
|
||||||
|
this.imageView = imageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final View getMView() {
|
||||||
|
return this.mView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StyleItemViewHolder(View mView) {
|
||||||
|
super(mView);
|
||||||
|
this.mView = mView;
|
||||||
|
this.imageView = mView.findViewById(R.id.image_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="85.84757"
|
||||||
|
android:endY="92.4963"
|
||||||
|
android:startX="42.9492"
|
||||||
|
android:startY="49.59793"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 3.5 MiB |
After Width: | Height: | Size: 313 KiB |
After Width: | Height: | Size: 241 KiB |
After Width: | Height: | Size: 247 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 328 KiB |
After Width: | Height: | Size: 255 KiB |
After Width: | Height: | Size: 193 KiB |
After Width: | Height: | Size: 307 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 631 KiB |
After Width: | Height: | Size: 273 KiB |
After Width: | Height: | Size: 288 KiB |
After Width: | Height: | Size: 254 KiB |
|
@ -0,0 +1,170 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#26A69A"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
</vector>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:fromDegrees="0"
|
||||||
|
android:pivotX="50%"
|
||||||
|
android:pivotY="50%"
|
||||||
|
android:toDegrees="360">
|
||||||
|
<shape
|
||||||
|
android:innerRadiusRatio="3"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thicknessRatio="8"
|
||||||
|
android:useLevel="false">
|
||||||
|
<gradient
|
||||||
|
android:centerColor="#62AEEC"
|
||||||
|
android:centerY="0.50"
|
||||||
|
android:endColor="#1063A5"
|
||||||
|
android:startColor="#61C2EC"
|
||||||
|
android:type="sweep"
|
||||||
|
android:useLevel="false" />
|
||||||
|
</shape>
|
||||||
|
</animated-rotate>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/listview_background_shape">
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@android:color/darker_gray" />
|
||||||
|
<padding
|
||||||
|
android:bottom="2dp"
|
||||||
|
android:left="2dp"
|
||||||
|
android:right="2dp"
|
||||||
|
android:top="2dp" />
|
||||||
|
<solid android:color="#ffffffff" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<size
|
||||||
|
android:width="40dp"
|
||||||
|
android:height="40dp" />
|
||||||
|
<corners android:radius="20dp" />
|
||||||
|
<solid android:color="#82eae5e5" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<size
|
||||||
|
android:width="100dp"
|
||||||
|
android:height="40dp"/>
|
||||||
|
<corners android:radius="20dp" />
|
||||||
|
<solid android:color="#784b4b4b" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#00000000">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#00000000"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/black"
|
||||||
|
tools:context="com.mindspore.classificationforcar.widget.CameraActivity" />
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:background="#66000000">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableStart="@drawable/logo"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="MS Car Classification"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:maxLines="3"
|
||||||
|
android:id="@+id/textResult"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:text="正在识别..."
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="25sp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:background="#66000000">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableStart="@drawable/logo"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="MS Car Classification"
|
||||||
|
android:textColor="#ffffff"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="300dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/img_origin"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/logo2" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminateDrawable="@drawable/progressbar"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:maxLines="3"
|
||||||
|
android:id="@+id/tv_image"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="Choose an Image"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/gray_btn"
|
||||||
|
android:gravity="center"
|
||||||
|
android:onClick="onClickPhoto"
|
||||||
|
android:text="PHOTO"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/gray_btn"
|
||||||
|
android:gravity="center"
|
||||||
|
android:onClick="onClickCamera"
|
||||||
|
android:text="CAMERA"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/gray_btn"
|
||||||
|
android:gravity="center"
|
||||||
|
android:onClick="onClickScene"
|
||||||
|
android:text="SCAN"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="Choose a Demo"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="20dp"
|
||||||
|
android:fadeScrollbars="false"
|
||||||
|
android:scrollbarSize="6dp"
|
||||||
|
android:scrollbarStyle="outsideInset"
|
||||||
|
android:scrollbarThumbVertical="@color/gray"
|
||||||
|
android:scrollbars="vertical" />
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.mindspore.classificationforcar.widget.AutoFitTextureView
|
||||||
|
android:id="@+id/texture"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
tools:srcCompat="@drawable/logo" />
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_left_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/hor_text_view_text_margin_normal"
|
||||||
|
android:layout_marginTop="@dimen/hor_text_view_text_margin_small"
|
||||||
|
android:textSize="@dimen/hor_text_view_text_size"
|
||||||
|
tools:text="person" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_toRightOf="@+id/tv_left_title"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:id="@+id/tv_right_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="@dimen/hor_text_view_text_margin_normal"
|
||||||
|
android:layout_marginStart="@dimen/hor_text_view_text_margin_normal"
|
||||||
|
android:layout_marginTop="@dimen/hor_text_view_text_margin_small"
|
||||||
|
android:textSize="@dimen/hor_text_view_text_size"
|
||||||
|
tools:text="12.5" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/view_bottom_line"
|
||||||
|
android:layout_marginTop="@dimen/hor_text_view_text_margin_small"
|
||||||
|
android:layout_alignStart="@+id/tv_left_title"
|
||||||
|
android:layout_alignEnd="@+id/tv_right_content"
|
||||||
|
android:background="@color/gray"
|
||||||
|
android:layout_below="@+id/tv_left_title"
|
||||||
|
android:layout_height="0.5dp"
|
||||||
|
android:layout_width="match_parent"/>
|
||||||
|
</RelativeLayout>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#303030</color>
|
||||||
|
<color name="colorPrimaryDark">#3700B3</color>
|
||||||
|
<color name="colorAccent">#03DAC5</color>
|
||||||
|
|
||||||
|
<color name="white">#ffffff</color>
|
||||||
|
<color name="black">#000000</color>
|
||||||
|
<color name="gray">#A69D9D</color>
|
||||||
|
<color name="gray_btn">#424242</color>
|
||||||
|
|
||||||
|
<color name="text_blue">#6DA7FF</color>
|
||||||
|
<color name="text_yellow">#F8E71C</color>
|
||||||
|
<color name="text_orange">#FF844D</color>
|
||||||
|
<color name="text_green">#66B50A</color>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<dimen name="ms_bottom_sheet_corner_radius">15dp</dimen>
|
||||||
|
<dimen name="ms_bottom_sheet_top_padding">8dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="hor_text_view_text_margin_normal">15dp</dimen>
|
||||||
|
<dimen name="hor_text_view_text_margin_small">6dp</dimen>
|
||||||
|
<dimen name="hor_text_view_text_size">15sp</dimen>
|
||||||
|
</resources>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#FFFFFF</color>
|
||||||
|
</resources>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">CarClassification</string>
|
||||||
|
<string name="action_settings">设置</string>
|
||||||
|
|
||||||
|
<string name="request_permission">This sample needs camera permission.</string>
|
||||||
|
<string name="camera_error">This device doesn\'t support Camera2 API.</string>
|
||||||
|
<string name="intro_message">使用的google的camera2demo.</string>
|
||||||
|
<string name="appwidget_text">EXAMPLE</string>
|
||||||
|
<string name="add_widget">Add widget</string>
|
||||||
|
|
||||||
|
<string name="image_invalid">The image path you selected is not valid. Please choose again</string>
|
||||||
|
<string name="train_invalid">Sorry, there is no object identified in this picture. Try another picture</string>
|
||||||
|
|
||||||
|
<string name="ms_ic_app_name" translation_description="Image Classification demo app [CHAR_LIMIT=40]">TFL Classify</string>
|
||||||
|
<string name="ms_ic_camera_error" translation_description="Error regarding camera support[CHAR_LIMIT=40]">This device doesn\'t support Camera2 API.</string>
|
||||||
|
<string name="ms_ic_gpu_quant_error" translation_description="Error regarding GPU support for Quant models[CHAR_LIMIT=60]">GPU does not yet supported quantized models.</string>
|
||||||
|
<string name="ms_ic_model" translatable="false">Model:</string>
|
||||||
|
<string-array name="ms_ic_models" translatable="false">
|
||||||
|
<item>Quantized_EfficientNet</item>
|
||||||
|
<item>Float_EfficientNet</item>
|
||||||
|
<item>Quantized_MobileNet</item>
|
||||||
|
<item>Float_MobileNet</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string name="ms_ic_device" translatable="false">Device:</string>
|
||||||
|
<string-array name="ms_ic_devices" translatable="false">
|
||||||
|
<item>CPU</item>
|
||||||
|
<item>GPU</item>
|
||||||
|
<item>NNAPI</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<resources>
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths>
|
||||||
|
<external-path
|
||||||
|
name="external_files"
|
||||||
|
path="." />
|
||||||
|
</paths>
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mindspore.classificationforcar;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "com.android.tools.build:gradle:4.0.1"
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://mirrors.huaweicloud.com/repository/maven/"
|
||||||
|
}
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Project-wide Gradle settings.
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx2048m
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app"s APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
||||||
|
# Automatically convert third-party libraries to use AndroidX
|
||||||
|
android.enableJetifier=true
|
||||||
|
android.injected.testOnly=false
|
BIN
model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#Tue Jul 28 10:28:05 CST 2020
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
|
@ -0,0 +1,172 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
|
@ -0,0 +1,84 @@
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
|
@ -0,0 +1,2 @@
|
||||||
|
include ':app'
|
||||||
|
rootProject.name = "CarClassification"
|