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 */;
|
||||
}
|
||||