├── .google └── packaging.yaml ├── .gradle └── 2.14.1 │ └── taskArtifacts │ ├── cache.properties │ ├── cache.properties.lock │ ├── fileHashes.bin │ ├── fileSnapshots.bin │ ├── fileSnapshotsToTreeSnapshotsIndex.bin │ └── taskArtifacts.bin ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── libraries │ ├── animated_vector_drawable_25_0_1.xml │ ├── appcompat_v7_25_0_1.xml │ ├── cardview_v7_25_0_1.xml │ ├── constraint_layout_1_0_2.xml │ ├── constraint_layout_solver_1_0_2.xml │ ├── espresso_core_2_2_2.xml │ ├── espresso_idling_resource_2_2_2.xml │ ├── exposed_instrumentation_api_publish_0_5.xml │ ├── hamcrest_core_1_3.xml │ ├── hamcrest_integration_1_3.xml │ ├── hamcrest_library_1_3.xml │ ├── javawriter_2_1_1.xml │ ├── javax_annotation_api_1_2.xml │ ├── javax_inject_1.xml │ ├── jsr305_2_0_1.xml │ ├── junit_4_12.xml │ ├── libandroid_tensorflow_inference_java.xml │ ├── rules_0_5.xml │ ├── runner_0_5.xml │ ├── support_annotations_25_0_1.xml │ ├── support_compat_25_0_1.xml │ ├── support_core_ui_25_0_1.xml │ ├── support_core_utils_25_0_1.xml │ ├── support_fragment_25_0_1.xml │ ├── support_media_compat_25_0_1.xml │ ├── support_v13_25_0_1.xml │ ├── support_v4_25_0_1.xml │ └── support_vector_drawable_25_0_1.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── workspace.xml ├── Application ├── Application.iml ├── build.gradle ├── libs │ ├── arm64-v8a │ │ └── libtensorflow_inference.so │ ├── armeabi-v7a │ │ └── libtensorflow_inference.so │ ├── libandroid_tensorflow_inference_java.jar │ ├── x86 │ │ └── libtensorflow_inference.so │ └── x86_64 │ │ └── libtensorflow_inference.so ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ ├── DecoderOutputs.txt │ │ └── idmap │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── android │ │ │ └── camera2basic │ │ │ ├── AutoFitTextureView.java │ │ │ ├── Camera2BasicFragment.java │ │ │ └── CameraActivity.java │ │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_action_info.png │ │ ├── ic_launcher.png │ │ └── tile.9.png │ │ ├── drawable-mdpi │ │ ├── ic_action_info.png │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ ├── ic_action_info.png │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ ├── ic_action_info.png │ │ └── ic_launcher.png │ │ ├── layout-land │ │ └── fragment_camera2_basic.xml │ │ ├── layout │ │ ├── activity_camera.xml │ │ └── fragment_camera2_basic.xml │ │ ├── values-sw600dp │ │ ├── template-dimens.xml │ │ └── template-styles.xml │ │ ├── values-v11 │ │ └── template-styles.xml │ │ ├── values-v21 │ │ ├── base-colors.xml │ │ └── base-template-styles.xml │ │ └── values │ │ ├── base-strings.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ ├── template-dimens.xml │ │ └── template-styles.xml └── tests │ ├── AndroidManifest.xml │ └── src │ └── com │ └── example │ └── android │ └── camera2basic │ └── tests │ └── SampleTests.java ├── Cam2Caption.iml ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── packaging.yaml ├── preview.gif └── settings.gradle /.google/packaging.yaml: -------------------------------------------------------------------------------- 1 | 2 | # GOOGLE SAMPLE PACKAGING DATA 3 | # 4 | # This file is used by Google as part of our samples packaging process. 5 | # End users may safely ignore this file. It has no relevance to other systems. 6 | --- 7 | status: PUBLISHED 8 | technologies: [Android] 9 | categories: [Media, Camera, Camera2] 10 | languages: [Java] 11 | solutions: [Mobile] 12 | github: android-Camera2Basic 13 | level: INTERMEDIATE 14 | icon: screenshots/icon-web.png 15 | apiRefs: 16 | - android:android.hardware.camera2.CameraManager 17 | - android:android.hardware.camera2.CameraDevice 18 | - android:android.hardware.camera2.CameraCharacteristics 19 | - android:android.hardware.camera2.CameraCaptureSession 20 | - android:android.hardware.camera2.CaptureRequest 21 | - android:android.hardware.camera2.CaptureResult 22 | - android:android.view.TextureView 23 | license: apache2 24 | -------------------------------------------------------------------------------- /.gradle/2.14.1/taskArtifacts/cache.properties: -------------------------------------------------------------------------------- 1 | #Sat Mar 18 10:52:09 IST 2017 2 | -------------------------------------------------------------------------------- /.gradle/2.14.1/taskArtifacts/cache.properties.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/.gradle/2.14.1/taskArtifacts/cache.properties.lock -------------------------------------------------------------------------------- /.gradle/2.14.1/taskArtifacts/fileHashes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/.gradle/2.14.1/taskArtifacts/fileHashes.bin -------------------------------------------------------------------------------- /.gradle/2.14.1/taskArtifacts/fileSnapshots.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/.gradle/2.14.1/taskArtifacts/fileSnapshots.bin -------------------------------------------------------------------------------- /.gradle/2.14.1/taskArtifacts/fileSnapshotsToTreeSnapshotsIndex.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/.gradle/2.14.1/taskArtifacts/fileSnapshotsToTreeSnapshotsIndex.bin -------------------------------------------------------------------------------- /.gradle/2.14.1/taskArtifacts/taskArtifacts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/.gradle/2.14.1/taskArtifacts/taskArtifacts.bin -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/libraries/animated_vector_drawable_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/appcompat_v7_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/cardview_v7_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/constraint_layout_1_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/constraint_layout_solver_1_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/espresso_core_2_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/espresso_idling_resource_2_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/exposed_instrumentation_api_publish_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_core_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_integration_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/hamcrest_library_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/javawriter_2_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/javax_annotation_api_1_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/javax_inject_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/jsr305_2_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/junit_4_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/libandroid_tensorflow_inference_java.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/libraries/rules_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/runner_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/support_annotations_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/support_compat_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_core_ui_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_core_utils_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_fragment_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_media_compat_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_v13_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/support_v4_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/support_vector_drawable_25_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /Application/Application.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /Application/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | } 10 | } 11 | 12 | apply plugin: 'com.android.application' 13 | 14 | repositories { 15 | jcenter() 16 | } 17 | 18 | 19 | 20 | // The sample build uses multiple directories to 21 | // keep boilerplate and common code separate from 22 | // the main sample code. 23 | List dirs = [ 24 | 'main', // main sample code; look here for the interesting stuff. 25 | 'common', // components that are reused by multiple samples 26 | 'template'] // boilerplate code that is generated by the sample template process 27 | 28 | android { 29 | compileSdkVersion 25 30 | buildToolsVersion "25.0.2" 31 | 32 | defaultConfig { 33 | minSdkVersion 21 34 | targetSdkVersion 25 35 | } 36 | 37 | compileOptions { 38 | sourceCompatibility JavaVersion.VERSION_1_7 39 | targetCompatibility JavaVersion.VERSION_1_7 40 | } 41 | 42 | sourceSets { 43 | main { 44 | dirs.each { dir -> 45 | java.srcDirs "src/${dir}/java" 46 | res.srcDirs "src/${dir}/res" 47 | } 48 | jniLibs.srcDirs = ['libs'] 49 | } 50 | androidTest.setRoot('tests') 51 | androidTest.java.srcDirs = ['tests/src'] 52 | 53 | } 54 | 55 | dependencies { 56 | compile fileTree(dir: 'libs', include: ['*.jar']) 57 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 58 | exclude group: 'com.android.support', module: 'support-annotations' 59 | }) 60 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 61 | testCompile 'junit:junit:4.12' 62 | compile "com.android.support:support-v4:25.0.1" 63 | compile "com.android.support:support-v13:25.0.1" 64 | compile "com.android.support:cardview-v7:25.0.1" 65 | compile "com.android.support:appcompat-v7:25.0.1" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Application/libs/arm64-v8a/libtensorflow_inference.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/libs/arm64-v8a/libtensorflow_inference.so -------------------------------------------------------------------------------- /Application/libs/armeabi-v7a/libtensorflow_inference.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/libs/armeabi-v7a/libtensorflow_inference.so -------------------------------------------------------------------------------- /Application/libs/libandroid_tensorflow_inference_java.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/libs/libandroid_tensorflow_inference_java.jar -------------------------------------------------------------------------------- /Application/libs/x86/libtensorflow_inference.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/libs/x86/libtensorflow_inference.so -------------------------------------------------------------------------------- /Application/libs/x86_64/libtensorflow_inference.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/libs/x86_64/libtensorflow_inference.so -------------------------------------------------------------------------------- /Application/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Application/src/main/assets/DecoderOutputs.txt: -------------------------------------------------------------------------------- 1 | decoder/LSTM/word_0:0 2 | decoder/LSTM/word_1:0 3 | decoder/LSTM/word_2:0 4 | decoder/LSTM/word_3:0 5 | decoder/LSTM/word_4:0 6 | decoder/LSTM/word_5:0 7 | decoder/LSTM/word_6:0 8 | decoder/LSTM/word_7:0 9 | decoder/LSTM/word_8:0 10 | decoder/LSTM/word_9:0 11 | decoder/LSTM/word_10:0 12 | decoder/LSTM/word_11:0 13 | decoder/LSTM/word_12:0 14 | decoder/LSTM/word_13:0 15 | decoder/LSTM/word_14:0 16 | decoder/LSTM/word_15:0 17 | decoder/LSTM/word_16:0 18 | decoder/LSTM/word_17:0 19 | decoder/LSTM/word_18:0 20 | decoder/LSTM/word_19:0 21 | decoder/LSTM/word_20:0 22 | decoder/LSTM/word_21:0 23 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/camera2basic/AutoFitTextureView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.camera2basic; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.TextureView; 22 | 23 | /** 24 | * A {@link TextureView} that can be adjusted to a specified aspect ratio. 25 | */ 26 | public class AutoFitTextureView extends TextureView { 27 | 28 | private int mRatioWidth = 0; 29 | private int mRatioHeight = 0; 30 | 31 | public AutoFitTextureView(Context context) { 32 | this(context, null); 33 | } 34 | 35 | public AutoFitTextureView(Context context, AttributeSet attrs) { 36 | this(context, attrs, 0); 37 | } 38 | 39 | public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) { 40 | super(context, attrs, defStyle); 41 | } 42 | 43 | /** 44 | * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio 45 | * calculated from the parameters. Note that the actual sizes of parameters don't matter, that 46 | * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. 47 | * 48 | * @param width Relative horizontal size 49 | * @param height Relative vertical size 50 | */ 51 | public void setAspectRatio(int width, int height) { 52 | if (width < 0 || height < 0) { 53 | throw new IllegalArgumentException("Size cannot be negative."); 54 | } 55 | mRatioWidth = width; 56 | mRatioHeight = height; 57 | requestLayout(); 58 | } 59 | 60 | @Override 61 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 62 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 63 | int width = MeasureSpec.getSize(widthMeasureSpec); 64 | int height = MeasureSpec.getSize(heightMeasureSpec); 65 | if (0 == mRatioWidth || 0 == mRatioHeight) { 66 | setMeasuredDimension(width, height); 67 | } else { 68 | if (width < height * mRatioWidth / mRatioHeight) { 69 | setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); 70 | } else { 71 | setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); 72 | } 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java: -------------------------------------------------------------------------------- 1 | package com.example.android.camera2basic; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.app.AlertDialog; 6 | import android.app.Dialog; 7 | import android.app.DialogFragment; 8 | import android.app.Fragment; 9 | import android.content.Context; 10 | import android.content.DialogInterface; 11 | import android.content.pm.PackageManager; 12 | import android.content.res.Configuration; 13 | import android.graphics.Color; 14 | import android.graphics.ImageFormat; 15 | import android.graphics.Matrix; 16 | import android.graphics.Point; 17 | import android.graphics.RectF; 18 | import android.graphics.SurfaceTexture; 19 | import android.hardware.camera2.CameraAccessException; 20 | import android.hardware.camera2.CameraCaptureSession; 21 | import android.hardware.camera2.CameraCharacteristics; 22 | import android.hardware.camera2.CameraDevice; 23 | import android.hardware.camera2.CameraManager; 24 | import android.hardware.camera2.CaptureRequest; 25 | import android.hardware.camera2.CaptureResult; 26 | import android.hardware.camera2.TotalCaptureResult; 27 | import android.hardware.camera2.params.StreamConfigurationMap; 28 | import android.media.Image; 29 | import android.media.ImageReader; 30 | import android.os.Bundle; 31 | import android.os.Handler; 32 | import android.os.HandlerThread; 33 | import android.support.annotation.NonNull; 34 | import android.support.v13.app.FragmentCompat; 35 | import android.support.v4.content.ContextCompat; 36 | import android.util.Log; 37 | import android.util.Size; 38 | import android.util.SparseIntArray; 39 | import android.view.LayoutInflater; 40 | import android.view.Surface; 41 | import android.view.TextureView; 42 | import android.view.View; 43 | import android.view.ViewGroup; 44 | import android.widget.Toast; 45 | import android.widget.TextView; 46 | import android.graphics.Bitmap; 47 | import android.graphics.BitmapFactory; 48 | 49 | import java.io.BufferedReader; 50 | import java.io.IOException; 51 | import java.io.InputStream; 52 | import java.io.InputStreamReader; 53 | import java.nio.ByteBuffer; 54 | import java.util.ArrayList; 55 | import java.util.Arrays; 56 | import java.util.Collections; 57 | import java.util.Comparator; 58 | import java.util.List; 59 | import java.util.concurrent.Semaphore; 60 | import java.util.concurrent.TimeUnit; 61 | 62 | import org.tensorflow.contrib.android.TensorFlowInferenceInterface; 63 | 64 | public class Camera2BasicFragment extends Fragment 65 | implements FragmentCompat.OnRequestPermissionsResultCallback{ 66 | 67 | private TextView textView; 68 | private static final String MODEL_FILE = "file:///android_asset/merged_frozen_graph.pb"; 69 | private static final String INPUT1 = "encoder/import/InputImage:0"; 70 | private static final String OUTPUT_NODES = "DecoderOutputs.txt"; 71 | private static final int NUM_TIMESTEPS = 22; 72 | private static final int IMAGE_SIZE = 299; 73 | private static final int IMAGE_CHANNELS = 3; 74 | private static final int[] DIM_IMAGE=new int[]{1, IMAGE_SIZE, IMAGE_SIZE, IMAGE_CHANNELS}; 75 | private TensorFlowInferenceInterface inferenceInterface; 76 | static { 77 | System.loadLibrary("tensorflow_inference"); 78 | } 79 | private String[] OutputNodes = null; 80 | private String[] WORD_MAP = null; 81 | /** 82 | * Conversion from screen rotation to JPEG orientation. 83 | */ 84 | private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 85 | private static final int REQUEST_CAMERA_PERMISSION = 1; 86 | private static final String FRAGMENT_DIALOG = "dialog"; 87 | 88 | static { 89 | ORIENTATIONS.append(Surface.ROTATION_0, 90); 90 | ORIENTATIONS.append(Surface.ROTATION_90, 0); 91 | ORIENTATIONS.append(Surface.ROTATION_180, 270); 92 | ORIENTATIONS.append(Surface.ROTATION_270, 180); 93 | } 94 | 95 | /** 96 | * Tag for the {@link Log}. 97 | */ 98 | private static final String TAG = "Camera2BasicFragment"; 99 | 100 | /** 101 | * Camera state: Showing camera preview. 102 | */ 103 | private static final int STATE_PREVIEW = 0; 104 | 105 | /** 106 | * Max preview width that is guaranteed by Camera2 API 107 | */ 108 | private static final int MAX_PREVIEW_WIDTH = 1920; 109 | 110 | /** 111 | * Max preview height that is guaranteed by Camera2 API 112 | */ 113 | private static final int MAX_PREVIEW_HEIGHT = 1080; 114 | 115 | /** 116 | * {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a 117 | * {@link TextureView}. 118 | */ 119 | private final TextureView.SurfaceTextureListener mSurfaceTextureListener 120 | = new TextureView.SurfaceTextureListener() { 121 | 122 | @Override 123 | public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { 124 | openCamera(width, height); 125 | } 126 | 127 | @Override 128 | public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { 129 | configureTransform(width, height); 130 | } 131 | 132 | @Override 133 | public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { 134 | return true; 135 | } 136 | 137 | @Override 138 | public void onSurfaceTextureUpdated(SurfaceTexture texture) { 139 | } 140 | 141 | }; 142 | 143 | /** 144 | * ID of the current {@link CameraDevice}. 145 | */ 146 | private String mCameraId; 147 | 148 | /** 149 | * An {@link AutoFitTextureView} for camera preview. 150 | */ 151 | private AutoFitTextureView mTextureView; 152 | 153 | /** 154 | * A {@link CameraCaptureSession } for camera preview. 155 | */ 156 | private CameraCaptureSession mCaptureSession; 157 | 158 | /** 159 | * A reference to the opened {@link CameraDevice}. 160 | */ 161 | private CameraDevice mCameraDevice; 162 | 163 | /** 164 | * The {@link android.util.Size} of camera preview. 165 | */ 166 | private Size mPreviewSize; 167 | 168 | /** 169 | * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state. 170 | */ 171 | private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { 172 | 173 | @Override 174 | public void onOpened(@NonNull CameraDevice cameraDevice) { 175 | // This method is called when the camera is opened. We start camera preview here. 176 | mCameraOpenCloseLock.release(); 177 | mCameraDevice = cameraDevice; 178 | createCameraPreviewSession(); 179 | } 180 | 181 | @Override 182 | public void onDisconnected(@NonNull CameraDevice cameraDevice) { 183 | mCameraOpenCloseLock.release(); 184 | cameraDevice.close(); 185 | mCameraDevice = null; 186 | } 187 | 188 | @Override 189 | public void onError(@NonNull CameraDevice cameraDevice, int error) { 190 | mCameraOpenCloseLock.release(); 191 | cameraDevice.close(); 192 | mCameraDevice = null; 193 | Activity activity = getActivity(); 194 | if (null != activity) { 195 | activity.finish(); 196 | } 197 | } 198 | 199 | }; 200 | 201 | /** 202 | * An additional thread for running tasks that shouldn't block the UI. 203 | */ 204 | private HandlerThread mBackgroundThread; 205 | 206 | /** 207 | * A {@link Handler} for running tasks in the background. 208 | */ 209 | private Handler mBackgroundHandler; 210 | 211 | /** 212 | * An {@link ImageReader} that handles still image capture. 213 | */ 214 | private ImageReader mImageReader; 215 | 216 | 217 | /** 218 | * {@link CaptureRequest.Builder} for the camera preview 219 | */ 220 | private CaptureRequest.Builder mPreviewRequestBuilder; 221 | 222 | /** 223 | * {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder} 224 | */ 225 | private CaptureRequest mPreviewRequest; 226 | 227 | /** 228 | * The current state of camera state for taking pictures. 229 | * 230 | * @see #mCaptureCallback 231 | */ 232 | private int mState = STATE_PREVIEW; 233 | 234 | /** 235 | * A {@link Semaphore} to prevent the app from exiting before closing the camera. 236 | */ 237 | private Semaphore mCameraOpenCloseLock = new Semaphore(1); 238 | 239 | /** 240 | * Orientation of the camera sensor 241 | */ 242 | private int mSensorOrientation; 243 | 244 | /** 245 | * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture. 246 | */ 247 | private CameraCaptureSession.CaptureCallback mCaptureCallback 248 | = new CameraCaptureSession.CaptureCallback() { 249 | 250 | private void process(CaptureResult result) { 251 | switch (mState) { 252 | case STATE_PREVIEW: { 253 | // We have nothing to do when the camera preview is working normally. 254 | break; 255 | } 256 | /* 257 | case STATE_WAITING_LOCK: { 258 | Integer afState = result.get(CaptureResult.CONTROL_AF_STATE); 259 | if (afState == null) { 260 | //captureStillPicture(); 261 | } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || 262 | CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) { 263 | // CONTROL_AE_STATE can be null on some devices 264 | Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); 265 | if (aeState == null || 266 | aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) { 267 | mState = STATE_PICTURE_TAKEN; 268 | //captureStillPicture(); 269 | } else { 270 | //runPrecaptureSequence(); 271 | } 272 | } 273 | break; 274 | } 275 | case STATE_WAITING_PRECAPTURE: { 276 | // CONTROL_AE_STATE can be null on some devices 277 | Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); 278 | if (aeState == null || 279 | aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || 280 | aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) { 281 | mState = STATE_WAITING_NON_PRECAPTURE; 282 | } 283 | break; 284 | } 285 | case STATE_WAITING_NON_PRECAPTURE: { 286 | // CONTROL_AE_STATE can be null on some devices 287 | Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); 288 | if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { 289 | mState = STATE_PICTURE_TAKEN; 290 | //captureStillPicture(); 291 | } 292 | break; 293 | } 294 | */ 295 | } 296 | } 297 | 298 | @Override 299 | public void onCaptureProgressed(@NonNull CameraCaptureSession session, 300 | @NonNull CaptureRequest request, 301 | @NonNull CaptureResult partialResult) { 302 | process(partialResult); 303 | } 304 | 305 | @Override 306 | public void onCaptureCompleted(@NonNull CameraCaptureSession session, 307 | @NonNull CaptureRequest request, 308 | @NonNull TotalCaptureResult result) { 309 | process(result); 310 | } 311 | 312 | }; 313 | 314 | /** 315 | * Shows a {@link Toast} on the UI thread. 316 | * 317 | * @param text The message to show 318 | */ 319 | private void showToast(final String text) { 320 | final Activity activity = getActivity(); 321 | if (activity != null) { 322 | activity.runOnUiThread(new Runnable() { 323 | @Override 324 | public void run() { 325 | Toast.makeText(activity, text, Toast.LENGTH_SHORT).show(); 326 | } 327 | }); 328 | } 329 | } 330 | 331 | /** 332 | * Given {@code choices} of {@code Size}s supported by a camera, choose the smallest one that 333 | * is at least as large as the respective texture view size, and that is at most as large as the 334 | * respective max size, and whose aspect ratio matches with the specified value. If such size 335 | * doesn't exist, choose the largest one that is at most as large as the respective max size, 336 | * and whose aspect ratio matches with the specified value. 337 | * 338 | * @param choices The list of sizes that the camera supports for the intended output 339 | * class 340 | * @param textureViewWidth The width of the texture view relative to sensor coordinate 341 | * @param textureViewHeight The height of the texture view relative to sensor coordinate 342 | * @param maxWidth The maximum width that can be chosen 343 | * @param maxHeight The maximum height that can be chosen 344 | * @param aspectRatio The aspect ratio 345 | * @return The optimal {@code Size}, or an arbitrary one if none were big enough 346 | */ 347 | private static Size chooseOptimalSize(Size[] choices, int textureViewWidth, 348 | int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) { 349 | 350 | // Collect the supported resolutions that are at least as big as the preview Surface 351 | List bigEnough = new ArrayList<>(); 352 | // Collect the supported resolutions that are smaller than the preview Surface 353 | List notBigEnough = new ArrayList<>(); 354 | int w = aspectRatio.getWidth(); 355 | int h = aspectRatio.getHeight(); 356 | for (Size option : choices) { 357 | if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight && 358 | option.getHeight() == option.getWidth() * h / w) { 359 | if (option.getWidth() >= textureViewWidth && 360 | option.getHeight() >= textureViewHeight) { 361 | bigEnough.add(option); 362 | } else { 363 | notBigEnough.add(option); 364 | } 365 | } 366 | } 367 | 368 | // Pick the smallest of those big enough. If there is no one big enough, pick the 369 | // largest of those not big enough. 370 | if (bigEnough.size() > 0) { 371 | return Collections.min(bigEnough, new CompareSizesByArea()); 372 | } else if (notBigEnough.size() > 0) { 373 | return Collections.max(notBigEnough, new CompareSizesByArea()); 374 | } else { 375 | Log.e(TAG, "Couldn't find any suitable preview size"); 376 | return choices[0]; 377 | } 378 | } 379 | 380 | public static Camera2BasicFragment newInstance() { 381 | return new Camera2BasicFragment(); 382 | } 383 | 384 | @Override 385 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 386 | Bundle savedInstanceState) { 387 | return inflater.inflate(R.layout.fragment_camera2_basic, container, false); 388 | } 389 | @Override 390 | public void onResume() { 391 | super.onResume(); 392 | startBackgroundThread(); 393 | 394 | // When the screen is turned off and turned back on, the SurfaceTexture is already 395 | // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open 396 | // a camera and start preview from here (otherwise, we wait until the surface is ready in 397 | // the SurfaceTextureListener). 398 | if (mTextureView.isAvailable()) { 399 | openCamera(mTextureView.getWidth(), mTextureView.getHeight()); 400 | } else { 401 | mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); 402 | } 403 | } 404 | 405 | @Override 406 | public void onPause() { 407 | closeCamera(); 408 | stopBackgroundThread(); 409 | super.onPause(); 410 | } 411 | 412 | private void requestCameraPermission() { 413 | if (FragmentCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { 414 | new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG); 415 | } else { 416 | FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 417 | REQUEST_CAMERA_PERMISSION); 418 | } 419 | } 420 | 421 | @Override 422 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 423 | @NonNull int[] grantResults) { 424 | if (requestCode == REQUEST_CAMERA_PERMISSION) { 425 | if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { 426 | ErrorDialog.newInstance(getString(R.string.request_permission)) 427 | .show(getChildFragmentManager(), FRAGMENT_DIALOG); 428 | } 429 | } else { 430 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 431 | } 432 | } 433 | 434 | private void setUpCameraOutputs(int width, int height) { 435 | Activity activity = getActivity(); 436 | CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); 437 | try { 438 | for (String cameraId : manager.getCameraIdList()) { 439 | CameraCharacteristics characteristics 440 | = manager.getCameraCharacteristics(cameraId); 441 | 442 | // We don't use a front facing camera in this sample. 443 | Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); 444 | if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) { 445 | continue; 446 | } 447 | 448 | StreamConfigurationMap map = characteristics.get( 449 | CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 450 | if (map == null) { 451 | continue; 452 | } 453 | 454 | // For still image captures, we use the largest available size. 455 | Size largest = Collections.max( 456 | Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), 457 | new CompareSizesByArea()); 458 | mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), 459 | ImageFormat.JPEG, 5); 460 | mImageReader.setOnImageAvailableListener( 461 | mOnImageAvailableListener, mBackgroundHandler); 462 | 463 | // Find out if we need to swap dimension to get the preview size relative to sensor 464 | // coordinate. 465 | int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 466 | //noinspection ConstantConditions 467 | mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 468 | boolean swappedDimensions = false; 469 | switch (displayRotation) { 470 | case Surface.ROTATION_0: 471 | case Surface.ROTATION_180: 472 | if (mSensorOrientation == 90 || mSensorOrientation == 270) { 473 | swappedDimensions = true; 474 | } 475 | break; 476 | case Surface.ROTATION_90: 477 | case Surface.ROTATION_270: 478 | if (mSensorOrientation == 0 || mSensorOrientation == 180) { 479 | swappedDimensions = true; 480 | } 481 | break; 482 | default: 483 | Log.e(TAG, "Display rotation is invalid: " + displayRotation); 484 | } 485 | 486 | Point displaySize = new Point(); 487 | activity.getWindowManager().getDefaultDisplay().getSize(displaySize); 488 | int rotatedPreviewWidth = width; 489 | int rotatedPreviewHeight = height; 490 | int maxPreviewWidth = displaySize.x; 491 | int maxPreviewHeight = displaySize.y; 492 | 493 | if (swappedDimensions) { 494 | rotatedPreviewWidth = height; 495 | rotatedPreviewHeight = width; 496 | maxPreviewWidth = displaySize.y; 497 | maxPreviewHeight = displaySize.x; 498 | } 499 | 500 | if (maxPreviewWidth > MAX_PREVIEW_WIDTH) { 501 | maxPreviewWidth = MAX_PREVIEW_WIDTH; 502 | } 503 | 504 | if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) { 505 | maxPreviewHeight = MAX_PREVIEW_HEIGHT; 506 | } 507 | 508 | // Danger, W.R.! Attempting to use too large a preview size could exceed the camera 509 | // bus' bandwidth limitation, resulting in gorgeous previews but the storage of 510 | // garbage capture data. 511 | mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), 512 | rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth, 513 | maxPreviewHeight, largest); 514 | 515 | // We fit the aspect ratio of TextureView to the size of preview we picked. 516 | int orientation = getResources().getConfiguration().orientation; 517 | if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 518 | mTextureView.setAspectRatio( 519 | mPreviewSize.getWidth(), mPreviewSize.getHeight()); 520 | } else { 521 | mTextureView.setAspectRatio( 522 | mPreviewSize.getHeight(), mPreviewSize.getWidth()); 523 | } 524 | 525 | // Check if the flash is supported. 526 | //Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); 527 | //mFlashSupported = available == null ? false : available; 528 | 529 | mCameraId = cameraId; 530 | return; 531 | } 532 | } catch (CameraAccessException e) { 533 | e.printStackTrace(); 534 | } catch (NullPointerException e) { 535 | // Currently an NPE is thrown when the Camera2API is used but not supported on the 536 | // device this code runs. 537 | ErrorDialog.newInstance(getString(R.string.camera_error)) 538 | .show(getChildFragmentManager(), FRAGMENT_DIALOG); 539 | } 540 | } 541 | 542 | /** 543 | * Opens the camera specified by {@link Camera2BasicFragment#mCameraId}. 544 | */ 545 | private void openCamera(int width, int height) { 546 | if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) 547 | != PackageManager.PERMISSION_GRANTED) { 548 | requestCameraPermission(); 549 | return; 550 | } 551 | setUpCameraOutputs(width, height); 552 | configureTransform(width, height); 553 | Activity activity = getActivity(); 554 | CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); 555 | try { 556 | if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { 557 | throw new RuntimeException("Time out waiting to lock camera opening."); 558 | } 559 | manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler); 560 | } catch (CameraAccessException e) { 561 | e.printStackTrace(); 562 | } catch (InterruptedException e) { 563 | throw new RuntimeException("Interrupted while trying to lock camera opening.", e); 564 | } 565 | } 566 | 567 | /** 568 | * Closes the current {@link CameraDevice}. 569 | */ 570 | private void closeCamera() { 571 | try { 572 | mCameraOpenCloseLock.acquire(); 573 | if (null != mCaptureSession) { 574 | mCaptureSession.close(); 575 | mCaptureSession = null; 576 | } 577 | if (null != mCameraDevice) { 578 | mCameraDevice.close(); 579 | mCameraDevice = null; 580 | } 581 | if (null != mImageReader) { 582 | mImageReader.close(); 583 | mImageReader = null; 584 | } 585 | } catch (InterruptedException e) { 586 | throw new RuntimeException("Interrupted while trying to lock camera closing.", e); 587 | } finally { 588 | mCameraOpenCloseLock.release(); 589 | } 590 | } 591 | 592 | /** 593 | * Starts a background thread and its {@link Handler}. 594 | */ 595 | private void startBackgroundThread() { 596 | mBackgroundThread = new HandlerThread("CameraBackground"); 597 | mBackgroundThread.start(); 598 | mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); 599 | } 600 | 601 | /** 602 | * Stops the background thread and its {@link Handler}. 603 | */ 604 | private void stopBackgroundThread() { 605 | mBackgroundThread.quitSafely(); 606 | try { 607 | mBackgroundThread.join(); 608 | mBackgroundThread = null; 609 | mBackgroundHandler = null; 610 | } catch (InterruptedException e) { 611 | e.printStackTrace(); 612 | } 613 | } 614 | 615 | /** 616 | * Creates a new {@link CameraCaptureSession} for camera preview. 617 | */ 618 | private void createCameraPreviewSession() { 619 | try { 620 | SurfaceTexture texture = mTextureView.getSurfaceTexture(); 621 | assert texture != null; 622 | 623 | // We configure the size of default buffer to be the size of camera preview we want. 624 | texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 625 | 626 | // This is the output Surface we need to start preview. 627 | Surface surface = new Surface(texture); 628 | 629 | // We set up a CaptureRequest.Builder with the output Surface. 630 | mPreviewRequestBuilder 631 | = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 632 | mPreviewRequestBuilder.addTarget(surface); 633 | mPreviewRequestBuilder.addTarget(mImageReader.getSurface()); 634 | 635 | // Here, we create a CameraCaptureSession for camera preview. 636 | mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), 637 | new CameraCaptureSession.StateCallback() { 638 | 639 | @Override 640 | public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { 641 | // The camera is already closed 642 | if (null == mCameraDevice) { 643 | return; 644 | } 645 | 646 | // When the session is ready, we start displaying the preview. 647 | mCaptureSession = cameraCaptureSession; 648 | try { 649 | // Auto focus should be continuous for camera preview. 650 | mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, 651 | CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 652 | // Flash is automatically enabled when necessary. 653 | //setAutoFlash(mPreviewRequestBuilder); 654 | 655 | // Finally, we start displaying the camera preview. 656 | mPreviewRequest = mPreviewRequestBuilder.build(); 657 | mCaptureSession.setRepeatingRequest(mPreviewRequest, 658 | mCaptureCallback, mBackgroundHandler); 659 | } catch (CameraAccessException e) { 660 | e.printStackTrace(); 661 | } 662 | } 663 | 664 | @Override 665 | public void onConfigureFailed( 666 | @NonNull CameraCaptureSession cameraCaptureSession) { 667 | showToast("Failed"); 668 | } 669 | }, null 670 | ); 671 | 672 | 673 | 674 | } catch (CameraAccessException e) { 675 | e.printStackTrace(); 676 | } 677 | } 678 | 679 | /** 680 | * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`. 681 | * This method should be called after the camera preview size is determined in 682 | * setUpCameraOutputs and also the size of `mTextureView` is fixed. 683 | * 684 | * @param viewWidth The width of `mTextureView` 685 | * @param viewHeight The height of `mTextureView` 686 | */ 687 | private void configureTransform(int viewWidth, int viewHeight) { 688 | Activity activity = getActivity(); 689 | if (null == mTextureView || null == mPreviewSize || null == activity) { 690 | return; 691 | } 692 | int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 693 | Matrix matrix = new Matrix(); 694 | RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); 695 | RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth()); 696 | float centerX = viewRect.centerX(); 697 | float centerY = viewRect.centerY(); 698 | if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { 699 | bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()); 700 | matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL); 701 | float scale = Math.max( 702 | (float) viewHeight / mPreviewSize.getHeight(), 703 | (float) viewWidth / mPreviewSize.getWidth()); 704 | matrix.postScale(scale, scale, centerX, centerY); 705 | matrix.postRotate(90 * (rotation - 2), centerX, centerY); 706 | } else if (Surface.ROTATION_180 == rotation) { 707 | matrix.postRotate(180, centerX, centerY); 708 | } 709 | mTextureView.setTransform(matrix); 710 | } 711 | 712 | /** 713 | * Retrieves the JPEG orientation from the specified screen rotation. 714 | * 715 | * @param rotation The screen rotation. 716 | * @return The JPEG orientation (one of 0, 90, 270, and 360) 717 | */ 718 | private int getOrientation(int rotation) { 719 | // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X) 720 | // We have to take that into account and rotate JPEG properly. 721 | // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS. 722 | // For devices with orientation of 270, we need to rotate the JPEG 180 degrees. 723 | return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360; 724 | } 725 | 726 | /** 727 | * Compares two {@code Size}s based on their areas. 728 | */ 729 | static class CompareSizesByArea implements Comparator { 730 | 731 | @Override 732 | public int compare(Size lhs, Size rhs) { 733 | // We cast here to ensure the multiplications won't overflow 734 | return Long.signum((long) lhs.getWidth() * lhs.getHeight() - 735 | (long) rhs.getWidth() * rhs.getHeight()); 736 | } 737 | 738 | } 739 | 740 | /** 741 | * Shows an error message dialog. 742 | */ 743 | public static class ErrorDialog extends DialogFragment { 744 | 745 | private static final String ARG_MESSAGE = "message"; 746 | 747 | public static ErrorDialog newInstance(String message) { 748 | ErrorDialog dialog = new ErrorDialog(); 749 | Bundle args = new Bundle(); 750 | args.putString(ARG_MESSAGE, message); 751 | dialog.setArguments(args); 752 | return dialog; 753 | } 754 | 755 | @Override 756 | public Dialog onCreateDialog(Bundle savedInstanceState) { 757 | final Activity activity = getActivity(); 758 | return new AlertDialog.Builder(activity) 759 | .setMessage(getArguments().getString(ARG_MESSAGE)) 760 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 761 | @Override 762 | public void onClick(DialogInterface dialogInterface, int i) { 763 | activity.finish(); 764 | } 765 | }) 766 | .create(); 767 | } 768 | 769 | } 770 | 771 | /** 772 | * Shows OK/Cancel confirmation dialog about camera permission. 773 | */ 774 | public static class ConfirmationDialog extends DialogFragment { 775 | 776 | @Override 777 | public Dialog onCreateDialog(Bundle savedInstanceState) { 778 | final Fragment parent = getParentFragment(); 779 | return new AlertDialog.Builder(getActivity()) 780 | .setMessage(R.string.request_permission) 781 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 782 | @Override 783 | public void onClick(DialogInterface dialog, int which) { 784 | FragmentCompat.requestPermissions(parent, 785 | new String[]{Manifest.permission.CAMERA}, 786 | REQUEST_CAMERA_PERMISSION); 787 | } 788 | }) 789 | .setNegativeButton(android.R.string.cancel, 790 | new DialogInterface.OnClickListener() { 791 | @Override 792 | public void onClick(DialogInterface dialog, int which) { 793 | Activity activity = parent.getActivity(); 794 | if (activity != null) { 795 | activity.finish(); 796 | } 797 | } 798 | }) 799 | .create(); 800 | } 801 | } 802 | 803 | 804 | @Override 805 | public void onViewCreated(final View view, Bundle savedInstanceState) { 806 | textView = (TextView) view.findViewById(R.id.textView); 807 | textView.setBackgroundColor(Color.BLACK); 808 | inferenceInterface = InitSession(); 809 | mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture); 810 | } 811 | 812 | String[] LoadFile(String fileName){ 813 | InputStream is = null; 814 | try { 815 | is = getActivity().getAssets().open(fileName); 816 | } catch (IOException e) { 817 | e.printStackTrace(); 818 | } 819 | BufferedReader r = new BufferedReader(new InputStreamReader(is)); 820 | StringBuilder total = new StringBuilder(); 821 | String line; 822 | try { 823 | while ((line = r.readLine()) != null) { 824 | total.append(line).append('\n'); 825 | } 826 | } catch (IOException e) { 827 | e.printStackTrace(); 828 | } 829 | return total.toString().split("\n"); 830 | } 831 | 832 | TensorFlowInferenceInterface InitSession(){ 833 | inferenceInterface = new TensorFlowInferenceInterface(); 834 | inferenceInterface.initializeTensorFlow(getActivity().getAssets(), MODEL_FILE); 835 | OutputNodes = LoadFile(OUTPUT_NODES); 836 | WORD_MAP = LoadFile("idmap"); 837 | return inferenceInterface; 838 | } 839 | 840 | String runModel(Bitmap imBitmap){ 841 | return GenerateCaptions(Preprocess(imBitmap)); 842 | } 843 | 844 | float[] Preprocess(Bitmap imBitmap){ 845 | imBitmap = Bitmap.createScaledBitmap(imBitmap, IMAGE_SIZE, IMAGE_SIZE, true); 846 | int[] intValues = new int[IMAGE_SIZE * IMAGE_SIZE]; 847 | float[] floatValues = new float[IMAGE_SIZE * IMAGE_SIZE * 3]; 848 | 849 | imBitmap.getPixels(intValues, 0, IMAGE_SIZE, 0, 0, IMAGE_SIZE, IMAGE_SIZE); 850 | 851 | for (int i = 0; i < intValues.length; ++i) { 852 | final int val = intValues[i]; 853 | floatValues[i * 3] = ((float)((val >> 16) & 0xFF))/255;//R 854 | floatValues[i * 3 + 1] = ((float)((val >> 8) & 0xFF))/255;//G 855 | floatValues[i * 3 + 2] = ((float)((val & 0xFF)))/255;//B 856 | } 857 | return floatValues; 858 | } 859 | 860 | String GenerateCaptions(float[] imRGBMatrix){ 861 | inferenceInterface.fillNodeFloat(INPUT1, DIM_IMAGE, imRGBMatrix); 862 | inferenceInterface.runInference(OutputNodes); 863 | 864 | String result = ""; 865 | int temp[][]= new int[NUM_TIMESTEPS][1]; 866 | for(int i = 0; i*/){ 869 | return result; 870 | } 871 | result += WORD_MAP[temp[i][0]]+" "; 872 | } 873 | return null; 874 | } 875 | 876 | public final ImageReader.OnImageAvailableListener mOnImageAvailableListener 877 | = new ImageReader.OnImageAvailableListener() { 878 | 879 | @Override 880 | public void onImageAvailable(ImageReader reader) { 881 | Image image = null; 882 | try { 883 | image = reader.acquireLatestImage(); 884 | ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 885 | byte[] imageBytes = new byte[buffer.remaining()]; 886 | buffer.get(imageBytes); 887 | Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); 888 | final String text = runModel(bitmap); 889 | getActivity().runOnUiThread(new Runnable() { 890 | @Override 891 | public void run() { 892 | textView.setText(text); 893 | 894 | } 895 | }); 896 | } finally { 897 | if (image != null) { 898 | image.close(); 899 | } 900 | } 901 | } 902 | }; 903 | 904 | } 905 | -------------------------------------------------------------------------------- /Application/src/main/java/com/example/android/camera2basic/CameraActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.android.camera2basic; 18 | 19 | import android.app.Activity; 20 | import android.os.Bundle; 21 | 22 | 23 | public class CameraActivity extends Activity { 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_camera); 29 | if (null == savedInstanceState) { 30 | getFragmentManager().beginTransaction() 31 | .replace(R.id.container, Camera2BasicFragment.newInstance()) 32 | .commit(); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Application/src/main/res/drawable-hdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-hdpi/ic_action_info.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-hdpi/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-hdpi/tile.9.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-mdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-mdpi/ic_action_info.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xhdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-xhdpi/ic_action_info.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xxhdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-xxhdpi/ic_action_info.png -------------------------------------------------------------------------------- /Application/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neural-nuts/Cam2Caption/b0db9e05a717cff8aaf6b36b7173052f664cb24b/Application/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Application/src/main/res/layout-land/fragment_camera2_basic.xml: -------------------------------------------------------------------------------- 1 | 16 | 19 | 20 | 27 | 28 | 38 | 39 |