├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── android └── mlkit-automl │ ├── .gitignore │ ├── .idea │ ├── codeStyles │ │ ├── Project.xml │ │ └── codeStyleConfig.xml │ ├── encodings.xml │ ├── inspectionProfiles │ │ ├── ktlint.xml │ │ └── profiles_settings.xml │ ├── misc.xml │ └── runConfigurations.xml │ ├── app │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ └── automl │ │ │ ├── dict.txt │ │ │ ├── manifest.json │ │ │ └── model.tflite │ │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── firebase │ │ │ └── codelab │ │ │ └── mlkit │ │ │ └── automl │ │ │ ├── BaseActivity.kt │ │ │ ├── ImageClassifier.kt │ │ │ └── StillImageActivity.kt │ │ └── res │ │ ├── drawable-anydpi │ │ ├── ic_photo_camera.xml │ │ └── ic_photo_library.xml │ │ ├── drawable-hdpi │ │ ├── dandelion_2817950_640.jpg │ │ ├── dandelion_4110356_640.jpg │ │ ├── rose_1463562_640.jpg │ │ ├── rose_3063284_640.jpg │ │ ├── sunflower_1627193_640.jpg │ │ └── sunflower_3292932_640.jpg │ │ ├── layout │ │ └── activity_still_image.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── file_paths.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── flower_photos.zip └── ios └── mlkit-automl ├── .gitignore ├── Images.xcassets ├── AppIcon.appiconset │ ├── 100.png │ ├── 1024.png │ ├── 114.png │ ├── 120.png │ ├── 144.png │ ├── 152.png │ ├── 167.png │ ├── 180.png │ ├── 20.png │ ├── 29.png │ ├── 40.png │ ├── 50.png │ ├── 57.png │ ├── 58.png │ ├── 60.png │ ├── 72.png │ ├── 76.png │ ├── 80.png │ ├── 87.png │ └── Contents.json ├── Contents.json ├── LaunchImage.launchimage │ └── Contents.json ├── Logo.imageset │ ├── Contents.json │ ├── logo1024-universal-341@1x.png │ ├── logo1024-universal-341@2x.png │ └── logo1024-universal-341@3x.png ├── ic_account_circle_36pt.imageset │ ├── Contents.json │ ├── ic_account_circle_36pt.png │ ├── ic_account_circle_36pt_2x.png │ └── ic_account_circle_36pt_3x.png ├── ic_more_vert_white.imageset │ ├── Contents.json │ ├── ic_more_vert_white.png │ ├── ic_more_vert_white_2x.png │ └── ic_more_vert_white_3x.png ├── ic_send.imageset │ ├── Contents.json │ ├── ic_send.png │ ├── ic_send_2x.png │ └── ic_send_3x.png ├── photo_camera.imageset │ ├── Contents.json │ ├── photo_camera_2x.png │ └── photo_camera_3x.png ├── photo_library.imageset │ ├── Contents.json │ ├── photo_library_2x.png │ └── photo_library_3x.png ├── switch_camera.imageset │ ├── Contents.json │ ├── switch_camera_2x.png │ └── switch_camera_3x.png └── video_camera.imageset │ ├── Contents.json │ ├── video_camera_2x.png │ └── video_camera_3x.png ├── LaunchScreen.xib ├── MLVisionExample.xcodeproj └── project.pbxproj ├── MLVisionExample ├── AppDelegate.swift ├── Base.lproj │ └── Main.storyboard ├── CameraViewController.swift ├── ImageClassifier.swift ├── Info.plist ├── MLKitExtensions.swift ├── UIUtilities.swift └── ViewController.swift ├── Podfile ├── Podfile.lock └── Resources ├── automl ├── dict.txt ├── manifest.json └── model.tflite └── flowers ├── dandelion_2817950_640.jpg ├── dandelion_4110356_640.jpg ├── rose_1463562_640.jpg ├── rose_3063284_640.jpg ├── sunflower_1627193_640.jpg └── sunflower_3292932_640.jpg /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Codelabs for ML Kit for Firebase 2 | ============ 3 | 4 | This repository contains the code for the AutoML Vision for ML Kit codelab: 5 | 6 | * [Train and deploy on-device image classification model with AutoML Vision Edge in ML Kit](https://codelabs.developers.google.com/codelabs/automl-vision-edge-in-mlkit) 7 | 8 | Introduction 9 | ------------ 10 | In these codelabs, you will learn: 11 | 12 | * How to train an image classification model using AutoML Vision Edge in ML Kit. 13 | * How to run it in a sample Android or iOS app using the ML Kit SDK. 14 | 15 | Pre-requisites 16 | -------------- 17 | None. 18 | 19 | Getting Started 20 | --------------- 21 | Visit the Google codelabs site to follow along the guided steps. 22 | 23 | Screenshots 24 | ----------- 25 | 26 | Support 27 | ------- 28 | 29 | - Stack Overflow: http://stackoverflow.com/questions/tagged/firebase-mlkit 30 | 31 | If you've found an error in this sample, please file an issue: 32 | https://github.com/googlecodelabs/automl-vision-edge-in-mlkit/issues 33 | 34 | Patches are encouraged, and may be submitted by forking this project and 35 | submitting a pull request through GitHub. 36 | 37 | License 38 | ------- 39 | 40 | Copyright 2019 Google LLC 41 | 42 | Licensed under the Apache License, Version 2.0 (the "License"); 43 | you may not use this file except in compliance with the License. 44 | You may obtain a copy of the License at 45 | 46 | https://www.apache.org/licenses/LICENSE-2.0 47 | 48 | Unless required by applicable law or agreed to in writing, software 49 | distributed under the License is distributed on an "AS IS" BASIS, 50 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 51 | See the License for the specific language governing permissions and 52 | limitations under the License. 53 | -------------------------------------------------------------------------------- /android/mlkit-automl/.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | *.aab 5 | 6 | # Files for the ART/Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | out/ 16 | 17 | # Gradle files 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # IntelliJ 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/tasks.xml 40 | .idea/gradle.xml 41 | .idea/assetWizardSettings.xml 42 | .idea/dictionaries 43 | .idea/libraries 44 | .idea/caches 45 | # Android Studio 3 in .gitignore file. 46 | .idea/caches/build_file_checksums.ser 47 | .idea/modules.xml 48 | 49 | # Keystore files 50 | # Uncomment the following lines if you do not want to check your keystore files in. 51 | #*.jks 52 | #*.keystore 53 | 54 | # External native build folder generated in Android Studio 2.2 and later 55 | .externalNativeBuild 56 | 57 | # Google Services (e.g. APIs or Firebase) 58 | google-services.json 59 | 60 | # Freeline 61 | freeline.py 62 | freeline/ 63 | freeline_project_description.json 64 | 65 | # fastlane 66 | fastlane/report.xml 67 | fastlane/Preview.html 68 | fastlane/screenshots 69 | fastlane/test_output 70 | fastlane/readme.md 71 | 72 | # Version control 73 | vcs.xml 74 | 75 | # lint 76 | lint/intermediates/ 77 | lint/generated/ 78 | lint/outputs/ 79 | lint/tmp/ 80 | # lint/reports/ -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 33 | -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/inspectionProfiles/ktlint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /android/mlkit-automl/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /android/mlkit-automl/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android-extensions' 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion 28 7 | buildToolsVersion '28.0.3' 8 | 9 | defaultConfig { 10 | applicationId "com.google.firebase.codelab.mlkit.automl" 11 | minSdkVersion 21 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | lintOptions { 19 | abortOnError false 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | 29 | aaptOptions { 30 | noCompress "tflite" 31 | } 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | packagingOptions { 39 | exclude 'META-INF/atomicfu.kotlin_module' 40 | } 41 | } 42 | 43 | dependencies { 44 | implementation fileTree(dir: 'libs', include: ['*.jar']) 45 | 46 | implementation 'androidx.appcompat:appcompat:1.0.0' 47 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 48 | implementation 'com.google.android.material:material:1.0.0' 49 | implementation 'androidx.annotation:annotation:1.0.0' 50 | implementation 'androidx.legacy:legacy-support-v13:1.0.0' 51 | 52 | implementation 'com.google.firebase:firebase-ml-vision:20.0.0' 53 | implementation 'com.google.firebase:firebase-ml-vision-automl:16.0.0' 54 | 55 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" 56 | 57 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.0" 58 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.0" 59 | } 60 | 61 | apply plugin: 'com.google.gms.google-services' 62 | apply plugin: 'kotlin-android-extensions' -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 34 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/assets/automl/dict.txt: -------------------------------------------------------------------------------- 1 | daisy 2 | dandelion 3 | roses 4 | sunflowers 5 | tulips -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/assets/automl/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "modelFile": "model.tflite", 3 | "labelsFile": "dict.txt", 4 | "modelType": "IMAGE_LABELING" 5 | } -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/assets/automl/model.tflite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/automl-vision-edge-in-mlkit/bec51615d216da3a93e15789b81bf57f80b98622/android/mlkit-automl/app/src/main/assets/automl/model.tflite -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/java/com/google/firebase/codelab/mlkit/automl/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 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 | * https://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.google.firebase.codelab.mlkit.automl 18 | 19 | import android.content.pm.PackageManager 20 | import androidx.appcompat.app.AppCompatActivity 21 | import android.os.Bundle 22 | import android.util.Log 23 | import androidx.core.app.ActivityCompat 24 | import androidx.core.content.ContextCompat 25 | 26 | /** Base activity that requests all needed permission at launch */ 27 | abstract class BaseActivity : AppCompatActivity(), 28 | ActivityCompat.OnRequestPermissionsResultCallback { 29 | 30 | private val requiredPermissions: Array by lazy { 31 | try { 32 | this.packageManager.getPackageInfo( 33 | this.packageName, 34 | PackageManager.GET_PERMISSIONS 35 | ).requestedPermissions ?: arrayOf() 36 | } catch (e: PackageManager.NameNotFoundException) { 37 | arrayOf() 38 | } 39 | } 40 | 41 | private fun allPermissionsGranted() = requiredPermissions.none { !isPermissionGranted(it) } 42 | 43 | private fun requestRuntimePermissions() { 44 | val allNeededPermissions = requiredPermissions.filter { !isPermissionGranted(it) } 45 | 46 | if (allNeededPermissions.isNotEmpty()) { 47 | ActivityCompat.requestPermissions( 48 | this, 49 | allNeededPermissions.toTypedArray(), 50 | PERMISSION_REQUESTS 51 | ) 52 | } 53 | } 54 | 55 | private fun isPermissionGranted(permission: String): Boolean { 56 | when (ContextCompat.checkSelfPermission(this, permission)) { 57 | PackageManager.PERMISSION_GRANTED -> { 58 | Log.i(TAG, "Permission granted: $permission") 59 | return true 60 | } 61 | else -> { 62 | Log.i(TAG, "Permission NOT granted: $permission") 63 | return false 64 | } 65 | } 66 | } 67 | 68 | override fun onCreate(savedInstanceState: Bundle?) { 69 | super.onCreate(savedInstanceState) 70 | 71 | if (!allPermissionsGranted()) { 72 | requestRuntimePermissions() 73 | } 74 | } 75 | 76 | companion object { 77 | 78 | /** Tag for the [Log]. */ 79 | private const val TAG = "BaseActivity" 80 | 81 | private const val PERMISSION_REQUESTS = 1 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/java/com/google/firebase/codelab/mlkit/automl/ImageClassifier.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 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 | * https://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.google.firebase.codelab.mlkit.automl 18 | 19 | import android.content.Context 20 | import android.graphics.Bitmap 21 | import android.os.SystemClock 22 | import android.util.Log 23 | import android.widget.Toast 24 | import com.google.android.gms.tasks.Task 25 | import com.google.android.gms.tasks.TaskCompletionSource 26 | import com.google.firebase.ml.common.FirebaseMLException 27 | import com.google.firebase.ml.common.modeldownload.FirebaseLocalModel 28 | import com.google.firebase.ml.common.modeldownload.FirebaseModelManager 29 | import com.google.firebase.ml.common.modeldownload.FirebaseRemoteModel 30 | import com.google.firebase.ml.vision.FirebaseVision 31 | import com.google.firebase.ml.vision.common.FirebaseVisionImage 32 | import com.google.firebase.ml.vision.label.FirebaseVisionImageLabel 33 | import com.google.firebase.ml.vision.label.FirebaseVisionImageLabeler 34 | import com.google.firebase.ml.vision.label.FirebaseVisionOnDeviceAutoMLImageLabelerOptions 35 | import java.io.IOException 36 | import java.util.Locale 37 | 38 | /** Classifies images with ML Kit AutoML. */ 39 | class ImageClassifier 40 | /** Initializes an `ImageClassifier`. */ 41 | @Throws(FirebaseMLException::class) 42 | internal constructor(context: Context) { 43 | 44 | /** MLKit AutoML Image Classifier */ 45 | private val labeler: FirebaseVisionImageLabeler? 46 | private var remoteModelDownloadSucceeded = false 47 | 48 | init { 49 | val remoteModel = FirebaseRemoteModel.Builder(REMOTE_MODEL_NAME).build() 50 | FirebaseModelManager.getInstance() 51 | .registerRemoteModel(remoteModel) 52 | 53 | FirebaseModelManager.getInstance() 54 | .registerLocalModel( 55 | FirebaseLocalModel.Builder(LOCAL_MODEL_NAME) 56 | .setAssetFilePath(LOCAL_MODEL_PATH) 57 | .build() 58 | ) 59 | 60 | val options = FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder() 61 | .setConfidenceThreshold(CONFIDENCE_THRESHOLD) 62 | .setLocalModelName(LOCAL_MODEL_NAME) 63 | .setRemoteModelName(REMOTE_MODEL_NAME) 64 | .build() 65 | 66 | labeler = FirebaseVision.getInstance().getOnDeviceAutoMLImageLabeler(options) 67 | 68 | Toast.makeText( 69 | context, 70 | "Begin downloading the remote AutoML model.", 71 | Toast.LENGTH_SHORT 72 | ).show() 73 | 74 | // Track the remote model download progress. 75 | FirebaseModelManager.getInstance() 76 | .downloadRemoteModelIfNeeded(remoteModel) 77 | .addOnCompleteListener { task -> 78 | if (task.isSuccessful) { 79 | Toast.makeText( 80 | context, 81 | "Download remote AutoML model success.", 82 | Toast.LENGTH_SHORT 83 | ).show() 84 | remoteModelDownloadSucceeded = true 85 | } else { 86 | val downloadingError = "Error downloading remote model." 87 | Log.e(TAG, downloadingError, task.exception) 88 | Toast.makeText(context, downloadingError, Toast.LENGTH_SHORT).show() 89 | } 90 | } 91 | 92 | Log.d(TAG, "Created a Firebase ML Kit AutoML Image Labeler.") 93 | } 94 | 95 | /** Classifies a frame from the preview stream. */ 96 | internal fun classifyFrame(bitmap: Bitmap): Task { 97 | if (labeler == null) { 98 | Log.e(TAG, "Image classifier has not been initialized; Skipped.") 99 | val e = IllegalStateException("Uninitialized Classifier.") 100 | 101 | val completionSource = TaskCompletionSource() 102 | completionSource.setException(e) 103 | return completionSource.task 104 | } 105 | 106 | val startTime = SystemClock.uptimeMillis() 107 | val image = FirebaseVisionImage.fromBitmap(bitmap) 108 | 109 | return labeler.processImage(image).continueWith { task -> 110 | val endTime = SystemClock.uptimeMillis() 111 | Log.d(TAG, "Time to run model inference: " + java.lang.Long.toString(endTime - startTime)) 112 | 113 | val labelProbList = task.result 114 | 115 | // Indicate whether the remote or local model is used. 116 | // Note: in most common cases, once a remote model is downloaded it will be used. However, in 117 | // very rare cases, the model itself might not be valid, and thus the local model is used. In 118 | // addition, since model download failures can be transient, and model download can also be 119 | // triggered in the background during inference, it is possible that a remote model is used 120 | // even if the first download fails. 121 | var textToShow = "Source: " + 122 | (if (this.remoteModelDownloadSucceeded) "Remote" else "Local") + 123 | " model\n" 124 | textToShow += "Latency: " + java.lang.Long.toString(endTime - startTime) + "ms\n" 125 | textToShow += if (labelProbList.isNullOrEmpty()) 126 | "No Result" 127 | else 128 | printTopKLabels(labelProbList) 129 | 130 | // print the results 131 | textToShow 132 | } 133 | } 134 | 135 | /** Closes labeler to release resources. */ 136 | internal fun close() { 137 | try { 138 | labeler?.close() 139 | } catch (e: IOException) { 140 | Log.e(TAG, "Unable to close the labeler instance", e) 141 | } 142 | 143 | } 144 | 145 | /** Prints top-K labels, to be shown in UI as the results. */ 146 | private val printTopKLabels: (List) -> String = { 147 | it.joinToString( 148 | separator = "\n", 149 | limit = RESULTS_TO_SHOW 150 | ) { label -> 151 | String.format(Locale.getDefault(), "Label: %s, Confidence: %4.2f", label.text, label.confidence) 152 | } 153 | } 154 | 155 | companion object { 156 | 157 | /** Tag for the [Log]. */ 158 | private const val TAG = "MLKitAutoMLCodelab" 159 | 160 | /** Name of the local model file stored in Assets. */ 161 | private const val LOCAL_MODEL_NAME = "automl_image_labeling_model" 162 | 163 | /** Path of local model file stored in Assets. */ 164 | private const val LOCAL_MODEL_PATH = "automl/manifest.json" 165 | 166 | /** Name of the remote model in Firebase ML Kit server. */ 167 | private const val REMOTE_MODEL_NAME = "mlkit_flowers" 168 | 169 | /** Number of results to show in the UI. */ 170 | private const val RESULTS_TO_SHOW = 3 171 | 172 | /** Min probability to classify the given image as belong to a category. */ 173 | private const val CONFIDENCE_THRESHOLD = 0.6f 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /android/mlkit-automl/app/src/main/java/com/google/firebase/codelab/mlkit/automl/StillImageActivity.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 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 | * https://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.google.firebase.codelab.mlkit.automl 18 | 19 | import android.app.Activity 20 | import android.content.Intent 21 | import android.graphics.Bitmap 22 | import android.graphics.BitmapFactory 23 | import android.net.Uri 24 | import android.os.Bundle 25 | import android.provider.MediaStore 26 | import android.util.Log 27 | import android.widget.Button 28 | import android.widget.ImageButton 29 | import android.widget.ImageView 30 | import android.widget.TextView 31 | import androidx.appcompat.app.AppCompatActivity 32 | import androidx.core.content.FileProvider 33 | import com.google.firebase.ml.common.FirebaseMLException 34 | import com.google.firebase.ml.vision.common.FirebaseVisionImage 35 | import java.io.File 36 | import java.io.IOException 37 | import java.text.SimpleDateFormat 38 | import java.util.Date 39 | 40 | class StillImageActivity : BaseActivity() { 41 | 42 | private var currentPhotoFile: File? = null 43 | private var imagePreview: ImageView? = null 44 | private var textView: TextView? = null 45 | 46 | private var classifier: ImageClassifier? = null 47 | private var currentImageIndex = 0 48 | private var bundledImageList: Array? = null 49 | 50 | override fun onCreate(savedInstanceState: Bundle?) { 51 | super.onCreate(savedInstanceState) 52 | 53 | setContentView(R.layout.activity_still_image) 54 | imagePreview = findViewById(R.id.image_preview) 55 | textView = findViewById(R.id.result_text) 56 | findViewById(R.id.photo_camera_button)?.setOnClickListener { takePhoto() } 57 | findViewById(R.id.photo_library_button)?.setOnClickListener { chooseFromLibrary() } 58 | findViewById