Moving to new seperate repos
@@ -1 +1,123 @@
|
|||||||
.idea
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
|
||||||
|
data/
|
||||||
|
downloads/
|
||||||
|
fortt/
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
.idea/*
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
|
|
||||||
data/
|
|
||||||
downloads/
|
|
||||||
fortt/
|
|
||||||
logs/
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
.python-version
|
|
||||||
|
|
||||||
# celery beat schedule file
|
|
||||||
celerybeat-schedule
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# Built application files
|
|
||||||
*.apk
|
|
||||||
*.ap_
|
|
||||||
*.aab
|
|
||||||
|
|
||||||
# Files for the ART/Dalvik VM
|
|
||||||
*.dex
|
|
||||||
|
|
||||||
# Java class files
|
|
||||||
*.class
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
bin/
|
|
||||||
gen/
|
|
||||||
out/
|
|
||||||
|
|
||||||
# Gradle files
|
|
||||||
.gradle/
|
|
||||||
build/
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# Local configuration file (sdk path, etc)
|
|
||||||
local.properties
|
|
||||||
|
|
||||||
# Proguard folder generated by Eclipse
|
|
||||||
proguard/
|
|
||||||
|
|
||||||
# Log Files
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Android Studio Navigation editor temp files
|
|
||||||
.navigation/
|
|
||||||
|
|
||||||
# Android Studio captures folder
|
|
||||||
captures/
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
*.iml
|
|
||||||
.idea/workspace.xml
|
|
||||||
.idea/tasks.xml
|
|
||||||
.idea/gradle.xml
|
|
||||||
.idea/assetWizardSettings.xml
|
|
||||||
.idea/dictionaries
|
|
||||||
.idea/libraries
|
|
||||||
.idea/caches
|
|
||||||
# Android Studio 3 in .gitignore file.
|
|
||||||
.idea/caches/build_file_checksums.ser
|
|
||||||
.idea/modules.xml
|
|
||||||
|
|
||||||
# Keystore files
|
|
||||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
|
||||||
#*.jks
|
|
||||||
#*.keystore
|
|
||||||
|
|
||||||
# External native build folder generated in Android Studio 2.2 and later
|
|
||||||
.externalNativeBuild
|
|
||||||
|
|
||||||
# Google Services (e.g. APIs or Firebase)
|
|
||||||
# google-services.json
|
|
||||||
|
|
||||||
# Freeline
|
|
||||||
freeline.py
|
|
||||||
freeline/
|
|
||||||
freeline_project_description.json
|
|
||||||
|
|
||||||
# fastlane
|
|
||||||
fastlane/report.xml
|
|
||||||
fastlane/Preview.html
|
|
||||||
fastlane/screenshots
|
|
||||||
fastlane/test_output
|
|
||||||
fastlane/readme.md
|
|
||||||
|
|
||||||
# Version control
|
|
||||||
vcs.xml
|
|
||||||
|
|
||||||
# lint
|
|
||||||
lint/intermediates/
|
|
||||||
lint/generated/
|
|
||||||
lint/outputs/
|
|
||||||
lint/tmp/
|
|
||||||
# lint/reports/
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# TF Lite Android App
|
|
||||||
|
|
||||||
## Building from Source with Bazel
|
|
||||||
|
|
||||||
1. Follow the [Bazel steps for the TF Demo App](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#bazel):
|
|
||||||
|
|
||||||
1. [Install Bazel and Android Prerequisites](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#install-bazel-and-android-prerequisites).
|
|
||||||
It's easiest with Android Studio.
|
|
||||||
|
|
||||||
- You'll need at least SDK version 23.
|
|
||||||
- Bazel requires Android Build Tools `26.0.1` or higher.
|
|
||||||
- You also need to install the Android Support Repository, available
|
|
||||||
through Android Studio under `Android SDK Manager -> SDK Tools ->
|
|
||||||
Android Support Repository`.
|
|
||||||
|
|
||||||
2. [Edit your `WORKSPACE`](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#edit-workspace)
|
|
||||||
to add SDK and NDK targets.
|
|
||||||
|
|
||||||
- Make sure the `api_level` in `WORKSPACE` is set to an SDK version that
|
|
||||||
you have installed.
|
|
||||||
- By default, Android Studio will install the SDK to `~/Android/Sdk` and
|
|
||||||
the NDK to `~/Android/Sdk/ndk-bundle`.
|
|
||||||
|
|
||||||
2. Build the app with Bazel. The demo needs C++11:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bazel build -c opt --cxxopt='--std=c++11' \
|
|
||||||
//tensorflow/contrib/lite/java/demo/app/src/main:TfLiteCameraDemo
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Install the demo on a
|
|
||||||
[debug-enabled device](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#install):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
adb install bazel-bin/tensorflow/contrib/lite/java/demo/app/src/main/TfLiteCameraDemo.apk
|
|
||||||
```
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
apply plugin: 'com.android.application'
|
|
||||||
|
|
||||||
project.ext.ASSET_DIR = projectDir.toString() + '/src/main/assets'
|
|
||||||
|
|
||||||
assert file(project.ext.ASSET_DIR + "/inception.tflite").exists()
|
|
||||||
assert file(project.ext.ASSET_DIR + "/labels.txt").exists()
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 26
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "android.example.com.tflitecamerademo"
|
|
||||||
minSdkVersion 21
|
|
||||||
targetSdkVersion 26
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
|
||||||
}
|
|
||||||
lintOptions {
|
|
||||||
abortOnError false
|
|
||||||
}
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aaptOptions {
|
|
||||||
noCompress "tflite"
|
|
||||||
noCompress "lite"
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url 'https://google.bintray.com/tensorflow'
|
|
||||||
}
|
|
||||||
google()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
|
|
||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
|
||||||
})
|
|
||||||
implementation 'com.android.support:appcompat-v7:25.2.0'
|
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
|
|
||||||
implementation 'com.android.support:design:25.2.0'
|
|
||||||
implementation 'com.android.support:support-annotations:25.3.1'
|
|
||||||
implementation 'com.android.support:support-v13:25.2.0'
|
|
||||||
|
|
||||||
implementation 'org.tensorflow:tensorflow-lite:+'
|
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright 2014 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.example.android.tflitecamerademo">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera" />
|
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
|
||||||
|
|
||||||
<application android:allowBackup="true"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:icon="@drawable/ic_launcher"
|
|
||||||
android:theme="@style/MaterialTheme">
|
|
||||||
|
|
||||||
<activity android:name="com.example.android.tflitecamerademo.CameraActivity"
|
|
||||||
android:label="@string/app_name">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package(default_visibility = ["//visibility:private"])
|
|
||||||
|
|
||||||
licenses(["notice"]) # Apache 2.0
|
|
||||||
|
|
||||||
exports_files(
|
|
||||||
glob(
|
|
||||||
["**/*"],
|
|
||||||
exclude = [
|
|
||||||
"BUILD",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all_files",
|
|
||||||
srcs = glob(
|
|
||||||
["**/*"],
|
|
||||||
exclude = [
|
|
||||||
"**/METADATA",
|
|
||||||
"**/OWNERS",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
visibility = ["//tensorflow:__subpackages__"],
|
|
||||||
)
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
abra
|
|
||||||
aerodactyl
|
|
||||||
aipom
|
|
||||||
alakazam
|
|
||||||
ampharos
|
|
||||||
arbok
|
|
||||||
arcanine
|
|
||||||
ariados
|
|
||||||
articuno
|
|
||||||
azumarill
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
|
|
||||||
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.example.android.tflitecamerademo;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.TextureView;
|
|
||||||
|
|
||||||
/** A {@link TextureView} that can be adjusted to a specified aspect ratio. */
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,708 +0,0 @@
|
|||||||
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
|
|
||||||
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.example.android.tflitecamerademo;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.app.DialogFragment;
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
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.CaptureRequest;
|
|
||||||
import android.hardware.camera2.CaptureResult;
|
|
||||||
import android.hardware.camera2.TotalCaptureResult;
|
|
||||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
|
||||||
import android.media.ImageReader;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.v13.app.FragmentCompat;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Size;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.Surface;
|
|
||||||
import android.view.TextureView;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/** Basic fragments for the Camera. */
|
|
||||||
public class Camera2BasicFragment extends Fragment
|
|
||||||
implements FragmentCompat.OnRequestPermissionsResultCallback {
|
|
||||||
|
|
||||||
/** Tag for the {@link Log}. */
|
|
||||||
private static final String TAG = "TfLiteCameraDemo";
|
|
||||||
|
|
||||||
private static final String FRAGMENT_DIALOG = "dialog";
|
|
||||||
|
|
||||||
private static final String HANDLE_THREAD_NAME = "CameraBackground";
|
|
||||||
|
|
||||||
private static final int PERMISSIONS_REQUEST_CODE = 1;
|
|
||||||
|
|
||||||
private final Object lock = new Object();
|
|
||||||
private boolean runClassifier = false;
|
|
||||||
private boolean checkedPermissions = false;
|
|
||||||
private TextView textView;
|
|
||||||
private ImageClassifier classifier;
|
|
||||||
|
|
||||||
/** Max preview width that is guaranteed by Camera2 API */
|
|
||||||
private static final int MAX_PREVIEW_WIDTH = 1920;
|
|
||||||
|
|
||||||
/** Max preview height that is guaranteed by Camera2 API */
|
|
||||||
private static final int MAX_PREVIEW_HEIGHT = 1080;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a {@link
|
|
||||||
* TextureView}.
|
|
||||||
*/
|
|
||||||
private final TextureView.SurfaceTextureListener surfaceTextureListener =
|
|
||||||
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(SurfaceTexture texture) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSurfaceTextureUpdated(SurfaceTexture texture) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** ID of the current {@link CameraDevice}. */
|
|
||||||
private String cameraId;
|
|
||||||
|
|
||||||
/** An {@link AutoFitTextureView} for camera preview. */
|
|
||||||
private AutoFitTextureView textureView;
|
|
||||||
|
|
||||||
/** A {@link CameraCaptureSession } for camera preview. */
|
|
||||||
private CameraCaptureSession captureSession;
|
|
||||||
|
|
||||||
/** A reference to the opened {@link CameraDevice}. */
|
|
||||||
private CameraDevice cameraDevice;
|
|
||||||
|
|
||||||
/** The {@link android.util.Size} of camera preview. */
|
|
||||||
private Size previewSize;
|
|
||||||
|
|
||||||
/** {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state. */
|
|
||||||
private final CameraDevice.StateCallback stateCallback =
|
|
||||||
new CameraDevice.StateCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOpened(@NonNull CameraDevice currentCameraDevice) {
|
|
||||||
// This method is called when the camera is opened. We start camera preview here.
|
|
||||||
cameraOpenCloseLock.release();
|
|
||||||
cameraDevice = currentCameraDevice;
|
|
||||||
createCameraPreviewSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisconnected(@NonNull CameraDevice currentCameraDevice) {
|
|
||||||
cameraOpenCloseLock.release();
|
|
||||||
currentCameraDevice.close();
|
|
||||||
cameraDevice = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(@NonNull CameraDevice currentCameraDevice, int error) {
|
|
||||||
cameraOpenCloseLock.release();
|
|
||||||
currentCameraDevice.close();
|
|
||||||
cameraDevice = null;
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (null != activity) {
|
|
||||||
activity.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** An additional thread for running tasks that shouldn't block the UI. */
|
|
||||||
private HandlerThread backgroundThread;
|
|
||||||
|
|
||||||
/** A {@link Handler} for running tasks in the background. */
|
|
||||||
private Handler backgroundHandler;
|
|
||||||
|
|
||||||
/** An {@link ImageReader} that handles image capture. */
|
|
||||||
private ImageReader imageReader;
|
|
||||||
|
|
||||||
/** {@link CaptureRequest.Builder} for the camera preview */
|
|
||||||
private CaptureRequest.Builder previewRequestBuilder;
|
|
||||||
|
|
||||||
/** {@link CaptureRequest} generated by {@link #previewRequestBuilder} */
|
|
||||||
private CaptureRequest previewRequest;
|
|
||||||
|
|
||||||
/** A {@link Semaphore} to prevent the app from exiting before closing the camera. */
|
|
||||||
private Semaphore cameraOpenCloseLock = new Semaphore(1);
|
|
||||||
|
|
||||||
/** A {@link CameraCaptureSession.CaptureCallback} that handles events related to capture. */
|
|
||||||
private CameraCaptureSession.CaptureCallback captureCallback =
|
|
||||||
new CameraCaptureSession.CaptureCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCaptureProgressed(
|
|
||||||
@NonNull CameraCaptureSession session,
|
|
||||||
@NonNull CaptureRequest request,
|
|
||||||
@NonNull CaptureResult partialResult) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCaptureCompleted(
|
|
||||||
@NonNull CameraCaptureSession session,
|
|
||||||
@NonNull CaptureRequest request,
|
|
||||||
@NonNull TotalCaptureResult result) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a {@link Toast} on the UI thread for the classification results.
|
|
||||||
*
|
|
||||||
* @param text The message to show
|
|
||||||
*/
|
|
||||||
private void showToast(final String text) {
|
|
||||||
final Activity activity = getActivity();
|
|
||||||
if (activity != null) {
|
|
||||||
activity.runOnUiThread(
|
|
||||||
new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
textView.setText(text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resizes image.
|
|
||||||
*
|
|
||||||
* Attempting to use too large a preview size could exceed the camera bus' bandwidth limitation,
|
|
||||||
* resulting in gorgeous previews but the storage of garbage capture data.
|
|
||||||
*
|
|
||||||
* Given {@code choices} of {@code Size}s supported by a camera, 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 camera 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
|
|
||||||
*/
|
|
||||||
private static 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() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
|
|
||||||
bigEnough.add(option);
|
|
||||||
} else {
|
|
||||||
notBigEnough.add(option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick the smallest of those big enough. If there is no one big enough, pick the
|
|
||||||
// largest of those not big enough.
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Camera2BasicFragment newInstance() {
|
|
||||||
return new Camera2BasicFragment();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Layout the preview and buttons. */
|
|
||||||
@Override
|
|
||||||
public View onCreateView(
|
|
||||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.fragment_camera2_basic, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Connect the buttons to their event handler. */
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(final View view, Bundle savedInstanceState) {
|
|
||||||
textureView = (AutoFitTextureView) view.findViewById(R.id.texture);
|
|
||||||
textView = (TextView) view.findViewById(R.id.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Load the model and labels. */
|
|
||||||
@Override
|
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
|
||||||
super.onActivityCreated(savedInstanceState);
|
|
||||||
try {
|
|
||||||
classifier = new ImageClassifier(getActivity());
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to initialize an image classifier.");
|
|
||||||
}
|
|
||||||
startBackgroundThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
startBackgroundThread();
|
|
||||||
|
|
||||||
// When the screen is turned off and turned back on, the SurfaceTexture is already
|
|
||||||
// available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
|
|
||||||
// a camera and start preview from here (otherwise, we wait until the surface is ready in
|
|
||||||
// the SurfaceTextureListener).
|
|
||||||
if (textureView.isAvailable()) {
|
|
||||||
openCamera(textureView.getWidth(), textureView.getHeight());
|
|
||||||
} else {
|
|
||||||
textureView.setSurfaceTextureListener(surfaceTextureListener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
closeCamera();
|
|
||||||
stopBackgroundThread();
|
|
||||||
super.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
classifier.close();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up member variables related to camera.
|
|
||||||
*
|
|
||||||
* @param width The width of available size for camera preview
|
|
||||||
* @param height The height of available size for camera preview
|
|
||||||
*/
|
|
||||||
private void setUpCameraOutputs(int width, int height) {
|
|
||||||
Activity activity = getActivity();
|
|
||||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
|
||||||
try {
|
|
||||||
for (String cameraId : manager.getCameraIdList()) {
|
|
||||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
|
|
||||||
|
|
||||||
// We don't use a front facing camera in this sample.
|
|
||||||
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
|
||||||
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamConfigurationMap map =
|
|
||||||
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
|
||||||
if (map == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// // For still image captures, we use the largest available size.
|
|
||||||
Size largest =
|
|
||||||
Collections.max(
|
|
||||||
Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new CompareSizesByArea());
|
|
||||||
imageReader =
|
|
||||||
ImageReader.newInstance(
|
|
||||||
largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, /*maxImages*/ 2);
|
|
||||||
|
|
||||||
// Find out if we need to swap dimension to get the preview size relative to sensor
|
|
||||||
// coordinate.
|
|
||||||
int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
|
|
||||||
// noinspection ConstantConditions
|
|
||||||
/* Orientation of the camera sensor */
|
|
||||||
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
|
|
||||||
boolean swappedDimensions = false;
|
|
||||||
switch (displayRotation) {
|
|
||||||
case Surface.ROTATION_0:
|
|
||||||
case Surface.ROTATION_180:
|
|
||||||
if (sensorOrientation == 90 || sensorOrientation == 270) {
|
|
||||||
swappedDimensions = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Surface.ROTATION_90:
|
|
||||||
case Surface.ROTATION_270:
|
|
||||||
if (sensorOrientation == 0 || sensorOrientation == 180) {
|
|
||||||
swappedDimensions = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Display rotation is invalid: " + displayRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point displaySize = new Point();
|
|
||||||
activity.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
previewSize =
|
|
||||||
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;
|
|
||||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
|
||||||
textureView.setAspectRatio(previewSize.getWidth(), previewSize.getHeight());
|
|
||||||
} else {
|
|
||||||
textureView.setAspectRatio(previewSize.getHeight(), previewSize.getWidth());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cameraId = cameraId;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
// Currently an NPE is thrown when the Camera2API is used but not supported on the
|
|
||||||
// device this code runs.
|
|
||||||
ErrorDialog.newInstance(getString(R.string.camera_error))
|
|
||||||
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getRequiredPermissions() {
|
|
||||||
Activity activity = getActivity();
|
|
||||||
try {
|
|
||||||
PackageInfo info =
|
|
||||||
activity
|
|
||||||
.getPackageManager()
|
|
||||||
.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
|
|
||||||
String[] ps = info.requestedPermissions;
|
|
||||||
if (ps != null && ps.length > 0) {
|
|
||||||
return ps;
|
|
||||||
} else {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Opens the camera specified by {@link Camera2BasicFragment#cameraId}. */
|
|
||||||
private void openCamera(int width, int height) {
|
|
||||||
if (!checkedPermissions && !allPermissionsGranted()) {
|
|
||||||
FragmentCompat.requestPermissions(this, getRequiredPermissions(), PERMISSIONS_REQUEST_CODE);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
checkedPermissions = true;
|
|
||||||
}
|
|
||||||
setUpCameraOutputs(width, height);
|
|
||||||
configureTransform(width, height);
|
|
||||||
Activity activity = getActivity();
|
|
||||||
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
|
||||||
try {
|
|
||||||
if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
|
||||||
throw new RuntimeException("Time out waiting to lock camera opening.");
|
|
||||||
}
|
|
||||||
manager.openCamera(cameraId, stateCallback, backgroundHandler);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean allPermissionsGranted() {
|
|
||||||
for (String permission : getRequiredPermissions()) {
|
|
||||||
if (ContextCompat.checkSelfPermission(getActivity(), permission)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(
|
|
||||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Closes the current {@link CameraDevice}. */
|
|
||||||
private void closeCamera() {
|
|
||||||
try {
|
|
||||||
cameraOpenCloseLock.acquire();
|
|
||||||
if (null != captureSession) {
|
|
||||||
captureSession.close();
|
|
||||||
captureSession = null;
|
|
||||||
}
|
|
||||||
if (null != cameraDevice) {
|
|
||||||
cameraDevice.close();
|
|
||||||
cameraDevice = null;
|
|
||||||
}
|
|
||||||
if (null != imageReader) {
|
|
||||||
imageReader.close();
|
|
||||||
imageReader = null;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
|
|
||||||
} finally {
|
|
||||||
cameraOpenCloseLock.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Starts a background thread and its {@link Handler}. */
|
|
||||||
private void startBackgroundThread() {
|
|
||||||
backgroundThread = new HandlerThread(HANDLE_THREAD_NAME);
|
|
||||||
backgroundThread.start();
|
|
||||||
backgroundHandler = new Handler(backgroundThread.getLooper());
|
|
||||||
synchronized (lock) {
|
|
||||||
runClassifier = true;
|
|
||||||
}
|
|
||||||
backgroundHandler.post(periodicClassify);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Stops the background thread and its {@link Handler}. */
|
|
||||||
private void stopBackgroundThread() {
|
|
||||||
backgroundThread.quitSafely();
|
|
||||||
try {
|
|
||||||
backgroundThread.join();
|
|
||||||
backgroundThread = null;
|
|
||||||
backgroundHandler = null;
|
|
||||||
synchronized (lock) {
|
|
||||||
runClassifier = false;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Takes photos and classify them periodically. */
|
|
||||||
private Runnable periodicClassify =
|
|
||||||
new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (lock) {
|
|
||||||
if (runClassifier) {
|
|
||||||
classifyFrame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
backgroundHandler.post(periodicClassify);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Creates a new {@link CameraCaptureSession} for camera preview. */
|
|
||||||
private void createCameraPreviewSession() {
|
|
||||||
try {
|
|
||||||
SurfaceTexture texture = textureView.getSurfaceTexture();
|
|
||||||
assert texture != null;
|
|
||||||
|
|
||||||
// We configure the size of default buffer to be the size of camera preview we want.
|
|
||||||
texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
|
||||||
|
|
||||||
// This is the output Surface we need to start preview.
|
|
||||||
Surface surface = new Surface(texture);
|
|
||||||
|
|
||||||
// We set up a CaptureRequest.Builder with the output Surface.
|
|
||||||
previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
|
||||||
previewRequestBuilder.addTarget(surface);
|
|
||||||
|
|
||||||
// Here, we create a CameraCaptureSession for camera preview.
|
|
||||||
cameraDevice.createCaptureSession(
|
|
||||||
Arrays.asList(surface),
|
|
||||||
new CameraCaptureSession.StateCallback() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
|
|
||||||
// The camera is already closed
|
|
||||||
if (null == cameraDevice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When the session is ready, we start displaying the preview.
|
|
||||||
captureSession = cameraCaptureSession;
|
|
||||||
try {
|
|
||||||
// Auto focus should be continuous for camera preview.
|
|
||||||
previewRequestBuilder.set(
|
|
||||||
CaptureRequest.CONTROL_AF_MODE,
|
|
||||||
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
|
||||||
|
|
||||||
// Finally, we start displaying the camera preview.
|
|
||||||
previewRequest = previewRequestBuilder.build();
|
|
||||||
captureSession.setRepeatingRequest(
|
|
||||||
previewRequest, captureCallback, backgroundHandler);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
|
|
||||||
showToast("Failed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
} catch (CameraAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the necessary {@link android.graphics.Matrix} transformation to `textureView`. This
|
|
||||||
* method should be called after the camera preview size is determined in setUpCameraOutputs and
|
|
||||||
* also the size of `textureView` is fixed.
|
|
||||||
*
|
|
||||||
* @param viewWidth The width of `textureView`
|
|
||||||
* @param viewHeight The height of `textureView`
|
|
||||||
*/
|
|
||||||
private void configureTransform(int viewWidth, int viewHeight) {
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (null == textureView || null == previewSize || 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, previewSize.getHeight(), previewSize.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 / previewSize.getHeight(),
|
|
||||||
(float) viewWidth / previewSize.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);
|
|
||||||
}
|
|
||||||
textureView.setTransform(matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Classifies a frame from the preview stream. */
|
|
||||||
private void classifyFrame() {
|
|
||||||
if (classifier == null || getActivity() == null || cameraDevice == null) {
|
|
||||||
showToast("Uninitialized Classifier or invalid context.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Bitmap bitmap =
|
|
||||||
textureView.getBitmap(ImageClassifier.DIM_IMG_SIZE_X, ImageClassifier.DIM_IMG_SIZE_Y);
|
|
||||||
String textToShow = classifier.classifyFrame(bitmap);
|
|
||||||
bitmap.recycle();
|
|
||||||
showToast(textToShow);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Compares two {@code Size}s based on their areas. */
|
|
||||||
private static 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Shows an error message dialog. */
|
|
||||||
public static class ErrorDialog extends DialogFragment {
|
|
||||||
|
|
||||||
private static final String ARG_MESSAGE = "message";
|
|
||||||
|
|
||||||
public static ErrorDialog newInstance(String message) {
|
|
||||||
ErrorDialog dialog = new ErrorDialog();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putString(ARG_MESSAGE, message);
|
|
||||||
dialog.setArguments(args);
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
||||||
final Activity activity = getActivity();
|
|
||||||
return new AlertDialog.Builder(activity)
|
|
||||||
.setMessage(getArguments().getString(ARG_MESSAGE))
|
|
||||||
.setPositiveButton(
|
|
||||||
android.R.string.ok,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
|
||||||
activity.finish();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
|
|
||||||
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.example.android.tflitecamerademo;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
/** Main {@code Activity} class for the Camera app. */
|
|
||||||
public class CameraActivity extends Activity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_camera);
|
|
||||||
if (null == savedInstanceState) {
|
|
||||||
getFragmentManager()
|
|
||||||
.beginTransaction()
|
|
||||||
.replace(R.id.container, Camera2BasicFragment.newInstance())
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
|
|
||||||
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.example.android.tflitecamerademo;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.res.AssetFileDescriptor;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.util.Log;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.MappedByteBuffer;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.PriorityQueue;
|
|
||||||
import org.tensorflow.lite.Interpreter;
|
|
||||||
|
|
||||||
/** Classifies images with Tensorflow Lite. */
|
|
||||||
public class ImageClassifier {
|
|
||||||
|
|
||||||
/** Tag for the {@link Log}. */
|
|
||||||
private static final String TAG = "TfLiteCameraDemo";
|
|
||||||
|
|
||||||
/** Name of the model file stored in Assets. */
|
|
||||||
private static final String MODEL_PATH = "inception.tflite";
|
|
||||||
|
|
||||||
/** Name of the label file stored in Assets. */
|
|
||||||
private static final String LABEL_PATH = "labels.txt";
|
|
||||||
|
|
||||||
/** Number of results to show in the UI. */
|
|
||||||
private static final int RESULTS_TO_SHOW = 3;
|
|
||||||
|
|
||||||
/** Dimensions of inputs. */
|
|
||||||
private static final int DIM_BATCH_SIZE = 1;
|
|
||||||
|
|
||||||
private static final int DIM_PIXEL_SIZE = 3;
|
|
||||||
|
|
||||||
static final int DIM_IMG_SIZE_X = 299;
|
|
||||||
static final int DIM_IMG_SIZE_Y = 299;
|
|
||||||
|
|
||||||
private static final int IMAGE_MEAN = 128;
|
|
||||||
private static final float IMAGE_STD = 128.0f;
|
|
||||||
|
|
||||||
|
|
||||||
/* Preallocated buffers for storing image data in. */
|
|
||||||
private int[] intValues = new int[DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y];
|
|
||||||
|
|
||||||
/** An instance of the driver class to run model inference with Tensorflow Lite. */
|
|
||||||
private Interpreter tflite;
|
|
||||||
|
|
||||||
/** Labels corresponding to the output of the vision model. */
|
|
||||||
private List<String> labelList;
|
|
||||||
|
|
||||||
/** A ByteBuffer to hold image data, to be feed into Tensorflow Lite as inputs. */
|
|
||||||
private ByteBuffer imgData = null;
|
|
||||||
|
|
||||||
/** An array to hold inference results, to be feed into Tensorflow Lite as outputs. */
|
|
||||||
private float[][] labelProbArray = null;
|
|
||||||
/** multi-stage low pass filter **/
|
|
||||||
private float[][] filterLabelProbArray = null;
|
|
||||||
private static final int FILTER_STAGES = 3;
|
|
||||||
private static final float FILTER_FACTOR = 0.4f;
|
|
||||||
|
|
||||||
private PriorityQueue<Map.Entry<String, Float>> sortedLabels =
|
|
||||||
new PriorityQueue<>(
|
|
||||||
RESULTS_TO_SHOW,
|
|
||||||
new Comparator<Map.Entry<String, Float>>() {
|
|
||||||
@Override
|
|
||||||
public int compare(Map.Entry<String, Float> o1, Map.Entry<String, Float> o2) {
|
|
||||||
return (o1.getValue()).compareTo(o2.getValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Initializes an {@code ImageClassifier}. */
|
|
||||||
ImageClassifier(Activity activity) throws IOException {
|
|
||||||
tflite = new Interpreter(loadModelFile(activity));
|
|
||||||
labelList = loadLabelList(activity);
|
|
||||||
imgData =
|
|
||||||
ByteBuffer.allocateDirect(
|
|
||||||
4 * DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE);
|
|
||||||
imgData.order(ByteOrder.nativeOrder());
|
|
||||||
labelProbArray = new float[1][labelList.size()];
|
|
||||||
filterLabelProbArray = new float[FILTER_STAGES][labelList.size()];
|
|
||||||
Log.d(TAG, "Created a Tensorflow Lite Image Classifier.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Classifies a frame from the preview stream. */
|
|
||||||
String classifyFrame(Bitmap bitmap) {
|
|
||||||
if (tflite == null) {
|
|
||||||
Log.e(TAG, "Image classifier has not been initialized; Skipped.");
|
|
||||||
return "Uninitialized Classifier.";
|
|
||||||
}
|
|
||||||
convertBitmapToByteBuffer(bitmap);
|
|
||||||
// Here's where the magic happens!!!
|
|
||||||
long startTime = SystemClock.uptimeMillis();
|
|
||||||
tflite.run(imgData, labelProbArray);
|
|
||||||
long endTime = SystemClock.uptimeMillis();
|
|
||||||
Log.d(TAG, "Timecost to run model inference: " + Long.toString(endTime - startTime));
|
|
||||||
|
|
||||||
// smooth the results
|
|
||||||
applyFilter();
|
|
||||||
|
|
||||||
// print the results
|
|
||||||
String textToShow = printTopKLabels();
|
|
||||||
textToShow = Long.toString(endTime - startTime) + "ms" + textToShow;
|
|
||||||
return textToShow;
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyFilter(){
|
|
||||||
int num_labels = labelList.size();
|
|
||||||
|
|
||||||
// Low pass filter `labelProbArray` into the first stage of the filter.
|
|
||||||
for(int j=0; j<num_labels; ++j){
|
|
||||||
filterLabelProbArray[0][j] += FILTER_FACTOR*(labelProbArray[0][j] -
|
|
||||||
filterLabelProbArray[0][j]);
|
|
||||||
}
|
|
||||||
// Low pass filter each stage into the next.
|
|
||||||
for (int i=1; i<FILTER_STAGES; ++i){
|
|
||||||
for(int j=0; j<num_labels; ++j){
|
|
||||||
filterLabelProbArray[i][j] += FILTER_FACTOR*(
|
|
||||||
filterLabelProbArray[i-1][j] -
|
|
||||||
filterLabelProbArray[i][j]);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the last stage filter output back to `labelProbArray`.
|
|
||||||
for(int j=0; j<num_labels; ++j){
|
|
||||||
labelProbArray[0][j] = filterLabelProbArray[FILTER_STAGES-1][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Closes tflite to release resources. */
|
|
||||||
public void close() {
|
|
||||||
tflite.close();
|
|
||||||
tflite = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reads label list from Assets. */
|
|
||||||
private List<String> loadLabelList(Activity activity) throws IOException {
|
|
||||||
List<String> labelList = new ArrayList<String>();
|
|
||||||
BufferedReader reader =
|
|
||||||
new BufferedReader(new InputStreamReader(activity.getAssets().open(LABEL_PATH)));
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
labelList.add(line);
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
return labelList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Memory-map the model file in Assets. */
|
|
||||||
private MappedByteBuffer loadModelFile(Activity activity) throws IOException {
|
|
||||||
AssetFileDescriptor fileDescriptor = activity.getAssets().openFd(MODEL_PATH);
|
|
||||||
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
|
|
||||||
FileChannel fileChannel = inputStream.getChannel();
|
|
||||||
long startOffset = fileDescriptor.getStartOffset();
|
|
||||||
long declaredLength = fileDescriptor.getDeclaredLength();
|
|
||||||
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Writes Image data into a {@code ByteBuffer}. */
|
|
||||||
private void convertBitmapToByteBuffer(Bitmap bitmap) {
|
|
||||||
if (imgData == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
imgData.rewind();
|
|
||||||
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
|
|
||||||
// Convert the image to floating point.
|
|
||||||
int pixel = 0;
|
|
||||||
long startTime = SystemClock.uptimeMillis();
|
|
||||||
for (int i = 0; i < DIM_IMG_SIZE_X; ++i) {
|
|
||||||
for (int j = 0; j < DIM_IMG_SIZE_Y; ++j) {
|
|
||||||
final int val = intValues[pixel++];
|
|
||||||
imgData.putFloat((((val >> 16) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
|
|
||||||
imgData.putFloat((((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
|
|
||||||
imgData.putFloat((((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long endTime = SystemClock.uptimeMillis();
|
|
||||||
Log.d(TAG, "Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Prints top-K labels, to be shown in UI as the results. */
|
|
||||||
private String printTopKLabels() {
|
|
||||||
for (int i = 0; i < labelList.size(); ++i) {
|
|
||||||
sortedLabels.add(
|
|
||||||
new AbstractMap.SimpleEntry<>(labelList.get(i), labelProbArray[0][i]));
|
|
||||||
if (sortedLabels.size() > RESULTS_TO_SHOW) {
|
|
||||||
sortedLabels.poll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String textToShow = "";
|
|
||||||
final int size = sortedLabels.size();
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
Map.Entry<String, Float> label = sortedLabels.poll();
|
|
||||||
textToShow = String.format("\n%s: %4.2f",label.getKey(),label.getValue()) + textToShow;
|
|
||||||
}
|
|
||||||
return textToShow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 116 B |
|
Before Width: | Height: | Size: 320 B |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 611 B |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 952 B |
|
Before Width: | Height: | Size: 7.1 KiB |
@@ -1,50 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2014 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.example.android.tflitecamerademo.AutoFitTextureView
|
|
||||||
android:id="@+id/texture"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/control"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_toRightOf="@id/texture"
|
|
||||||
android:background="@color/control_background"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView android:id="@+id/text"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="20dp"
|
|
||||||
android:textColor="#FFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2014 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="#000"
|
|
||||||
tools:context="com.example.android.tflitecamerademo.CameraActivity" />
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2014 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.example.android.tflitecamerademo.AutoFitTextureView
|
|
||||||
android:id="@+id/texture"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/control"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="112dp"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:background="@color/control_background">
|
|
||||||
|
|
||||||
<TextView android:id="@+id/text"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingLeft="80dp"
|
|
||||||
android:textColor="#FFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Semantic definitions -->
|
|
||||||
|
|
||||||
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
|
|
||||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<style name="Widget.SampleMessage">
|
|
||||||
<item name="android:textAppearance">?android:textAppearanceLarge</item>
|
|
||||||
<item name="android:lineSpacingMultiplier">1.2</item>
|
|
||||||
<item name="android:shadowDy">-6.5</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Activity themes -->
|
|
||||||
<style name="Theme.Base" parent="android:Theme.Holo.Light" />
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Activity themes -->
|
|
||||||
<style name="Theme.Base" parent="android:Theme.Material.Light">
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">TensorDex</string>
|
|
||||||
<string name="intro_message">
|
|
||||||
<![CDATA[
|
|
||||||
|
|
||||||
|
|
||||||
This sample demonstrates the basic use of TfLite API. Check the source code to see how
|
|
||||||
you can use TfLite for efficient, on-device inference with trained TensorFlow models.
|
|
||||||
|
|
||||||
|
|
||||||
]]>
|
|
||||||
</string>
|
|
||||||
</resources>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright 2015 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<color name="control_background">#cc4285f4</color>
|
|
||||||
</resources>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2014 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<string name="picture">Picture</string>
|
|
||||||
<string name="description_info">Info</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="toggle_turn_on">NN:On</string>
|
|
||||||
<string name="toggle_turn_off">NN:Off</string>
|
|
||||||
<string name="toggle">Use NNAPI</string>
|
|
||||||
</resources>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2014 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<style name="MaterialTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen" />
|
|
||||||
</resources>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
|
|
||||||
|
|
||||||
<dimen name="margin_tiny">4dp</dimen>
|
|
||||||
<dimen name="margin_small">8dp</dimen>
|
|
||||||
<dimen name="margin_medium">16dp</dimen>
|
|
||||||
<dimen name="margin_large">32dp</dimen>
|
|
||||||
<dimen name="margin_huge">64dp</dimen>
|
|
||||||
|
|
||||||
<!-- Semantic definitions -->
|
|
||||||
|
|
||||||
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
|
|
||||||
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<!--
|
|
||||||
Copyright 2013 The Android Open Source Project
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Activity themes -->
|
|
||||||
|
|
||||||
<style name="Theme.Base" parent="android:Theme.Light" />
|
|
||||||
|
|
||||||
<style name="Theme.Sample" parent="Theme.Base" />
|
|
||||||
|
|
||||||
<style name="AppTheme" parent="Theme.Sample" />
|
|
||||||
<!-- Widget styling -->
|
|
||||||
|
|
||||||
<style name="Widget" />
|
|
||||||
|
|
||||||
<style name="Widget.SampleMessage">
|
|
||||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
|
||||||
<item name="android:lineSpacingMultiplier">1.1</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="Widget.SampleMessageTile">
|
|
||||||
<item name="android:background">@drawable/tile</item>
|
|
||||||
<item name="android:shadowColor">#7F000000</item>
|
|
||||||
<item name="android:shadowDy">-3.5</item>
|
|
||||||
<item name="android:shadowRadius">2</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
||||||
|
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
google()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
|
||||||
// in the individual module build.gradle files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task clean(type: Delete) {
|
|
||||||
delete rootProject.buildDir
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# 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=-Xmx1536m
|
|
||||||
|
|
||||||
# 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
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#Sun Apr 14 18:55:46 CDT 2019
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
##
|
|
||||||
## Gradle start up script for UN*X
|
|
||||||
##
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS=""
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=`basename "$0"`
|
|
||||||
|
|
||||||
# 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
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN* )
|
|
||||||
cygwin=true
|
|
||||||
;;
|
|
||||||
Darwin* )
|
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
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" ] ; 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
|
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
|
||||||
function splitJvmOpts() {
|
|
||||||
JVM_OPTS=("$@")
|
|
||||||
}
|
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
@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
|
|
||||||
|
|
||||||
@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=
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
|
||||||
set APP_BASE_NAME=%~n0
|
|
||||||
set APP_HOME=%DIRNAME%
|
|
||||||
|
|
||||||
@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 Windowz variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_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=%*
|
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
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
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
include ':app'
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
/data/*.txt
|
|
||||||
/data/*lite
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
# Xcode
|
|
||||||
#
|
|
||||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
|
||||||
|
|
||||||
## Build generated
|
|
||||||
build/
|
|
||||||
DerivedData/
|
|
||||||
|
|
||||||
## Various settings
|
|
||||||
*.pbxuser
|
|
||||||
!default.pbxuser
|
|
||||||
*.mode1v3
|
|
||||||
!default.mode1v3
|
|
||||||
*.mode2v3
|
|
||||||
!default.mode2v3
|
|
||||||
*.perspectivev3
|
|
||||||
!default.perspectivev3
|
|
||||||
xcuserdata/
|
|
||||||
|
|
||||||
## Other
|
|
||||||
*.moved-aside
|
|
||||||
*.xccheckout
|
|
||||||
*.xcscmblueprint
|
|
||||||
|
|
||||||
## Obj-C/Swift specific
|
|
||||||
*.hmap
|
|
||||||
*.ipa
|
|
||||||
*.dSYM.zip
|
|
||||||
*.dSYM
|
|
||||||
|
|
||||||
## Playgrounds
|
|
||||||
timeline.xctimeline
|
|
||||||
playground.xcworkspace
|
|
||||||
|
|
||||||
# Swift Package Manager
|
|
||||||
#
|
|
||||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
|
||||||
# Packages/
|
|
||||||
# Package.pins
|
|
||||||
# Package.resolved
|
|
||||||
.build/
|
|
||||||
|
|
||||||
# CocoaPods
|
|
||||||
#
|
|
||||||
# We recommend against adding the Pods directory to your .gitignore. However
|
|
||||||
# you should judge for yourself, the pros and cons are mentioned at:
|
|
||||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
|
||||||
#
|
|
||||||
# Pods/
|
|
||||||
#
|
|
||||||
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
|
||||||
# *.xcworkspace
|
|
||||||
|
|
||||||
# Carthage
|
|
||||||
#
|
|
||||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
|
||||||
# Carthage/Checkouts
|
|
||||||
|
|
||||||
Carthage/Build
|
|
||||||
|
|
||||||
# fastlane
|
|
||||||
#
|
|
||||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
|
||||||
# screenshots whenever they are needed.
|
|
||||||
# For more information about the recommended setup visit:
|
|
||||||
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
|
||||||
|
|
||||||
fastlane/report.xml
|
|
||||||
fastlane/Preview.html
|
|
||||||
fastlane/screenshots/**/*.png
|
|
||||||
fastlane/test_output
|
|
||||||
|
|
||||||
# Code Injection
|
|
||||||
#
|
|
||||||
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
|
||||||
# https://github.com/johnno1962/injectionforxcode
|
|
||||||
|
|
||||||
iOSInjectionProject/
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"size": "20x20",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-2.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "20x20",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-3.png",
|
|
||||||
"scale": "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "29x29",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-4.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "29x29",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-5.png",
|
|
||||||
"scale": "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "40x40",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-6.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "40x40",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-7.png",
|
|
||||||
"scale": "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "60x60",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo-1.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "60x60",
|
|
||||||
"idiom": "iphone",
|
|
||||||
"filename": "logo.png",
|
|
||||||
"scale": "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "20x20",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-8.png",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "20x20",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-9.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "29x29",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-10.png",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "29x29",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-11.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "40x40",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-12.png",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "40x40",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-13.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "76x76",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-14.png",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "76x76",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-15.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "83.5x83.5",
|
|
||||||
"idiom": "ipad",
|
|
||||||
"filename": "logo-16.png",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": "1024x1024",
|
|
||||||
"idiom": "ios-marketing",
|
|
||||||
"filename": "logo-17.png",
|
|
||||||
"scale": "1x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"version": 1,
|
|
||||||
"author": "xcode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"info": {
|
|
||||||
"version": 1,
|
|
||||||
"author": "xcode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
@interface CameraExampleAppDelegate : UIResponder<UIApplicationDelegate>
|
|
||||||
|
|
||||||
@property(strong, nonatomic) UIWindow* window;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
#import "CameraExampleAppDelegate.h"
|
|
||||||
|
|
||||||
@implementation CameraExampleAppDelegate
|
|
||||||
|
|
||||||
@synthesize window = _window;
|
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application
|
|
||||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
|
||||||
[self.window makeKeyAndVisible];
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
|
||||||
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
|
||||||
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
#import <AVFoundation/AVFoundation.h>
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
#import <Photos/Photos.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "tensorflow/contrib/lite/kernels/register.h"
|
|
||||||
#include "tensorflow/contrib/lite/model.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int channels;
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
} image_data;
|
|
||||||
|
|
||||||
|
|
||||||
@interface CameraExampleViewController
|
|
||||||
: UIViewController<UIGestureRecognizerDelegate, AVCaptureVideoDataOutputSampleBufferDelegate> {
|
|
||||||
IBOutlet UIView* previewView;
|
|
||||||
CALayer* previewLayer;
|
|
||||||
UIView* flashView;
|
|
||||||
NSMutableArray* labelLayers;
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::string> labels;
|
|
||||||
std::unique_ptr<tflite::FlatBufferModel> model;
|
|
||||||
tflite::ops::builtin::BuiltinOpResolver resolver;
|
|
||||||
std::unique_ptr<tflite::Interpreter> interpreter;
|
|
||||||
|
|
||||||
double total_latency;
|
|
||||||
int total_count;
|
|
||||||
|
|
||||||
int photos_index;
|
|
||||||
PHFetchResult *photos;
|
|
||||||
|
|
||||||
UIImage* input_image;
|
|
||||||
UIImage* display_image;
|
|
||||||
}
|
|
||||||
@property(strong, nonatomic) CATextLayer* predictionTextLayer;
|
|
||||||
|
|
||||||
- (IBAction)takePicture:(id)sender;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@@ -1,467 +0,0 @@
|
|||||||
// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
#import "CameraExampleViewController.h"
|
|
||||||
#import <AssertMacros.h>
|
|
||||||
#import <AssetsLibrary/AssetsLibrary.h>
|
|
||||||
#import <CoreImage/CoreImage.h>
|
|
||||||
#import <ImageIO/ImageIO.h>
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include "tensorflow/contrib/lite/kernels/register.h"
|
|
||||||
#include "tensorflow/contrib/lite/model.h"
|
|
||||||
#include "tensorflow/contrib/lite/string_util.h"
|
|
||||||
#include "tensorflow/contrib/lite/mutable_op_resolver.h"
|
|
||||||
|
|
||||||
#define LOG(x) std::cerr
|
|
||||||
|
|
||||||
// If you have your own model, modify this to the file name, and make sure
|
|
||||||
// you've added the file to your app resources too.
|
|
||||||
static NSString* model_file_name = @"graph";
|
|
||||||
static NSString* model_file_type = @"lite";
|
|
||||||
|
|
||||||
// If you have your own model, point this to the labels file.
|
|
||||||
static NSString* labels_file_name = @"labels";
|
|
||||||
static NSString* labels_file_type = @"txt";
|
|
||||||
|
|
||||||
// These dimensions need to match those the model was trained with.
|
|
||||||
static const int wanted_input_width = 224;
|
|
||||||
static const int wanted_input_height = 224;
|
|
||||||
static const int wanted_input_channels = 3;
|
|
||||||
|
|
||||||
static NSString* FilePathForResourceName(NSString* name, NSString* extension) {
|
|
||||||
NSString* file_path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
|
|
||||||
if (file_path == NULL) {
|
|
||||||
LOG(FATAL) << "Couldn't find '" << [name UTF8String] << "." << [extension UTF8String]
|
|
||||||
<< "' in bundle.";
|
|
||||||
}
|
|
||||||
return file_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LoadLabels(NSString* file_name, NSString* file_type,
|
|
||||||
std::vector<std::string>* label_strings) {
|
|
||||||
NSString* labels_path = FilePathForResourceName(file_name, file_type);
|
|
||||||
if (!labels_path) {
|
|
||||||
LOG(ERROR) << "Failed to find model proto at" << [file_name UTF8String]
|
|
||||||
<< [file_type UTF8String];
|
|
||||||
}
|
|
||||||
std::ifstream t;
|
|
||||||
t.open([labels_path UTF8String]);
|
|
||||||
std::string line;
|
|
||||||
while (t) {
|
|
||||||
std::getline(t, line);
|
|
||||||
if (line.length()){
|
|
||||||
label_strings->push_back(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the top N confidence values over threshold in the provided vector,
|
|
||||||
// sorted by confidence in descending order.
|
|
||||||
static void GetTopN(const float* prediction, const int prediction_size, const int num_results,
|
|
||||||
const float threshold, std::vector<std::pair<float, int>>* top_results) {
|
|
||||||
// Will contain top N results in ascending order.
|
|
||||||
std::priority_queue<std::pair<float, int>, std::vector<std::pair<float, int>>,
|
|
||||||
std::greater<std::pair<float, int>>>
|
|
||||||
top_result_pq;
|
|
||||||
|
|
||||||
const long count = prediction_size;
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
const float value = prediction[i];
|
|
||||||
// Only add it if it beats the threshold and has a chance at being in
|
|
||||||
// the top N.
|
|
||||||
if (value < threshold) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
top_result_pq.push(std::pair<float, int>(value, i));
|
|
||||||
|
|
||||||
// If at capacity, kick the smallest value out.
|
|
||||||
if (top_result_pq.size() > num_results) {
|
|
||||||
top_result_pq.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy to output vector and reverse into descending order.
|
|
||||||
while (!top_result_pq.empty()) {
|
|
||||||
top_results->push_back(top_result_pq.top());
|
|
||||||
top_result_pq.pop();
|
|
||||||
}
|
|
||||||
std::reverse(top_results->begin(), top_results->end());
|
|
||||||
}
|
|
||||||
|
|
||||||
@interface CameraExampleViewController (InternalMethods)
|
|
||||||
- (void)teardownAVCapture;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation CameraExampleViewController
|
|
||||||
|
|
||||||
- (void) attachPreviewLayer{
|
|
||||||
photos_index = 0;
|
|
||||||
photos = nil;
|
|
||||||
previewLayer = [[CALayer alloc] init];
|
|
||||||
|
|
||||||
[previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
|
|
||||||
CALayer* rootLayer = [previewView layer];
|
|
||||||
[rootLayer setMasksToBounds:YES];
|
|
||||||
[previewLayer setFrame:[rootLayer bounds]];
|
|
||||||
[rootLayer addSublayer:previewLayer];
|
|
||||||
|
|
||||||
[self UpdatePhoto];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)UpdatePhoto{
|
|
||||||
PHAsset* asset;
|
|
||||||
if (photos==nil || photos_index >= photos.count){
|
|
||||||
[self updatePhotosLibrary];
|
|
||||||
photos_index=0;
|
|
||||||
}
|
|
||||||
if (photos.count){
|
|
||||||
asset = photos[photos_index];
|
|
||||||
photos_index += 1;
|
|
||||||
input_image = [self convertImageFromAsset:asset
|
|
||||||
targetSize:CGSizeMake(wanted_input_width, wanted_input_height)
|
|
||||||
mode:PHImageContentModeAspectFill];
|
|
||||||
display_image = [self convertImageFromAsset:asset
|
|
||||||
targetSize:CGSizeMake(asset.pixelWidth,asset.pixelHeight)
|
|
||||||
mode:PHImageContentModeAspectFit];
|
|
||||||
[self DrawImage];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input_image != nil){
|
|
||||||
image_data image = [self CGImageToPixels:input_image.CGImage];
|
|
||||||
[self inputImageToModel:image];
|
|
||||||
[self runModel];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)DrawImage{
|
|
||||||
CGFloat view_height = 800;
|
|
||||||
CGFloat view_width = 600;
|
|
||||||
|
|
||||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(view_width, view_height), NO, 0.0);
|
|
||||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
||||||
UIGraphicsPushContext(context);
|
|
||||||
|
|
||||||
float scale = view_width/display_image.size.width;
|
|
||||||
|
|
||||||
if (display_image.size.height*scale > view_height){
|
|
||||||
scale = view_height/display_image.size.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGPoint origin = CGPointMake((view_width - display_image.size.width*scale) / 2.0f,
|
|
||||||
(view_height - display_image.size.height*scale) / 2.0f);
|
|
||||||
[display_image drawInRect:CGRectMake(origin.x, origin.y,
|
|
||||||
display_image.size.width*scale,
|
|
||||||
display_image.size.height*scale)];
|
|
||||||
UIGraphicsPopContext();
|
|
||||||
display_image = UIGraphicsGetImageFromCurrentImageContext();
|
|
||||||
UIGraphicsEndImageContext();
|
|
||||||
previewLayer.contents = (id) display_image.CGImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)teardownAVCapture {
|
|
||||||
[previewLayer removeFromSuperlayer];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) updatePhotosLibrary{
|
|
||||||
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
|
|
||||||
fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
|
|
||||||
photos = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIImage *) convertImageFromAsset:(PHAsset *)asset
|
|
||||||
targetSize:(CGSize) targetSize
|
|
||||||
mode:(PHImageContentMode) mode{
|
|
||||||
PHImageManager * manager = [[PHImageManager alloc] init];
|
|
||||||
PHImageRequestOptions * options = [[PHImageRequestOptions alloc] init];
|
|
||||||
NSMutableArray * images = [[NSMutableArray alloc] init];
|
|
||||||
NSMutableArray * infos = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
options.synchronous = TRUE;
|
|
||||||
|
|
||||||
[manager requestImageForAsset:asset
|
|
||||||
targetSize:targetSize
|
|
||||||
contentMode:mode
|
|
||||||
options:options
|
|
||||||
resultHandler:^(UIImage *image, NSDictionary *info){
|
|
||||||
[images addObject:image];
|
|
||||||
[infos addObject:info];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
UIImage *result = images[0];
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:
|
|
||||||
(UIDeviceOrientation)deviceOrientation {
|
|
||||||
AVCaptureVideoOrientation result = (AVCaptureVideoOrientation)(deviceOrientation);
|
|
||||||
if (deviceOrientation == UIDeviceOrientationLandscapeLeft)
|
|
||||||
result = AVCaptureVideoOrientationLandscapeRight;
|
|
||||||
else if (deviceOrientation == UIDeviceOrientationLandscapeRight)
|
|
||||||
result = AVCaptureVideoOrientationLandscapeLeft;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (image_data)CGImageToPixels:(CGImage *)image {
|
|
||||||
image_data result;
|
|
||||||
result.width = (int)CGImageGetWidth(image);
|
|
||||||
result.height = (int)CGImageGetHeight(image);
|
|
||||||
result.channels = 4;
|
|
||||||
|
|
||||||
CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
|
|
||||||
const int bytes_per_row = (result.width * result.channels);
|
|
||||||
const int bytes_in_image = (bytes_per_row * result.height);
|
|
||||||
result.data = std::vector<uint8_t>(bytes_in_image);
|
|
||||||
const int bits_per_component = 8;
|
|
||||||
|
|
||||||
CGContextRef context =
|
|
||||||
CGBitmapContextCreate(result.data.data(), result.width, result.height, bits_per_component, bytes_per_row,
|
|
||||||
color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
|
||||||
CGColorSpaceRelease(color_space);
|
|
||||||
CGContextDrawImage(context, CGRectMake(0, 0, result.width, result.height), image);
|
|
||||||
CGContextRelease(context);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- (IBAction)takePicture:(id)sender {
|
|
||||||
[self UpdatePhoto];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)inputImageToModel:(image_data)image{
|
|
||||||
float* out = interpreter->typed_input_tensor<float>(0);
|
|
||||||
|
|
||||||
const float input_mean = 127.5f;
|
|
||||||
const float input_std = 127.5f;
|
|
||||||
assert(image.channels >= wanted_input_channels);
|
|
||||||
uint8_t* in = image.data.data();
|
|
||||||
|
|
||||||
for (int y = 0; y < wanted_input_height; ++y) {
|
|
||||||
const int in_y = (y * image.height) / wanted_input_height;
|
|
||||||
uint8_t* in_row = in + (in_y * image.width * image.channels);
|
|
||||||
float* out_row = out + (y * wanted_input_width * wanted_input_channels);
|
|
||||||
for (int x = 0; x < wanted_input_width; ++x) {
|
|
||||||
const int in_x = (x * image.width) / wanted_input_width;
|
|
||||||
uint8_t* in_pixel = in_row + (in_x * image.channels);
|
|
||||||
float* out_pixel = out_row + (x * wanted_input_channels);
|
|
||||||
for (int c = 0; c < wanted_input_channels; ++c) {
|
|
||||||
out_pixel[c] = (in_pixel[c] - input_mean) / input_std;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)runModel {
|
|
||||||
double startTimestamp = [[NSDate new] timeIntervalSince1970];
|
|
||||||
if (interpreter->Invoke() != kTfLiteOk) {
|
|
||||||
LOG(FATAL) << "Failed to invoke!";
|
|
||||||
}
|
|
||||||
double endTimestamp = [[NSDate new] timeIntervalSince1970];
|
|
||||||
total_latency += (endTimestamp - startTimestamp);
|
|
||||||
total_count += 1;
|
|
||||||
NSLog(@"Time: %.4lf, avg: %.4lf, count: %d", endTimestamp - startTimestamp,
|
|
||||||
total_latency / total_count, total_count);
|
|
||||||
|
|
||||||
const int output_size = (int)labels.size();
|
|
||||||
const int kNumResults = 5;
|
|
||||||
const float kThreshold = 0.1f;
|
|
||||||
|
|
||||||
std::vector<std::pair<float, int>> top_results;
|
|
||||||
|
|
||||||
float* output = interpreter->typed_output_tensor<float>(0);
|
|
||||||
GetTopN(output, output_size, kNumResults, kThreshold, &top_results);
|
|
||||||
|
|
||||||
std::vector<std::pair<float, std::string>> newValues;
|
|
||||||
for (const auto& result : top_results) {
|
|
||||||
std::pair<float, std::string> item;
|
|
||||||
item.first = result.first;
|
|
||||||
item.second = labels[result.second];
|
|
||||||
|
|
||||||
newValues.push_back(item);
|
|
||||||
}
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
|
||||||
[self setPredictionValues:newValues];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc {
|
|
||||||
[self teardownAVCapture];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)didReceiveMemoryWarning {
|
|
||||||
[super didReceiveMemoryWarning];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
|
||||||
[super viewDidLoad];
|
|
||||||
labelLayers = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
NSString* graph_path = FilePathForResourceName(model_file_name, model_file_type);
|
|
||||||
model = tflite::FlatBufferModel::BuildFromFile([graph_path UTF8String]);
|
|
||||||
if (!model) {
|
|
||||||
LOG(FATAL) << "Failed to mmap model " << graph_path;
|
|
||||||
}
|
|
||||||
LOG(INFO) << "Loaded model " << graph_path;
|
|
||||||
model->error_reporter();
|
|
||||||
LOG(INFO) << "resolved reporter";
|
|
||||||
|
|
||||||
tflite::ops::builtin::BuiltinOpResolver resolver;
|
|
||||||
LoadLabels(labels_file_name, labels_file_type, &labels);
|
|
||||||
|
|
||||||
tflite::InterpreterBuilder(*model, resolver)(&interpreter);
|
|
||||||
if (!interpreter) {
|
|
||||||
LOG(FATAL) << "Failed to construct interpreter";
|
|
||||||
}
|
|
||||||
if (interpreter->AllocateTensors() != kTfLiteOk) {
|
|
||||||
LOG(FATAL) << "Failed to allocate tensors!";
|
|
||||||
}
|
|
||||||
|
|
||||||
[self attachPreviewLayer];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewDidUnload {
|
|
||||||
[super viewDidUnload];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
|
||||||
[super viewWillAppear:animated];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
|
||||||
[super viewDidAppear:animated];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewWillDisappear:(BOOL)animated {
|
|
||||||
[super viewWillDisappear:animated];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)viewDidDisappear:(BOOL)animated {
|
|
||||||
[super viewDidDisappear:animated];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
|
||||||
return (interfaceOrientation == UIInterfaceOrientationPortrait);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)prefersStatusBarHidden {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setPredictionValues:(std::vector<std::pair<float, std::string>>)newValues {
|
|
||||||
|
|
||||||
const float leftMargin = 10.0f;
|
|
||||||
const float topMargin = 10.0f;
|
|
||||||
|
|
||||||
const float valueWidth = 48.0f;
|
|
||||||
const float valueHeight = 18.0f;
|
|
||||||
|
|
||||||
const float labelWidth = 246.0f;
|
|
||||||
const float labelHeight = 18.0f;
|
|
||||||
|
|
||||||
const float labelMarginX = 5.0f;
|
|
||||||
const float labelMarginY = 5.0f;
|
|
||||||
|
|
||||||
[self removeAllLabelLayers];
|
|
||||||
|
|
||||||
int labelCount = 0;
|
|
||||||
for (const auto& item : newValues) {
|
|
||||||
std::string label = item.second;
|
|
||||||
const float value = item.first;
|
|
||||||
const float originY = topMargin + ((labelHeight + labelMarginY) * labelCount);
|
|
||||||
const int valuePercentage = (int)roundf(value * 100.0f);
|
|
||||||
|
|
||||||
const float valueOriginX = leftMargin;
|
|
||||||
NSString* valueText = [NSString stringWithFormat:@"%d%%", valuePercentage];
|
|
||||||
|
|
||||||
[self addLabelLayerWithText:valueText
|
|
||||||
originX:valueOriginX
|
|
||||||
originY:originY
|
|
||||||
width:valueWidth
|
|
||||||
height:valueHeight
|
|
||||||
alignment:kCAAlignmentRight];
|
|
||||||
|
|
||||||
const float labelOriginX = (leftMargin + valueWidth + labelMarginX);
|
|
||||||
|
|
||||||
NSString *nsLabel = [NSString stringWithCString:label.c_str()
|
|
||||||
encoding:[NSString defaultCStringEncoding]];
|
|
||||||
[self addLabelLayerWithText:[nsLabel capitalizedString]
|
|
||||||
originX:labelOriginX
|
|
||||||
originY:originY
|
|
||||||
width:labelWidth
|
|
||||||
height:labelHeight
|
|
||||||
alignment:kCAAlignmentLeft];
|
|
||||||
|
|
||||||
labelCount += 1;
|
|
||||||
if (labelCount > 4) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)removeAllLabelLayers {
|
|
||||||
for (CATextLayer* layer in labelLayers) {
|
|
||||||
[layer removeFromSuperlayer];
|
|
||||||
}
|
|
||||||
[labelLayers removeAllObjects];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)addLabelLayerWithText:(NSString*)text
|
|
||||||
originX:(float)originX
|
|
||||||
originY:(float)originY
|
|
||||||
width:(float)width
|
|
||||||
height:(float)height
|
|
||||||
alignment:(NSString*)alignment {
|
|
||||||
CFTypeRef font = (CFTypeRef) @"Menlo-Regular";
|
|
||||||
const float fontSize = 12.0;
|
|
||||||
const float marginSizeX = 5.0f;
|
|
||||||
const float marginSizeY = 2.0f;
|
|
||||||
|
|
||||||
const CGRect backgroundBounds = CGRectMake(originX, originY, width, height);
|
|
||||||
const CGRect textBounds = CGRectMake((originX + marginSizeX), (originY + marginSizeY),
|
|
||||||
(width - (marginSizeX * 2)), (height - (marginSizeY * 2)));
|
|
||||||
|
|
||||||
CATextLayer* background = [CATextLayer layer];
|
|
||||||
[background setBackgroundColor:[UIColor blackColor].CGColor];
|
|
||||||
[background setOpacity:0.5f];
|
|
||||||
[background setFrame:backgroundBounds];
|
|
||||||
background.cornerRadius = 5.0f;
|
|
||||||
|
|
||||||
[[self.view layer] addSublayer:background];
|
|
||||||
[labelLayers addObject:background];
|
|
||||||
|
|
||||||
CATextLayer* layer = [CATextLayer layer];
|
|
||||||
[layer setForegroundColor:[UIColor whiteColor].CGColor];
|
|
||||||
[layer setFrame:textBounds];
|
|
||||||
[layer setAlignmentMode:alignment];
|
|
||||||
[layer setWrapped:YES];
|
|
||||||
[layer setFont:font];
|
|
||||||
[layer setFontSize:fontSize];
|
|
||||||
layer.contentsScale = [[UIScreen mainScreen] scale];
|
|
||||||
[layer setString:text];
|
|
||||||
|
|
||||||
[[self.view layer] addSublayer:layer];
|
|
||||||
[labelLayers addObject:layer];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>en</string>
|
|
||||||
<key>CFBundleDisplayName</key>
|
|
||||||
<string>tflite_photos_example</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>${EXECUTABLE_NAME}</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>${PRODUCT_NAME}</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>APPL</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>LSRequiresIPhoneOS</key>
|
|
||||||
<true/>
|
|
||||||
<key>NSCameraUsageDescription</key>
|
|
||||||
<string>Capture images to detect object</string>
|
|
||||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
|
||||||
<string>This app requires access to the photo library.</string>
|
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
|
||||||
<string>This App classifies images from your photos library.</string>
|
|
||||||
<key>UIMainStoryboardFile</key>
|
|
||||||
<string>MainStoryboard_iPhone</string>
|
|
||||||
<key>UIRequiresFullScreen</key>
|
|
||||||
<true/>
|
|
||||||
<key>UIStatusBarHidden</key>
|
|
||||||
<true/>
|
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
</array>
|
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" colorMatched="YES" initialViewController="2">
|
|
||||||
<device id="retina4_7" orientation="portrait">
|
|
||||||
<adaptation id="fullscreen"/>
|
|
||||||
</device>
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<customFonts key="customFonts">
|
|
||||||
<array key="Menlo.ttc">
|
|
||||||
<string>Menlo-Regular</string>
|
|
||||||
</array>
|
|
||||||
</customFonts>
|
|
||||||
<scenes>
|
|
||||||
<!--Camera Example View Controller-->
|
|
||||||
<scene sceneID="5">
|
|
||||||
<objects>
|
|
||||||
<viewController id="2" customClass="CameraExampleViewController" sceneMemberID="viewController">
|
|
||||||
<view key="view" contentMode="scaleToFill" id="3">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<view contentMode="scaleToFill" id="12">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="621"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<gestureRecognizers/>
|
|
||||||
</view>
|
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="iD8-yH-eWH">
|
|
||||||
<rect key="frame" x="0.0" y="453" width="320" height="36"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="20"/>
|
|
||||||
<state key="normal" title="Next Photo">
|
|
||||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
</state>
|
|
||||||
<connections>
|
|
||||||
<action selector="myAction:" destination="2" eventType="valueChanged" id="X4s-U5-7V7"/>
|
|
||||||
<action selector="takePicture:" destination="2" eventType="touchUpInside" id="BTy-7E-XUS"/>
|
|
||||||
</connections>
|
|
||||||
</button>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
</view>
|
|
||||||
<connections>
|
|
||||||
<outlet property="previewView" destination="12" id="13"/>
|
|
||||||
</connections>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="4" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
|
||||||
</document>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
platform :ios, '8.0'
|
|
||||||
inhibit_all_warnings!
|
|
||||||
|
|
||||||
target 'tflite_photos_example'
|
|
||||||
pod 'TensorFlowLite'
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
#import "CameraExampleAppDelegate.h"
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
int retVal = 0;
|
|
||||||
|
|
||||||
@autoreleasepool {
|
|
||||||
retVal =
|
|
||||||
UIApplicationMain(argc, argv, nil, NSStringFromClass([CameraExampleAppDelegate class]));
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
@@ -1,395 +0,0 @@
|
|||||||
// !$*UTF8*$!
|
|
||||||
{
|
|
||||||
archiveVersion = 1;
|
|
||||||
classes = {
|
|
||||||
};
|
|
||||||
objectVersion = 46;
|
|
||||||
objects = {
|
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
|
||||||
1C3C9DCC1ED3AB4200B8B5FA /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C3C9DCA1ED3AB4200B8B5FA /* main.mm */; };
|
|
||||||
1C99111C1ED3B0E600A6BFB9 /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1C99111B1ED3B0E600A6BFB9 /* MainStoryboard_iPhone.storyboard */; };
|
|
||||||
1CA5EB931ED3ABFB00247A34 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CA5EB921ED3ABFB00247A34 /* CoreMedia.framework */; };
|
|
||||||
1CB47D491ED3AD1700DF7666 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CB47D481ED3AD1700DF7666 /* AVFoundation.framework */; };
|
|
||||||
1CDB2D491ED3A9CD007929E9 /* CameraExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CDB2D431ED3A9CD007929E9 /* CameraExampleAppDelegate.m */; };
|
|
||||||
1CDB2D4A1ED3A9CD007929E9 /* CameraExampleViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1CDB2D451ED3A9CD007929E9 /* CameraExampleViewController.mm */; };
|
|
||||||
1CDB2D4E1ED3AA35007929E9 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1CDB2D4D1ED3AA35007929E9 /* Info.plist */; };
|
|
||||||
2E12E3C82087CB8600FD9D4A /* graph.lite in Resources */ = {isa = PBXBuildFile; fileRef = 2E12E3C72087CB8600FD9D4A /* graph.lite */; };
|
|
||||||
2E92D8912088011F005F343A /* AppIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2E92D8902088011F005F343A /* AppIcon.xcassets */; };
|
|
||||||
2ED6BE3A207C23E000D3BF6F /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ED6BE39207C23E000D3BF6F /* Photos.framework */; };
|
|
||||||
AB30E2C6AA6147C90F25FFD2 /* libPods-tflite_photos_example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FF33ED907C01C2D2EA78BBB /* libPods-tflite_photos_example.a */; };
|
|
||||||
AC1F82661FBA3CBD0052BA77 /* labels.txt in Resources */ = {isa = PBXBuildFile; fileRef = AC1F82641FBA3CBD0052BA77 /* labels.txt */; };
|
|
||||||
/* End PBXBuildFile section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
|
||||||
1C0D73481ECCC41B008C1DAB /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; };
|
|
||||||
1C0D734A1ECCC460008C1DAB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
|
||||||
1C3C9DCA1ED3AB4200B8B5FA /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
|
|
||||||
1C564C0D1ED3A92E00087306 /* tflite_photos_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tflite_photos_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
1C99111B1ED3B0E600A6BFB9 /* MainStoryboard_iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard_iPhone.storyboard; sourceTree = "<group>"; };
|
|
||||||
1CA45FFE1ECCC356002FA6A4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
|
||||||
1CA5EB921ED3ABFB00247A34 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
|
|
||||||
1CB47D481ED3AD1700DF7666 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
|
|
||||||
1CDB2D421ED3A9CD007929E9 /* CameraExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CameraExampleAppDelegate.h; sourceTree = "<group>"; };
|
|
||||||
1CDB2D431ED3A9CD007929E9 /* CameraExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraExampleAppDelegate.m; sourceTree = "<group>"; };
|
|
||||||
1CDB2D441ED3A9CD007929E9 /* CameraExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CameraExampleViewController.h; sourceTree = "<group>"; };
|
|
||||||
1CDB2D451ED3A9CD007929E9 /* CameraExampleViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CameraExampleViewController.mm; sourceTree = "<group>"; };
|
|
||||||
1CDB2D4D1ED3AA35007929E9 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
||||||
2E12E3C72087CB8600FD9D4A /* graph.lite */ = {isa = PBXFileReference; lastKnownFileType = file; path = graph.lite; sourceTree = "<group>"; };
|
|
||||||
2E92D8902088011F005F343A /* AppIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = AppIcon.xcassets; sourceTree = "<group>"; };
|
|
||||||
2ED6BE39207C23E000D3BF6F /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; };
|
|
||||||
2FF33ED907C01C2D2EA78BBB /* libPods-tflite_photos_example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-tflite_photos_example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
3BA8BF92C84895BFE59D8236 /* libPods-tflite_camera_example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-tflite_camera_example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
3BC5BE4BBD09374D3E98F082 /* Pods-tflite_camera_example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tflite_camera_example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-tflite_camera_example/Pods-tflite_camera_example.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
55ED318E8D29C8AFEF03DF1E /* Pods-tflite_camera_example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tflite_camera_example.release.xcconfig"; path = "Pods/Target Support Files/Pods-tflite_camera_example/Pods-tflite_camera_example.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
7B75D9AAB5B7890D81174E26 /* Pods-tflite_photos_example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tflite_photos_example.release.xcconfig"; path = "Pods/Target Support Files/Pods-tflite_photos_example/Pods-tflite_photos_example.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
92A36BF8A50AF5A52BB51EA5 /* Pods-tflite_photos_example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-tflite_photos_example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-tflite_photos_example/Pods-tflite_photos_example.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
AC1F82641FBA3CBD0052BA77 /* labels.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = labels.txt; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
|
||||||
1C564C0A1ED3A92E00087306 /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
2ED6BE3A207C23E000D3BF6F /* Photos.framework in Frameworks */,
|
|
||||||
1CB47D491ED3AD1700DF7666 /* AVFoundation.framework in Frameworks */,
|
|
||||||
1CA5EB931ED3ABFB00247A34 /* CoreMedia.framework in Frameworks */,
|
|
||||||
AB30E2C6AA6147C90F25FFD2 /* libPods-tflite_photos_example.a in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXFrameworksBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
|
||||||
24D7686C331131624F4454A0 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
2ED6BE39207C23E000D3BF6F /* Photos.framework */,
|
|
||||||
1CB47D481ED3AD1700DF7666 /* AVFoundation.framework */,
|
|
||||||
1CA5EB921ED3ABFB00247A34 /* CoreMedia.framework */,
|
|
||||||
1C0D734A1ECCC460008C1DAB /* CoreGraphics.framework */,
|
|
||||||
1C0D73481ECCC41B008C1DAB /* CoreImage.framework */,
|
|
||||||
1CA45FFE1ECCC356002FA6A4 /* UIKit.framework */,
|
|
||||||
3BA8BF92C84895BFE59D8236 /* libPods-tflite_camera_example.a */,
|
|
||||||
2FF33ED907C01C2D2EA78BBB /* libPods-tflite_photos_example.a */,
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
3E9FC355632FB928EA23BEED /* Pods */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
3BC5BE4BBD09374D3E98F082 /* Pods-tflite_camera_example.debug.xcconfig */,
|
|
||||||
55ED318E8D29C8AFEF03DF1E /* Pods-tflite_camera_example.release.xcconfig */,
|
|
||||||
92A36BF8A50AF5A52BB51EA5 /* Pods-tflite_photos_example.debug.xcconfig */,
|
|
||||||
7B75D9AAB5B7890D81174E26 /* Pods-tflite_photos_example.release.xcconfig */,
|
|
||||||
);
|
|
||||||
name = Pods;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
591157921CF4011C00C31E3A = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
2E92D8902088011F005F343A /* AppIcon.xcassets */,
|
|
||||||
1C99111B1ED3B0E600A6BFB9 /* MainStoryboard_iPhone.storyboard */,
|
|
||||||
1C3C9DCA1ED3AB4200B8B5FA /* main.mm */,
|
|
||||||
1CDB2D4D1ED3AA35007929E9 /* Info.plist */,
|
|
||||||
1CDB2D421ED3A9CD007929E9 /* CameraExampleAppDelegate.h */,
|
|
||||||
1CDB2D431ED3A9CD007929E9 /* CameraExampleAppDelegate.m */,
|
|
||||||
1CDB2D441ED3A9CD007929E9 /* CameraExampleViewController.h */,
|
|
||||||
1CDB2D451ED3A9CD007929E9 /* CameraExampleViewController.mm */,
|
|
||||||
59A3CFF31CF4E68100C4259F /* data */,
|
|
||||||
5911579C1CF4011C00C31E3A /* Products */,
|
|
||||||
3E9FC355632FB928EA23BEED /* Pods */,
|
|
||||||
24D7686C331131624F4454A0 /* Frameworks */,
|
|
||||||
);
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
5911579C1CF4011C00C31E3A /* Products */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
1C564C0D1ED3A92E00087306 /* tflite_photos_example.app */,
|
|
||||||
);
|
|
||||||
name = Products;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
59A3CFF31CF4E68100C4259F /* data */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
2E12E3C72087CB8600FD9D4A /* graph.lite */,
|
|
||||||
AC1F82641FBA3CBD0052BA77 /* labels.txt */,
|
|
||||||
);
|
|
||||||
path = data;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
|
||||||
1C564C0C1ED3A92E00087306 /* tflite_photos_example */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = 1C564C351ED3A92E00087306 /* Build configuration list for PBXNativeTarget "tflite_photos_example" */;
|
|
||||||
buildPhases = (
|
|
||||||
66DAEAAEE9EF6550C3A061E0 /* [CP] Check Pods Manifest.lock */,
|
|
||||||
1C564C091ED3A92E00087306 /* Sources */,
|
|
||||||
1C564C0A1ED3A92E00087306 /* Frameworks */,
|
|
||||||
1C564C0B1ED3A92E00087306 /* Resources */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = tflite_photos_example;
|
|
||||||
productName = tflite_camera_example;
|
|
||||||
productReference = 1C564C0D1ED3A92E00087306 /* tflite_photos_example.app */;
|
|
||||||
productType = "com.apple.product-type.application";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
|
||||||
591157931CF4011C00C31E3A /* Project object */ = {
|
|
||||||
isa = PBXProject;
|
|
||||||
attributes = {
|
|
||||||
LastSwiftUpdateCheck = 0830;
|
|
||||||
LastUpgradeCheck = 0830;
|
|
||||||
ORGANIZATIONNAME = Google;
|
|
||||||
TargetAttributes = {
|
|
||||||
1C564C0C1ED3A92E00087306 = {
|
|
||||||
CreatedOnToolsVersion = 8.3.2;
|
|
||||||
DevelopmentTeam = EQHXZ8M8AV;
|
|
||||||
ProvisioningStyle = Manual;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
buildConfigurationList = 591157961CF4011C00C31E3A /* Build configuration list for PBXProject "tflite_photos_example" */;
|
|
||||||
compatibilityVersion = "Xcode 3.2";
|
|
||||||
developmentRegion = English;
|
|
||||||
hasScannedForEncodings = 0;
|
|
||||||
knownRegions = (
|
|
||||||
en,
|
|
||||||
Base,
|
|
||||||
);
|
|
||||||
mainGroup = 591157921CF4011C00C31E3A;
|
|
||||||
productRefGroup = 5911579C1CF4011C00C31E3A /* Products */;
|
|
||||||
projectDirPath = "";
|
|
||||||
projectRoot = "";
|
|
||||||
targets = (
|
|
||||||
1C564C0C1ED3A92E00087306 /* tflite_photos_example */,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
/* End PBXProject section */
|
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
|
||||||
1C564C0B1ED3A92E00087306 /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
2E92D8912088011F005F343A /* AppIcon.xcassets in Resources */,
|
|
||||||
2E12E3C82087CB8600FD9D4A /* graph.lite in Resources */,
|
|
||||||
1C99111C1ED3B0E600A6BFB9 /* MainStoryboard_iPhone.storyboard in Resources */,
|
|
||||||
1CDB2D4E1ED3AA35007929E9 /* Info.plist in Resources */,
|
|
||||||
AC1F82661FBA3CBD0052BA77 /* labels.txt in Resources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXResourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
66DAEAAEE9EF6550C3A061E0 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-tflite_photos_example-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
|
||||||
1C564C091ED3A92E00087306 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
1CDB2D4A1ED3A9CD007929E9 /* CameraExampleViewController.mm in Sources */,
|
|
||||||
1CDB2D491ED3A9CD007929E9 /* CameraExampleAppDelegate.m in Sources */,
|
|
||||||
1C3C9DCC1ED3AB4200B8B5FA /* main.mm in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
|
||||||
1C564C361ED3A92E00087306 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 92A36BF8A50AF5A52BB51EA5 /* Pods-tflite_photos_example.debug.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
|
||||||
DEVELOPMENT_TEAM = EQHXZ8M8AV;
|
|
||||||
INFOPLIST_FILE = Info.plist;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.pf.tf-photos-example";
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
|
||||||
SWIFT_VERSION = 3.0;
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
1C564C371ED3A92E00087306 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 7B75D9AAB5B7890D81174E26 /* Pods-tflite_photos_example.release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
|
||||||
DEVELOPMENT_TEAM = EQHXZ8M8AV;
|
|
||||||
INFOPLIST_FILE = Info.plist;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.pf.tf-photos-example";
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
|
||||||
SWIFT_VERSION = 3.0;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
591157B01CF4011D00C31E3A /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
ENABLE_TESTABILITY = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
||||||
"DEBUG=1",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
HEADER_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
../../../../../../,
|
|
||||||
../../../downloads/flatbuffers/include/,
|
|
||||||
../../../downloads/eigen/,
|
|
||||||
../../../downloads/,
|
|
||||||
);
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
591157B11CF4011D00C31E3A /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
HEADER_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
../../../../../../,
|
|
||||||
../../../downloads/flatbuffers/include/,
|
|
||||||
../../../downloads/eigen/,
|
|
||||||
../../../downloads/,
|
|
||||||
);
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
/* End XCBuildConfiguration section */
|
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
|
||||||
1C564C351ED3A92E00087306 /* Build configuration list for PBXNativeTarget "tflite_photos_example" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
1C564C361ED3A92E00087306 /* Debug */,
|
|
||||||
1C564C371ED3A92E00087306 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
591157961CF4011C00C31E3A /* Build configuration list for PBXProject "tflite_photos_example" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
591157B01CF4011D00C31E3A /* Debug */,
|
|
||||||
591157B11CF4011D00C31E3A /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
|
||||||
};
|
|
||||||
rootObject = 591157931CF4011C00C31E3A /* Project object */;
|
|
||||||
}
|
|
||||||