├── .gitignore ├── AndroidManifest.xml ├── LICENSE ├── README.md ├── assets ├── OpenSans-Regular.ttf ├── affenpinscher.jpg ├── afghan_hound.jpg ├── african_hunting_dog.jpg ├── airedale_terrier.jpg ├── american_staffordshire_terrier.jpg ├── appenzeller_sennenhund.jpg ├── australian_terrier.jpg ├── basenji.jpg ├── basset_hound.jpg ├── beagle.jpg ├── bedlington_terrier.jpg ├── bernese_mountain_dog.jpg ├── blenheim_spaniel.jpg ├── bloodhound.jpg ├── bluetick_coonhound.jpg ├── border_collie.jpg ├── border_terrier.jpg ├── borzoi.jpg ├── boston_terrier.jpg ├── bouvier_des_flandres.jpg ├── boxer_dog.jpg ├── brabancon_griffon.jpg ├── briard.jpg ├── brittany_spaniel.jpg ├── bull_mastiff.jpg ├── cairn_terrier.jpg ├── cardigan_welsh_corgi.jpg ├── chesapeake_bay_retriever.jpg ├── chihuahua_dog.jpg ├── chow_chow.jpg ├── clumber_spaniel.jpg ├── coated_retriever.jpg ├── coated_wheaten_terrier.jpg ├── cocker_spaniel.jpg ├── collie.jpg ├── curly_coated_retriever.jpg ├── dachshund.jpg ├── dandie_dinmont_terrier.jpg ├── dhole.jpg ├── dingo.jpg ├── doberman.jpg ├── english_foxhound.jpg ├── english_setter.jpg ├── english_springer_spaniel.jpg ├── entlebucher_mountain_dog.jpg ├── eskimo_dog.jpg ├── french_bulldog.jpg ├── german_shepherd.jpg ├── giant_schnauzer.jpg ├── golden_retriever.jpg ├── gordon_setter.jpg ├── great_dane.jpg ├── great_pyrenees.jpg ├── greater_swiss_mountain_dog.jpg ├── groenendael_dog.jpg ├── haired_fox_terrier.jpg ├── haired_pointer.jpg ├── ibizan_hound.jpg ├── irish_setter.jpg ├── irish_terrier.jpg ├── irish_water_spaniel.jpg ├── irish_wolfhound.jpg ├── italian_greyhound.jpg ├── japanese_spaniel.jpg ├── keeshond.jpg ├── kelpie.jpg ├── kerry_blue_terrier.jpg ├── komondor.jpg ├── kuvasz.jpg ├── labrador_retriever.jpg ├── lakeland_terrier.jpg ├── leonberger.jpg ├── lhasa_apso.jpg ├── malamute.jpg ├── malinois_dog.jpg ├── maltese_dog.jpg ├── mexican_hairless_dog.jpg ├── miniature_pinscher.jpg ├── miniature_poodle.jpg ├── miniature_schnauzer.jpg ├── newfoundland_dog.jpg ├── nodata.jpg ├── norfolk_terrier.jpg ├── norwegian_elkhound.jpg ├── norwich_terrier.jpg ├── old_english_sheepdog.jpg ├── otterhound.jpg ├── papillon_dog.jpg ├── pekingese.jpg ├── pembroke_welsh_corgi.jpg ├── pomeranian.jpg ├── pug.jpg ├── redbone_coonhound.jpg ├── rhodesian_ridgeback.jpg ├── rottweiler.jpg ├── saint_bernard.jpg ├── saluki.jpg ├── samoyed_dog.jpg ├── schipperke.jpg ├── scotch_terrier.jpg ├── scottish_deerhound.jpg ├── sealyham_terrier.jpg ├── shetland_sheepdog.jpg ├── shih_tzu.jpg ├── siberian_husky.jpg ├── silky_terrier.jpg ├── staffordshire_bull_terrier.jpg ├── standard_poodle.jpg ├── standard_schnauzer.jpg ├── stripped.pb ├── sussex_spaniel.jpg ├── tan_coonhound.jpg ├── tibetan_mastiff.jpg ├── tibetan_terrier.jpg ├── toy_poodle.jpg ├── toy_terrier.jpg ├── vizsla.jpg ├── walker_hound.jpg ├── weimaraner.jpg ├── welsh_springer_spaniel.jpg ├── west_highland_white_terrier.jpg ├── whippet.jpg └── yorkshire_terrier.jpg ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── metadata ├── ar │ └── summary.txt ├── de │ └── summary.txt ├── en-US │ ├── full_description.txt │ ├── images │ │ ├── featureGraphic.png │ │ ├── icon.png │ │ └── phoneScreenshots │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ ├── 5.png │ │ │ ├── 6.png │ │ │ ├── 7.png │ │ │ └── 8.png │ ├── short_description.txt │ ├── summary.txt │ └── title.txt ├── es │ └── summary.txt ├── fr │ └── summary.txt ├── he │ └── summary.txt ├── it │ └── summary.txt ├── nb │ └── summary.txt ├── pl │ └── summary.txt ├── pt-BR │ └── summary.txt ├── pt-PT │ └── summary.txt ├── pt │ └── summary.txt ├── ro │ └── summary.txt ├── ru │ └── summary.txt ├── tr │ └── summary.txt ├── uk │ └── summary.txt └── zh-CN │ └── summary.txt ├── res ├── drawable-hdpi │ ├── camera_icon.png │ ├── ic_action_save.png │ └── ic_launcher.png ├── drawable-mdpi │ ├── camera_icon.png │ ├── ic_action_save.png │ └── ic_launcher.png ├── drawable-v21 │ └── button_background_selector.xml ├── drawable-xhdpi │ ├── camera_icon.png │ ├── ic_action_save.png │ └── ic_launcher.png ├── drawable-xxhdpi │ ├── camera_icon.png │ ├── ic_action_save.png │ └── ic_launcher.png ├── drawable-xxxhdpi │ └── ic_action_save.png ├── drawable │ ├── blackout_transition.xml │ ├── button_background_selector.xml │ ├── ic_change_language.xml │ └── roundedbutton.xml ├── layout │ ├── activity_camera.xml │ ├── activity_list.xml │ ├── camera_connection_fragment.xml │ ├── lang_dialog.xml │ ├── list_group.xml │ └── list_item.xml ├── menu │ └── mainmenu.xml ├── values-de │ └── strings.xml ├── values-fr │ └── strings.xml ├── values-ka │ └── strings.xml ├── values │ ├── colors.xml │ ├── filenames.xml │ └── strings.xml └── xml │ └── filepaths.xml └── src └── com └── jstappdev └── dbclf ├── AutoFitTextureView.java ├── CameraActivity.java ├── CameraConnectionFragment.java ├── Classifier.java ├── ClassifierActivity.java ├── LegacyCameraConnectionFragment.java ├── ListAdapter.java ├── RecognitionScoreView.java ├── SimpleListActivity.java ├── TensorFlowImageClassifier.java └── env └── ImageUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | release/ 16 | debug/ 17 | gradleBuild/ 18 | dbclf.iml 19 | .idea/ 20 | 21 | # Gradle files 22 | .gradle/ 23 | build/ 24 | 25 | # Local configuration file (sdk path, etc) 26 | local.properties 27 | 28 | # Proguard folder generated by Eclipse 29 | proguard/ 30 | 31 | # Log Files 32 | *.log 33 | 34 | # Android Studio Navigation editor temp files 35 | .navigation/ 36 | 37 | # Android Studio captures folder 38 | captures/ 39 | 40 | # IntelliJ 41 | *.iml 42 | .idea/workspace.xml 43 | .idea/tasks.xml 44 | .idea/gradle.xml 45 | .idea/assetWizardSettings.xml 46 | .idea/dictionaries 47 | .idea/libraries 48 | .idea/caches 49 | 50 | # Keystore files 51 | # Uncomment the following line if you do not want to check your keystore files in. 52 | #*.jks 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 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 22 | 27 | 30 | 31 | 32 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Identify Dog Breeds Android App 2 | 3 | This is the source code for the Identify Dog Breeds and Identify Dog Breeds Pro Android applications. The uploaded TensorFlow model (assets/stripped.pb) is the same as used in the free mobile app and was trained on an extended version of the 4 | Stanford Dogs Dataset. Based on the TensorFlow Android Camera Demo application, licensed under Apache License 2.0. French translation by Clément Thonon. Georgian translation by Giorgi Abulashvili. 5 | 6 | Project abandoned in favor of https://github.com/j05t/identify-dog-breeds-pro. The Pro version is available for free from the F-Droid store at https://f-droid.org/packages/com.jstappdev.identify_dog_breeds_pro/ so there is no reason to maintain a separate free version of the app. 7 | 8 | 9 | Screenshot Another Screenshot Another Screenshot 10 | 11 | ## Downloads 12 | Get it on F-Droid 13 | download 14 | -------------------------------------------------------------------------------- /assets/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /assets/affenpinscher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/affenpinscher.jpg -------------------------------------------------------------------------------- /assets/afghan_hound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/afghan_hound.jpg -------------------------------------------------------------------------------- /assets/african_hunting_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/african_hunting_dog.jpg -------------------------------------------------------------------------------- /assets/airedale_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/airedale_terrier.jpg -------------------------------------------------------------------------------- /assets/american_staffordshire_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/american_staffordshire_terrier.jpg -------------------------------------------------------------------------------- /assets/appenzeller_sennenhund.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/appenzeller_sennenhund.jpg -------------------------------------------------------------------------------- /assets/australian_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/australian_terrier.jpg -------------------------------------------------------------------------------- /assets/basenji.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/basenji.jpg -------------------------------------------------------------------------------- /assets/basset_hound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/basset_hound.jpg -------------------------------------------------------------------------------- /assets/beagle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/beagle.jpg -------------------------------------------------------------------------------- /assets/bedlington_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/bedlington_terrier.jpg -------------------------------------------------------------------------------- /assets/bernese_mountain_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/bernese_mountain_dog.jpg -------------------------------------------------------------------------------- /assets/blenheim_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/blenheim_spaniel.jpg -------------------------------------------------------------------------------- /assets/bloodhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/bloodhound.jpg -------------------------------------------------------------------------------- /assets/bluetick_coonhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/bluetick_coonhound.jpg -------------------------------------------------------------------------------- /assets/border_collie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/border_collie.jpg -------------------------------------------------------------------------------- /assets/border_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/border_terrier.jpg -------------------------------------------------------------------------------- /assets/borzoi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/borzoi.jpg -------------------------------------------------------------------------------- /assets/boston_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/boston_terrier.jpg -------------------------------------------------------------------------------- /assets/bouvier_des_flandres.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/bouvier_des_flandres.jpg -------------------------------------------------------------------------------- /assets/boxer_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/boxer_dog.jpg -------------------------------------------------------------------------------- /assets/brabancon_griffon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/brabancon_griffon.jpg -------------------------------------------------------------------------------- /assets/briard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/briard.jpg -------------------------------------------------------------------------------- /assets/brittany_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/brittany_spaniel.jpg -------------------------------------------------------------------------------- /assets/bull_mastiff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/bull_mastiff.jpg -------------------------------------------------------------------------------- /assets/cairn_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/cairn_terrier.jpg -------------------------------------------------------------------------------- /assets/cardigan_welsh_corgi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/cardigan_welsh_corgi.jpg -------------------------------------------------------------------------------- /assets/chesapeake_bay_retriever.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/chesapeake_bay_retriever.jpg -------------------------------------------------------------------------------- /assets/chihuahua_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/chihuahua_dog.jpg -------------------------------------------------------------------------------- /assets/chow_chow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/chow_chow.jpg -------------------------------------------------------------------------------- /assets/clumber_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/clumber_spaniel.jpg -------------------------------------------------------------------------------- /assets/coated_retriever.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/coated_retriever.jpg -------------------------------------------------------------------------------- /assets/coated_wheaten_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/coated_wheaten_terrier.jpg -------------------------------------------------------------------------------- /assets/cocker_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/cocker_spaniel.jpg -------------------------------------------------------------------------------- /assets/collie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/collie.jpg -------------------------------------------------------------------------------- /assets/curly_coated_retriever.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/curly_coated_retriever.jpg -------------------------------------------------------------------------------- /assets/dachshund.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/dachshund.jpg -------------------------------------------------------------------------------- /assets/dandie_dinmont_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/dandie_dinmont_terrier.jpg -------------------------------------------------------------------------------- /assets/dhole.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/dhole.jpg -------------------------------------------------------------------------------- /assets/dingo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/dingo.jpg -------------------------------------------------------------------------------- /assets/doberman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/doberman.jpg -------------------------------------------------------------------------------- /assets/english_foxhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/english_foxhound.jpg -------------------------------------------------------------------------------- /assets/english_setter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/english_setter.jpg -------------------------------------------------------------------------------- /assets/english_springer_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/english_springer_spaniel.jpg -------------------------------------------------------------------------------- /assets/entlebucher_mountain_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/entlebucher_mountain_dog.jpg -------------------------------------------------------------------------------- /assets/eskimo_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/eskimo_dog.jpg -------------------------------------------------------------------------------- /assets/french_bulldog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/french_bulldog.jpg -------------------------------------------------------------------------------- /assets/german_shepherd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/german_shepherd.jpg -------------------------------------------------------------------------------- /assets/giant_schnauzer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/giant_schnauzer.jpg -------------------------------------------------------------------------------- /assets/golden_retriever.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/golden_retriever.jpg -------------------------------------------------------------------------------- /assets/gordon_setter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/gordon_setter.jpg -------------------------------------------------------------------------------- /assets/great_dane.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/great_dane.jpg -------------------------------------------------------------------------------- /assets/great_pyrenees.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/great_pyrenees.jpg -------------------------------------------------------------------------------- /assets/greater_swiss_mountain_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/greater_swiss_mountain_dog.jpg -------------------------------------------------------------------------------- /assets/groenendael_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/groenendael_dog.jpg -------------------------------------------------------------------------------- /assets/haired_fox_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/haired_fox_terrier.jpg -------------------------------------------------------------------------------- /assets/haired_pointer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/haired_pointer.jpg -------------------------------------------------------------------------------- /assets/ibizan_hound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/ibizan_hound.jpg -------------------------------------------------------------------------------- /assets/irish_setter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/irish_setter.jpg -------------------------------------------------------------------------------- /assets/irish_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/irish_terrier.jpg -------------------------------------------------------------------------------- /assets/irish_water_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/irish_water_spaniel.jpg -------------------------------------------------------------------------------- /assets/irish_wolfhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/irish_wolfhound.jpg -------------------------------------------------------------------------------- /assets/italian_greyhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/italian_greyhound.jpg -------------------------------------------------------------------------------- /assets/japanese_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/japanese_spaniel.jpg -------------------------------------------------------------------------------- /assets/keeshond.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/keeshond.jpg -------------------------------------------------------------------------------- /assets/kelpie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/kelpie.jpg -------------------------------------------------------------------------------- /assets/kerry_blue_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/kerry_blue_terrier.jpg -------------------------------------------------------------------------------- /assets/komondor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/komondor.jpg -------------------------------------------------------------------------------- /assets/kuvasz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/kuvasz.jpg -------------------------------------------------------------------------------- /assets/labrador_retriever.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/labrador_retriever.jpg -------------------------------------------------------------------------------- /assets/lakeland_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/lakeland_terrier.jpg -------------------------------------------------------------------------------- /assets/leonberger.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/leonberger.jpg -------------------------------------------------------------------------------- /assets/lhasa_apso.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/lhasa_apso.jpg -------------------------------------------------------------------------------- /assets/malamute.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/malamute.jpg -------------------------------------------------------------------------------- /assets/malinois_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/malinois_dog.jpg -------------------------------------------------------------------------------- /assets/maltese_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/maltese_dog.jpg -------------------------------------------------------------------------------- /assets/mexican_hairless_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/mexican_hairless_dog.jpg -------------------------------------------------------------------------------- /assets/miniature_pinscher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/miniature_pinscher.jpg -------------------------------------------------------------------------------- /assets/miniature_poodle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/miniature_poodle.jpg -------------------------------------------------------------------------------- /assets/miniature_schnauzer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/miniature_schnauzer.jpg -------------------------------------------------------------------------------- /assets/newfoundland_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/newfoundland_dog.jpg -------------------------------------------------------------------------------- /assets/nodata.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/nodata.jpg -------------------------------------------------------------------------------- /assets/norfolk_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/norfolk_terrier.jpg -------------------------------------------------------------------------------- /assets/norwegian_elkhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/norwegian_elkhound.jpg -------------------------------------------------------------------------------- /assets/norwich_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/norwich_terrier.jpg -------------------------------------------------------------------------------- /assets/old_english_sheepdog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/old_english_sheepdog.jpg -------------------------------------------------------------------------------- /assets/otterhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/otterhound.jpg -------------------------------------------------------------------------------- /assets/papillon_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/papillon_dog.jpg -------------------------------------------------------------------------------- /assets/pekingese.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/pekingese.jpg -------------------------------------------------------------------------------- /assets/pembroke_welsh_corgi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/pembroke_welsh_corgi.jpg -------------------------------------------------------------------------------- /assets/pomeranian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/pomeranian.jpg -------------------------------------------------------------------------------- /assets/pug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/pug.jpg -------------------------------------------------------------------------------- /assets/redbone_coonhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/redbone_coonhound.jpg -------------------------------------------------------------------------------- /assets/rhodesian_ridgeback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/rhodesian_ridgeback.jpg -------------------------------------------------------------------------------- /assets/rottweiler.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/rottweiler.jpg -------------------------------------------------------------------------------- /assets/saint_bernard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/saint_bernard.jpg -------------------------------------------------------------------------------- /assets/saluki.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/saluki.jpg -------------------------------------------------------------------------------- /assets/samoyed_dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/samoyed_dog.jpg -------------------------------------------------------------------------------- /assets/schipperke.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/schipperke.jpg -------------------------------------------------------------------------------- /assets/scotch_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/scotch_terrier.jpg -------------------------------------------------------------------------------- /assets/scottish_deerhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/scottish_deerhound.jpg -------------------------------------------------------------------------------- /assets/sealyham_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/sealyham_terrier.jpg -------------------------------------------------------------------------------- /assets/shetland_sheepdog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/shetland_sheepdog.jpg -------------------------------------------------------------------------------- /assets/shih_tzu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/shih_tzu.jpg -------------------------------------------------------------------------------- /assets/siberian_husky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/siberian_husky.jpg -------------------------------------------------------------------------------- /assets/silky_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/silky_terrier.jpg -------------------------------------------------------------------------------- /assets/staffordshire_bull_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/staffordshire_bull_terrier.jpg -------------------------------------------------------------------------------- /assets/standard_poodle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/standard_poodle.jpg -------------------------------------------------------------------------------- /assets/standard_schnauzer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/standard_schnauzer.jpg -------------------------------------------------------------------------------- /assets/stripped.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/stripped.pb -------------------------------------------------------------------------------- /assets/sussex_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/sussex_spaniel.jpg -------------------------------------------------------------------------------- /assets/tan_coonhound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/tan_coonhound.jpg -------------------------------------------------------------------------------- /assets/tibetan_mastiff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/tibetan_mastiff.jpg -------------------------------------------------------------------------------- /assets/tibetan_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/tibetan_terrier.jpg -------------------------------------------------------------------------------- /assets/toy_poodle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/toy_poodle.jpg -------------------------------------------------------------------------------- /assets/toy_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/toy_terrier.jpg -------------------------------------------------------------------------------- /assets/vizsla.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/vizsla.jpg -------------------------------------------------------------------------------- /assets/walker_hound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/walker_hound.jpg -------------------------------------------------------------------------------- /assets/weimaraner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/weimaraner.jpg -------------------------------------------------------------------------------- /assets/welsh_springer_spaniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/welsh_springer_spaniel.jpg -------------------------------------------------------------------------------- /assets/west_highland_white_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/west_highland_white_terrier.jpg -------------------------------------------------------------------------------- /assets/whippet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/whippet.jpg -------------------------------------------------------------------------------- /assets/yorkshire_terrier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/assets/yorkshire_terrier.jpg -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // set to 'armabi-v7a', 'all', 'arm64-v8a' 2 | // armabi-v7a will only build for armabi-v7a (most smartphones) 3 | // all will build for arm64-v8a, armabi-v7a, x86, x86_64 4 | def buildFor = 'armabi-v7a' 5 | 6 | 7 | project.buildDir = 'gradleBuild' 8 | getProject().setBuildDir('gradleBuild') 9 | 10 | buildscript { 11 | repositories { 12 | google() 13 | jcenter() 14 | } 15 | 16 | dependencies { 17 | classpath 'com.android.tools.build:gradle:4.1.3' 18 | classpath 'org.apache.httpcomponents:httpclient:4.5.6' 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | google() 25 | jcenter() 26 | maven { url "https://jitpack.io" } 27 | } 28 | } 29 | 30 | 31 | project.ext.ASSET_DIR = projectDir.toString() + '/assets' 32 | 33 | apply plugin: 'com.android.application' 34 | 35 | android { 36 | compileSdkVersion 30 37 | buildToolsVersion '30.0.3' 38 | 39 | defaultConfig { 40 | applicationId = 'com.jstappdev.dbclf' 41 | minSdkVersion 21 42 | targetSdkVersion 30 43 | 44 | versionCode 103 45 | versionName "45" 46 | } 47 | 48 | if (buildFor == 'armabi-v7a') { 49 | defaultConfig { 50 | ndk { 51 | abiFilters 'armeabi-v7a' 52 | } 53 | } 54 | } else if (buildFor == 'arm64-v8a') { 55 | defaultConfig { 56 | ndk { 57 | abiFilters 'arm64-v8a' 58 | } 59 | } 60 | } 61 | 62 | sourceSets { 63 | main { 64 | java { 65 | srcDir 'src' 66 | } 67 | 68 | manifest.srcFile 'AndroidManifest.xml' 69 | resources.srcDirs = ['src'] 70 | aidl.srcDirs = ['src'] 71 | renderscript.srcDirs = ['src'] 72 | res.srcDirs = ['res'] 73 | assets.srcDirs = [project.ext.ASSET_DIR] 74 | jniLibs.srcDirs = ['libs'] 75 | } 76 | 77 | debug.setRoot('build-types/debug') 78 | release.setRoot('build-types/release') 79 | } 80 | compileOptions { 81 | targetCompatibility 1.8 82 | sourceCompatibility 1.8 83 | } 84 | } 85 | 86 | 87 | dependencies { 88 | implementation 'org.tensorflow:tensorflow-android:1.8.0' 89 | implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' 90 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 91 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 92 | } 93 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## For more details on how to configure your build environment visit 2 | # http://www.gradle.org/docs/current/userguide/build_environment.html 3 | # 4 | # Specifies the JVM arguments used for the daemon process. 5 | # The setting is particularly useful for tweaking memory settings. 6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 7 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 8 | # 9 | # When configured, Gradle will run in incubating parallel mode. 10 | # This option should only be used with decoupled projects. More details, visit 11 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 12 | # org.gradle.parallel=true 13 | #Thu Sep 26 10:56:51 CEST 2019 14 | android.enableJetifier=true 15 | org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx1024M" 16 | android.useAndroidX=true 17 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Aug 07 13:37:03 CEST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /metadata/ar/summary.txt: -------------------------------------------------------------------------------- 1 | حدد أكثر من مائة سلالة مختلفة من الكلاب باستخدام هاتفك الذكي 2 | -------------------------------------------------------------------------------- /metadata/de/summary.txt: -------------------------------------------------------------------------------- 1 | Über 100 verschiedene Hundebabys mit dem Smartphone bestimmen 2 | -------------------------------------------------------------------------------- /metadata/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 | Identify over one hundred different dog breeds with your smartphone. 2 | 3 | This application will not run on devices with less than 1 GB of RAM. 4 | 5 | If you like this app consider buying the premium version which supports the identification of more than two hundred different dog breeds with much higher accuracy. 6 | 7 | Click the camera button or load an image from the gallery to identify a dog in a single picture. Activate continuous predictions and keep the dog in the circle to get predictions directly from the video stream. The app works best for high quality images loaded from the gallery. 8 | 9 | The application reports up to three predictions with highest confidence. Please treat the output only as a suggestion. 10 | 11 | Based on an extended version of the Stanford Dogs Dataset. 12 | Icons made by Pause08, Smashicons, Freepik from www.flaticon.com. 13 | -------------------------------------------------------------------------------- /metadata/en-US/images/featureGraphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/featureGraphic.png -------------------------------------------------------------------------------- /metadata/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/icon.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/1.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/2.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/3.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/4.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/5.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/6.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/7.png -------------------------------------------------------------------------------- /metadata/en-US/images/phoneScreenshots/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/metadata/en-US/images/phoneScreenshots/8.png -------------------------------------------------------------------------------- /metadata/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | Identify dog breeds with your smartphone. 2 | -------------------------------------------------------------------------------- /metadata/en-US/summary.txt: -------------------------------------------------------------------------------- 1 | Identify over one hundred different dog breeds with your smartphone 2 | -------------------------------------------------------------------------------- /metadata/en-US/title.txt: -------------------------------------------------------------------------------- 1 | Identify Dog Breeds 2 | -------------------------------------------------------------------------------- /metadata/es/summary.txt: -------------------------------------------------------------------------------- 1 | Identificar más de 100 razas de perros diferentes con su teléfono inteligente 2 | -------------------------------------------------------------------------------- /metadata/fr/summary.txt: -------------------------------------------------------------------------------- 1 | Identifiez plus de cent races de chien avec votre téléphone 2 | -------------------------------------------------------------------------------- /metadata/he/summary.txt: -------------------------------------------------------------------------------- 1 | זיהוי מבין מאות זני כלבים בעזרת הטלפון החכם שלך 2 | -------------------------------------------------------------------------------- /metadata/it/summary.txt: -------------------------------------------------------------------------------- 1 | Identifica oltre cento diverse razze di cani con il tuo smartphone 2 | -------------------------------------------------------------------------------- /metadata/nb/summary.txt: -------------------------------------------------------------------------------- 1 | Identifiser over hundre hunderaser med din enhet 2 | -------------------------------------------------------------------------------- /metadata/pl/summary.txt: -------------------------------------------------------------------------------- 1 | Zidentyfikuj ponad sto różnych ras psów za pomocą smartfona 2 | -------------------------------------------------------------------------------- /metadata/pt-BR/summary.txt: -------------------------------------------------------------------------------- 1 | Identifique mais de 100 diferentes raças de cães com seu smartphone 2 | -------------------------------------------------------------------------------- /metadata/pt-PT/summary.txt: -------------------------------------------------------------------------------- 1 | Identifique mais de 100 raças de cães diferentes com seu smartphone 2 | -------------------------------------------------------------------------------- /metadata/pt/summary.txt: -------------------------------------------------------------------------------- 1 | Identifique mais de 100 raças de cães diferentes com seu smartphone 2 | -------------------------------------------------------------------------------- /metadata/ro/summary.txt: -------------------------------------------------------------------------------- 1 | Identificați peste o sută de rase diferite de câini cu ajutorul smartphone-ului 2 | -------------------------------------------------------------------------------- /metadata/ru/summary.txt: -------------------------------------------------------------------------------- 1 | Определите более сотни разных пород собак с помощью своего смартфона 2 | -------------------------------------------------------------------------------- /metadata/tr/summary.txt: -------------------------------------------------------------------------------- 1 | Akıllı telefonunuzla yüzden fazla farklı köpek türünü tanımlayın 2 | -------------------------------------------------------------------------------- /metadata/uk/summary.txt: -------------------------------------------------------------------------------- 1 | Визначте понад сто різних порід псів за допомогою смартфона 2 | -------------------------------------------------------------------------------- /metadata/zh-CN/summary.txt: -------------------------------------------------------------------------------- 1 | 使用智能手机识别超过一百种不同的狗品种 2 | -------------------------------------------------------------------------------- /res/drawable-hdpi/camera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-hdpi/camera_icon.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_action_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-hdpi/ic_action_save.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/camera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-mdpi/camera_icon.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_action_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-mdpi/ic_action_save.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-v21/button_background_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /res/drawable-xhdpi/camera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xhdpi/camera_icon.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_action_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xhdpi/ic_action_save.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/camera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xxhdpi/camera_icon.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_action_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xxhdpi/ic_action_save.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxxhdpi/ic_action_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j05t/dbclf/d6cf06d60a58367b4baefa8732947abe97581b10/res/drawable-xxxhdpi/ic_action_save.png -------------------------------------------------------------------------------- /res/drawable/blackout_transition.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /res/drawable/button_background_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /res/drawable/ic_change_language.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/drawable/roundedbutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 22 | 23 | 32 | 33 | 43 | 44 | 55 | 56 | 67 | 68 | 81 | 82 | 89 | 90 | 97 | 98 | 108 | 109 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /res/layout/activity_list.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/layout/camera_connection_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /res/layout/lang_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /res/layout/list_group.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /res/layout/list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /res/menu/mainmenu.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 11 | 15 | 18 | 21 | -------------------------------------------------------------------------------- /res/values-de/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Erkenne Hunderassen 4 | Erkenne Hunderassen 5 | Dieses Gerät unterstützt die Camera2 API nicht. 6 | Lade Foto.. 7 | Erkenne Hunderassen 9 |

Erkenne über einhundert verschiedene Hunderassen mit deinem Smartphone.

10 |

Klicken Sie auf den Kamera-Button oder laden Sie ein Bild aus der Bildergalerie, um ein einzelnes Bild zu analysieren. Tippen Sie auf die Anzeige, um das angezeigte Ergebnis zu schließen, oder verwenden Sie die Teilen-Schaltfläche, um einen Screenshot zu teilen.

11 |

Aktivieren Sie kontinuierliche Vorhersagen und halten Sie den Hund im Kreis, um Vorhersagen direkt aus dem Videostrom zu erhalten. Die Anwendung meldet die drei Vorhersagen mit der höchsten Wahrscheinlichkeit. Bitte behandeln Sie die Ausgabe nur als Vorschlag.

12 |

Wenn Ihnen diese App gefällt, sollten Sie die Premium Version kaufen, die die Identifizierung von mehr als zweihundert verschiedenen Hunderassen mit viel höherer Genauigkeit erlaubt: https://play.google.com/store/apps/details?id=com.jstappdev.identify_dog_breeds_pro

13 |

Anerkennungen

14 |

Basierend auf einer erweiterten Version des Stanford Dogs Datensatzes. Icons von Pause08, Smashicons, Becris, Freepik von www.flaticon.com.

15 |

Apache License 2.0. Source code verfügbar auf github.com/j05t/dbclf. Bilder von Wikipedia.

16 | ]]>
17 | Über diese App 18 | Beenden 19 | Zu wenig freier Speicher. Versuchen Sie, einige Hintergrundanwendungen zu schließen. 20 | Teile mit.. 21 | Unterstützte Rassen 22 | Suche auf Wikipedia? 23 | Nein 24 | Ja 25 | Keine Erkennung 26 | Sprache ändern 27 | 28 | 29 | Affenpinscher 30 | Afghanischer Windhund 31 | Afrikanischer Wildhund 32 | Airedale Terrier 33 | American Staffordshire Terrier 34 | Appenzeller Sennenhund 35 | Australian Terrier 36 | Basenji 37 | Basset Hound 38 | Beagle 39 | Bedlington Terrier 40 | Berner Sennenhund 41 | Cavalier King Charles Spaniel 42 | Bloodhound 43 | Bluetick Coonhound 44 | Border Collie 45 | Border Terrier 46 | Barsoi 47 | Bouvier des Flandres 48 | Deutscher Boxer 49 | Belgischer Zwerggriffon 50 | Briard 51 | Brittany Spaniel 52 | Bullmastiff 53 | Cairn Terrier 54 | Welsh Corgi Cardigan 55 | Chesapeake Bay Retriever 56 | Chihuahua (Hunderasse) 57 | Chow Chow 58 | Clumber Spaniel 59 | Flat Coated Retriever 60 | Irish Soft Coated Wheaten Terrier 61 | Cocker Spaniel 62 | Langhaarcollie 63 | Curly Coated Retriever 64 | Dandie Dinmont Terrier 65 | Dingo 66 | Dobermann 67 | English Foxhound 68 | English Setter 69 | English Springer Spaniel 70 | Entlebucher Sennenhund 71 | American Eskimo Dog 72 | Französische Bulldogge 73 | Deutscher Schäferhund 74 | Riesenschnauzer 75 | Golden Retriever 76 | Gordon Setter 77 | Grosser Schweizer Sennenhund 78 | Deutsche Dogge 79 | Chien de Montagne des Pyrénées 80 | Groenendael 81 | Foxterrier 82 | Deutsch Kurzhaar 83 | Irish Setter 84 | Irish Terrier 85 | Irish Water Spaniel 86 | Irish Wolfhound 87 | Italienisches Windspiel 88 | Japan Chin 89 | Keeshond 90 | Kelpie 91 | Kerry Blue Terrier 92 | Komondor 93 | Kuvasz 94 | Labrador Retriever 95 | Lakeland Terrier 96 | Leonberger 97 | Lhasa Apso 98 | Dackel 99 | Alaskan Malamute 100 | Malinois 101 | Xoloitzcuintle 102 | Zwergpinscher 103 | Zwergpudel 104 | Zwergschnauzer 105 | Neufundländer 106 | Norfolk Terrier 107 | Norwegischer Elchhund grau 108 | Norwich Terrier 109 | Bobtail 110 | Otterhund 111 | Kontinentaler Zwergspaniel 112 | Pekingese 113 | Welsh Corgi Pembroke 114 | Deutsche Spitze 115 | Mops 116 | Redbone Coonhound 117 | Rhodesian Ridgeback 118 | Rottweiler 119 | Boston Terrier 120 | Rothund 121 | Podenco Ibicenco 122 | Malteser (Hunderasse) 123 | Saint Bernard 124 | Saluki 125 | Samojede 126 | Schipperke 127 | Scotch Terrier 128 | Deerhound 129 | Sealyham Terrier 130 | Shetland Sheepdog 131 | Siberian Husky 132 | Australian Silky Terrier 133 | Staffordshire Bull Terrier 134 | Pudel 135 | Schnauzer 136 | Sussex Spaniel 137 | Black and Tan Coonhound 138 | Do Khyi 139 | Tibet-Terrier 140 | Kleinpudel 141 | English Toy Terrier 142 | Shih Tzu 143 | Vizsla 144 | Treeing Walker Coonhound 145 | Weimaraner 146 | Welsh Springer Spaniel 147 | West Highland White Terrier 148 | Whippet 149 | Yorkshire Terrier 150 | 151 | 152 |
153 | -------------------------------------------------------------------------------- /res/values-fr/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Identify Dog Breeds 4 | Identifiez les races de chiens 5 | Cet appareil ne prend pas en charge l\'API Camera2. 6 | Depuis la Galerie.. 7 | Identify Dog Breeds 9 |

Identifiez plus d\'une centaine de races de chiens différentes avec votre smartphone.

10 |

Cliquez sur le bouton de l\'appareil photo ou chargez une image à partir de la galerie d\'images pour analyser une image. Appuyez sur l\'écran pour fermer le résultat affiché ou utilisez le bouton Partager pour partager une capture d\'écran.

11 |

Activer les prédictions continues et garder le chien dans le cercle pour obtenir le résultat en direct. L\'application indique jusqu\'à trois prédictions jugées les plus correctes. Ce résultat n\'a aucune valeur scientifique.

12 |

Si vous aimez cette application, passez à la version premium qui permet l\'identification de plus de deux cents races de chiens différentes avec une précision plus accrue : https://play.google.com/store/apps/details?id=com.jstappdev.identify_dog_breeds_pro

13 |

Remerciements

14 |

Basé sur une version étendue de la base de données Stanford Dogs. Icônes créées par Pause08, Smashicons, Becris, Freepik de www.flaticon.com. 15 |

Apache License 2.0. Code source disponible à github.com/j05t/dbclf. Images issues de Wikipedia. Traduction française par Clément Thonon.

16 | ]]>
17 | A propos 18 | Quitter 19 | Erreur de mémoire insuffisante. Essayez de fermer quelques applications en arrière-plan. 20 | Partager avec.. 21 | Races identifiables 22 | Regarder sur Wikipedia ? 23 | Non 24 | Oui 25 | Pas de détection 26 | Langue 27 | 28 | 29 | Affenpinscher 30 | Lévrier afghan 31 | Lycaon 32 | Airedale Terrier 33 | American Staffordshire Terrier 34 | Bouvier de l’Appenzell 35 | Terrier australien 36 | Basenji 37 | Basset Hound 38 | Beagle 39 | Bedlington terrier 40 | Bouvier bernois 41 | Cavalier King Charles Spaniel 42 | Chien de Saint-Hubert 43 | Bluetick coonhound 44 | Border Collie 45 | Border Terrier 46 | Barzoï 47 | Bouvier des Flandres 48 | Boxer 49 | Petit brabançon 50 | Berger de Brie 51 | Épagneul breton 52 | Bullmastiff 53 | Cairn terrier 54 | Welsh Corgi Cardigan 55 | Retriever de la baie de Chesapeake 56 | Chihuahua 57 | Chow-chow 58 | Clumber Spaniel 59 | Retriever à poil plat 60 | Terrier irlandais à poil doux 61 | Cocker Spaniel 62 | Colley à poil long 63 | Retriever à poil bouclé 64 | Dandie Dinmont Terrier 65 | Dingo 66 | Dobermann 67 | Foxhound anglais 68 | Setter anglais 69 | Springer anglais 70 | Bouvier de l\'Entlebuch 71 | Esquimau américain 72 | Bouledogue 73 | Berger allemand 74 | Schnauzer géant 75 | Golden retriever 76 | Setter Gordon 77 | Grand bouvier suisse 78 | Dogue allemand 79 | Chien de montagne des Pyrénées 80 | Berger belge Groenendael 81 | Fox-terrier à poil dur 82 | Braque allemand à poil court 83 | Setter irlandais rouge 84 | Terrier irlandais 85 | Épagneul d\'eau irlandais 86 | Irish wolfhound 87 | Petit lévrier italien 88 | Épagneul japonais 89 | Spitz Loup 90 | Australian Kelpie 91 | Terrier Kerry Blue 92 | Komondor 93 | Kuvasz 94 | Labrador retriever 95 | Lakeland Terrier 96 | Leonberg (chien) 97 | Lhassa Apso 98 | Teckel 99 | Malamute de l\'Alaska 100 | Malinois 101 | Xoloitzcuintle 102 | Pinscher nain 103 | Caniche 104 | Schnauzer nain 105 | Terre-neuve 106 | Norfolk Terrier 107 | Chien d\'élan norvégien gris 108 | Norwich Terrier 109 | Bobtail 110 | Chien à loutre 111 | Épagneul nain continental papillon 112 | Pékinois 113 | Welsh Corgi Pembroke 114 | Spitz nain 115 | Carlin 116 | Redbone Coonhound 117 | Rhodesian Ridgeback 118 | Rottweiler 119 | Terrier de Boston 120 | Dhole 121 | Podenco d\'Ibiza 122 | Bichon maltais 123 | Saint-bernard 124 | Lévrier persan 125 | Samoyède 126 | Schipperke 127 | Terrier écossais 128 | Deerhound 129 | Sealyham Terrier 130 | Shetland 131 | Husky de Sibérie 132 | Terrier australien à poil soyeux 133 | Staffordshire Bull Terrier 134 | Caniche 135 | Schnauzer moyen 136 | Sussex Spaniel 137 | Chien noir et feu pour la chasse au raton laveur 138 | Dogue du Tibet 139 | Terrier tibétain 140 | Caniche 141 | Terrier d\'agrément anglais noir et feu 142 | Shih tzu 143 | Braque hongrois à poil court 144 | Treeing Walker Coonhound 145 | Braque de Weimar 146 | Welsh Springer Spaniel 147 | West Highland white terrier 148 | Lévrier whippet 149 | Yorkshire Terrier 150 | 151 | 152 |
153 | -------------------------------------------------------------------------------- /res/values-ka/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ძაღლების ჯიშის ამომცნობი 4 | ძაღლების ჯიშის ამომცნობი 5 | ამ მოწყობილობაში Camera2 API მხარდაჭერილი არაა. 6 | გალერეიდან.. 7 | ძაღლების ჯიშის ამომცნობი 9 |

ამოიცანი ასზე მეტი განსხვავებული ძაღლის ჯიში თქვენი სმარტფონით.

10 |

დააჭირე კამერის ღილაკს ან სურათის ჩატვირთვას სურათების გალერეიდან სურათის ანალიზისთვის. დააჭირეთ დახურვას ან გაზიარების ღილაკს სკრინშოტის გასაზიარებლად.

11 |

განგრძობითი ამოცნობის გააქტიურება. გთხოვთ მოათავსოთ ძაღლი წრეში(ეკრანზე) პირდაპირ ვიდეო ნაკადიდან ამოცნობის მისაღებად. პროგრამა შეგატყობინებთ 3-მდე ამოცნობის ვარიანტს, რომელსაც იგი მიიჩნევს ყველა ზუსტად. გთხოვთ მიღებული შედეგი მიიღოთ მხოლოდ შესაძლო დაშვებად.

12 |

თუ თქვენ მოგეწონათ ეს აპლიკაცია, გთხოვთ შეიძინოთ პრემიუმ ვერსია, სტანდარტულისგან განსხვავებით მასში მხარდაჭერილია 200-ზე მეტი განსხვავებული ძაღლის ჯიში მაღალი სიზუსტით: https://play.google.com/store/apps/details?id=com.jstappdev.identify_dog_breeds_pro

13 |

მადლიერებები

14 |

ეფუძნება Stanford Dogs dataset გაფართოებულ ვერსიას. ხატულების ავტორები: Pause08, Smashicons, Freepik > www.flaticon.com.

15 |

Apache License 2.0. საწყისი კოდი ხელმისაწვდომია github.com/j05t/dbclf. სურათები აღებულია ვიკიპედიიდან.

16 | ]]>
17 | პროგრამის შესახებ 18 | გამოსვლა 19 | მეხსიერება არაა საკმარისი. გთხოვთ დახურეთ რამდენიმე ფონური აპლიკაცია. 20 | გაზიარება შერჩეულთან.. 21 | მხარდაჭერილი ჯიშები 22 | ვიკიპედიაზე ვნახო? 23 | არა 24 | კი 25 | ვერ მოიძებნა 26 | ენის შეცვლა 27 | 28 | 29 | აფენ პინჩერი 30 | ავღანური მწევარი 31 | აფრიკული აფთრისებრი ძაღლი 32 | ერდელტერიერი 33 | ამერიკული სტაფორდშირის ტერიერი 34 | აპენცელერ ზენენჰუნდი 35 | ავსტრალიური ტერიერი 36 | ბასენჯი 37 | ბასეტ ჰაუნდი 38 | ბიგლი 39 | ბედლინგტონ ტერიერი 40 | ბერნული ზენენჰუნდი 41 | ბლენჰეიმ სპანიელი(კავალერი მეფე ჩარლზის სპანიელი) 42 | ბლადჰოუნდი 43 | Bluetick Coonhound 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 | წითელი მგელი(Dhole) 121 | პოდენკო იბისენკო 122 | მალტეზე 123 | სენბერნარი 124 | სალუკი 125 | სამოედური შპიცი 126 | შიპერკე 127 | შოტლანდიური ტერიერი 128 | დირჰაუნდი 129 | სილიჰემ-ტერიერი 130 | შეტლანდიური ნაგაზი 131 | ციმბირული ჰასკი 132 | ავსტრალიური აბრეშუმისებრი ტერიერი 133 | სტაფორდშირული ბულტერიერი 134 | სტანდარტ პუდელი 135 | მიტელშნაუცერი 136 | სუსექსური სპანიელი 137 | კუნჰაუნდი 138 | ტიბეტური მასტიფი 139 | ტიბეტური ტერიერი 140 | სათამაშო პუდელი 141 | ინგლისური სათამაშო პუდელი (Black & Tan) 142 | ში ცუ 143 | უნგრული ვიზლა 144 | Treeing Walker Coonhound 145 | ვეიმარანერი 146 | უელსური სპირნგერ სპანიელი 147 | უესტ-ჰაილენდ-უაიტ-ტერიერი 148 | უიპეტი 149 | იორკშირ-ტერიერი 150 | 151 | 152 |
-------------------------------------------------------------------------------- /res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #1A000000 4 | #000 5 | 6 | -------------------------------------------------------------------------------- /res/values/filenames.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | affenpinscher.jpg 5 | afghan_hound.jpg 6 | african_hunting_dog.jpg 7 | airedale_terrier.jpg 8 | american_staffordshire_terrier.jpg 9 | appenzeller_sennenhund.jpg 10 | australian_terrier.jpg 11 | basenji.jpg 12 | basset_hound.jpg 13 | beagle.jpg 14 | bedlington_terrier.jpg 15 | bernese_mountain_dog.jpg 16 | blenheim_spaniel.jpg 17 | bloodhound.jpg 18 | bluetick_coonhound.jpg 19 | border_collie.jpg 20 | border_terrier.jpg 21 | borzoi.jpg 22 | bouvier_des_flandres.jpg 23 | boxer_dog.jpg 24 | brabancon_griffon.jpg 25 | briard.jpg 26 | brittany_spaniel.jpg 27 | bull_mastiff.jpg 28 | cairn_terrier.jpg 29 | cardigan_welsh_corgi.jpg 30 | chesapeake_bay_retriever.jpg 31 | chihuahua_dog.jpg 32 | chow_chow.jpg 33 | clumber_spaniel.jpg 34 | coated_retriever.jpg 35 | coated_wheaten_terrier.jpg 36 | cocker_spaniel.jpg 37 | collie.jpg 38 | curly_coated_retriever.jpg 39 | dandie_dinmont_terrier.jpg 40 | dingo.jpg 41 | doberman.jpg 42 | english_foxhound.jpg 43 | english_setter.jpg 44 | english_springer_spaniel.jpg 45 | entlebucher_mountain_dog.jpg 46 | eskimo_dog.jpg 47 | french_bulldog.jpg 48 | german_shepherd.jpg 49 | giant_schnauzer.jpg 50 | golden_retriever.jpg 51 | gordon_setter.jpg 52 | greater_swiss_mountain_dog.jpg 53 | great_dane.jpg 54 | great_pyrenees.jpg 55 | groenendael_dog.jpg 56 | haired_fox_terrier.jpg 57 | haired_pointer.jpg 58 | irish_setter.jpg 59 | irish_terrier.jpg 60 | irish_water_spaniel.jpg 61 | irish_wolfhound.jpg 62 | italian_greyhound.jpg 63 | japanese_spaniel.jpg 64 | keeshond.jpg 65 | kelpie.jpg 66 | kerry_blue_terrier.jpg 67 | komondor.jpg 68 | kuvasz.jpg 69 | labrador_retriever.jpg 70 | lakeland_terrier.jpg 71 | leonberger.jpg 72 | lhasa_apso.jpg 73 | dachshund.jpg 74 | malamute.jpg 75 | malinois_dog.jpg 76 | mexican_hairless_dog.jpg 77 | miniature_pinscher.jpg 78 | miniature_poodle.jpg 79 | miniature_schnauzer.jpg 80 | newfoundland_dog.jpg 81 | norfolk_terrier.jpg 82 | norwegian_elkhound.jpg 83 | norwich_terrier.jpg 84 | old_english_sheepdog.jpg 85 | otterhound.jpg 86 | papillon_dog.jpg 87 | pekingese.jpg 88 | pembroke_welsh_corgi.jpg 89 | pomeranian.jpg 90 | pug.jpg 91 | redbone_coonhound.jpg 92 | rhodesian_ridgeback.jpg 93 | rottweiler.jpg 94 | boston_terrier.jpg 95 | dhole.jpg 96 | ibizan_hound.jpg 97 | maltese_dog.jpg 98 | saint_bernard.jpg 99 | saluki.jpg 100 | samoyed_dog.jpg 101 | schipperke.jpg 102 | scotch_terrier.jpg 103 | scottish_deerhound.jpg 104 | sealyham_terrier.jpg 105 | shetland_sheepdog.jpg 106 | siberian_husky.jpg 107 | silky_terrier.jpg 108 | staffordshire_bull_terrier.jpg 109 | standard_poodle.jpg 110 | standard_schnauzer.jpg 111 | sussex_spaniel.jpg 112 | tan_coonhound.jpg 113 | tibetan_mastiff.jpg 114 | tibetan_terrier.jpg 115 | toy_poodle.jpg 116 | toy_terrier.jpg 117 | shih_tzu.jpg 118 | vizsla.jpg 119 | walker_hound.jpg 120 | weimaraner.jpg 121 | welsh_springer_spaniel.jpg 122 | west_highland_white_terrier.jpg 123 | whippet.jpg 124 | yorkshire_terrier.jpg 125 | 126 | 127 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Identify Dog Breeds 4 | Identify Dog Breeds 5 | This device doesn\'t support Camera2 API. 6 | From Gallery.. 7 | Identify Dog Breeds 9 |

Identify over one hundred different dog breeds with your smartphone.

10 |

Click the camera button or load an image from the image gallery to analyze a single picture. Tap the display to close the displayed result, or use the share button to share a screenshot.

11 |

Activate continuous predictions and keep the dog in the circle to get predictions directly from the video stream. The application reports up to three predictions it believes to be the most correct. Please treat the output only as a suggestion.

12 |

If you like this app consider buying the premium version which supports the identification of more than two hundred different dog breeds with much higher accuracy: https://play.google.com/store/apps/details?id=com.jstappdev.identify_dog_breeds_pro

13 |

Acknowledgements

14 |

Based on an extended version of the Stanford Dogs dataset. Icons made by Pause08, Smashicons, Becris, Freepik from www.flaticon.com. 15 |

Apache License 2.0. Source code available at github.com/j05t/dbclf. Pictures from Wikipedia.

16 | ]]>
17 | About 18 | Exit 19 | Out of Memory Error. Try closing a few background applications. 20 | Share with.. 21 | Supported Breeds 22 | Look up on Wikipedia? 23 | No 24 | Yes 25 | No detection 26 | Change Language 27 | 28 | 29 | Affenpinscher 30 | Afghan Hound 31 | African Hunting Dog 32 | Airedale Terrier 33 | American Staffordshire Terrier 34 | Appenzeller Sennenhund 35 | Australian Terrier 36 | Basenji 37 | Basset Hound 38 | Beagle 39 | Bedlington Terrier 40 | Bernese Mountain Dog 41 | Blenheim Spaniel 42 | Bloodhound 43 | Bluetick Coonhound 44 | Border Collie 45 | Border Terrier 46 | Borzoi 47 | Bouvier Des Flandres 48 | Boxer (dog) 49 | Griffon Bruxellois 50 | Briard 51 | Brittany Spaniel 52 | Bullmastiff 53 | Cairn Terrier 54 | Cardigan Welsh Corgi 55 | Chesapeake Bay Retriever 56 | Chihuahua (dog) 57 | Chow Chow 58 | Clumber Spaniel 59 | Flat-coated Retriever 60 | Soft-coated Wheaten Terrier 61 | Cocker Spaniel 62 | Collie 63 | Curly Coated Retriever 64 | Dandie Dinmont Terrier 65 | Dingo 66 | Doberman 67 | English Foxhound 68 | English Setter 69 | English Springer Spaniel 70 | Entlebucher Mountain Dog 71 | Eskimo Dog 72 | French Bulldog 73 | German Shepherd 74 | Giant Schnauzer 75 | Golden Retriever 76 | Gordon Setter 77 | Greater Swiss Mountain Dog 78 | Great Dane 79 | Great Pyrenees 80 | Groenendael dog 81 | Fox Terrier 82 | German Shorthaired Pointer 83 | Irish Setter 84 | Irish Terrier 85 | Irish Water Spaniel 86 | Irish Wolfhound 87 | Italian Greyhound 88 | Japanese Chin 89 | Keeshond 90 | Kelpie 91 | Kerry Blue Terrier 92 | Komondor 93 | Kuvasz 94 | Labrador Retriever 95 | Lakeland Terrier 96 | Leonberger 97 | Lhasa Apso 98 | Dachshund 99 | Alaskan Malamute 100 | Malinois dog 101 | Mexican Hairless Dog 102 | Miniature Pinscher 103 | Miniature Poodle 104 | Miniature Schnauzer 105 | Newfoundland dog 106 | Norfolk Terrier 107 | Norwegian Elkhound 108 | Norwich Terrier 109 | Old English Sheepdog 110 | Otterhound 111 | Papillon dog 112 | Pekingese 113 | Pembroke Welsh Corgi 114 | Pomeranian 115 | Pug 116 | Redbone Coonhound 117 | Rhodesian Ridgeback 118 | Rottweiler 119 | Boston Terrier 120 | Dhole 121 | Ibizan Hound 122 | Maltese dog 123 | Saint Bernard 124 | Saluki 125 | Samoyed dog 126 | Schipperke 127 | Scotch Terrier 128 | Scottish Deerhound 129 | Sealyham Terrier 130 | Shetland Sheepdog 131 | Siberian Husky 132 | Silky Terrier 133 | Staffordshire Bull Terrier 134 | Standard Poodle 135 | Standard Schnauzer 136 | Sussex Spaniel 137 | Black and Tan Coonhound 138 | Tibetan Mastiff 139 | Tibetan Terrier 140 | Toy Poodle 141 | English Toy Terrier (Black & Tan) 142 | Shih Tzu 143 | Vizsla 144 | Treeing Walker Coonhound 145 | Weimaraner 146 | Welsh Springer Spaniel 147 | West Highland White Terrier 148 | Whippet 149 | Yorkshire Terrier 150 | 151 | 152 | 153 | English 154 | Deutsch 155 | Français 156 | ქართული 157 | 158 | 159 | 160 | en 161 | de 162 | fr 163 | ka 164 | 165 | 166 |
167 | -------------------------------------------------------------------------------- /res/xml/filepaths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/AutoFitTextureView.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | /* 4 | * Copyright 2016 The TensorFlow Authors. All Rights Reserved. 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | import android.content.Context; 19 | import android.util.AttributeSet; 20 | import android.view.TextureView; 21 | 22 | /** 23 | * A {@link TextureView} that can be adjusted to a specified aspect ratio. 24 | */ 25 | public class AutoFitTextureView extends TextureView { 26 | private int ratioWidth = 0; 27 | private int ratioHeight = 0; 28 | 29 | public AutoFitTextureView(final Context context) { 30 | this(context, null); 31 | } 32 | 33 | public AutoFitTextureView(final Context context, final AttributeSet attrs) { 34 | this(context, attrs, 0); 35 | } 36 | 37 | public AutoFitTextureView(final Context context, final AttributeSet attrs, final int defStyle) { 38 | super(context, attrs, defStyle); 39 | } 40 | 41 | /** 42 | * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio 43 | * calculated from the parameters. Note that the actual sizes of parameters don't matter, that 44 | * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. 45 | * 46 | * @param width Relative horizontal size 47 | * @param height Relative vertical size 48 | */ 49 | public void setAspectRatio(final int width, final int height) { 50 | if (width < 0 || height < 0) { 51 | throw new IllegalArgumentException("Size cannot be negative."); 52 | } 53 | ratioWidth = width; 54 | ratioHeight = height; 55 | requestLayout(); 56 | } 57 | 58 | @Override 59 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 60 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 61 | final int width = MeasureSpec.getSize(widthMeasureSpec); 62 | final int height = MeasureSpec.getSize(heightMeasureSpec); 63 | if (0 == ratioWidth || 0 == ratioHeight) { 64 | setMeasuredDimension(width, height); 65 | } else { 66 | if (width < height * ratioWidth / ratioHeight) { 67 | setMeasuredDimension(width, width * ratioHeight / ratioWidth); 68 | } else { 69 | setMeasuredDimension(height * ratioWidth / ratioHeight, height); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/CameraConnectionFragment.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | /* 4 | * Copyright 2016 The TensorFlow Authors. All Rights Reserved. 5 | * Modifications copyright (C) 2018 Josef Steppan 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import android.Manifest; 21 | import android.app.Activity; 22 | import android.content.Context; 23 | import android.content.pm.PackageManager; 24 | import android.content.res.Configuration; 25 | import android.graphics.ImageFormat; 26 | import android.graphics.Matrix; 27 | import android.graphics.RectF; 28 | import android.graphics.SurfaceTexture; 29 | import android.hardware.camera2.CameraAccessException; 30 | import android.hardware.camera2.CameraCaptureSession; 31 | import android.hardware.camera2.CameraCharacteristics; 32 | import android.hardware.camera2.CameraDevice; 33 | import android.hardware.camera2.CameraManager; 34 | import android.hardware.camera2.CaptureRequest; 35 | import android.hardware.camera2.CaptureResult; 36 | import android.hardware.camera2.TotalCaptureResult; 37 | import android.hardware.camera2.params.StreamConfigurationMap; 38 | import android.media.ImageReader; 39 | import android.media.ImageReader.OnImageAvailableListener; 40 | import android.os.Bundle; 41 | import android.os.Handler; 42 | import android.os.HandlerThread; 43 | import android.util.Size; 44 | import android.util.SparseIntArray; 45 | import android.view.LayoutInflater; 46 | import android.view.Surface; 47 | import android.view.TextureView; 48 | import android.view.View; 49 | import android.view.ViewGroup; 50 | import android.widget.Toast; 51 | 52 | import androidx.annotation.NonNull; 53 | import androidx.core.app.ActivityCompat; 54 | import androidx.fragment.app.Fragment; 55 | 56 | import java.util.ArrayList; 57 | import java.util.Arrays; 58 | import java.util.Collections; 59 | import java.util.Comparator; 60 | import java.util.List; 61 | import java.util.concurrent.Semaphore; 62 | import java.util.concurrent.TimeUnit; 63 | 64 | public class CameraConnectionFragment extends Fragment { 65 | 66 | /** 67 | * The camera preview size will be chosen to be the smallest frame by pixel size capable of 68 | * containing a DESIRED_SIZE x DESIRED_SIZE square. 69 | */ 70 | private static final int MINIMUM_PREVIEW_SIZE = 299; 71 | 72 | /** 73 | * Conversion from screen rotation to JPEG orientation. 74 | */ 75 | private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 76 | 77 | static { 78 | ORIENTATIONS.append(Surface.ROTATION_0, 90); 79 | ORIENTATIONS.append(Surface.ROTATION_90, 0); 80 | ORIENTATIONS.append(Surface.ROTATION_180, 270); 81 | ORIENTATIONS.append(Surface.ROTATION_270, 180); 82 | } 83 | 84 | /** 85 | * A {@link Semaphore} to prevent the app from exiting before closing the camera. 86 | */ 87 | private final Semaphore cameraOpenCloseLock = new Semaphore(1); 88 | /** 89 | * The input size in pixels desired by TensorFlow (width and height of a square bitmap). 90 | */ 91 | private final Size inputSize; 92 | /** 93 | * The layout identifier to inflate for this Fragment. 94 | */ 95 | private final int layout; 96 | private final CameraCaptureSession.CaptureCallback captureCallback = 97 | new CameraCaptureSession.CaptureCallback() { 98 | @Override 99 | public void onCaptureProgressed( 100 | final CameraCaptureSession session, 101 | final CaptureRequest request, 102 | final CaptureResult partialResult) { 103 | } 104 | 105 | @Override 106 | public void onCaptureCompleted( 107 | final CameraCaptureSession session, 108 | final CaptureRequest request, 109 | final TotalCaptureResult result) { 110 | } 111 | }; 112 | /** 113 | * ID of the current {@link CameraDevice}. 114 | */ 115 | private String cameraId; 116 | /** 117 | * An {@link AutoFitTextureView} for camera preview. 118 | */ 119 | private AutoFitTextureView textureView; 120 | /** 121 | * A {@link CameraCaptureSession } for camera preview. 122 | */ 123 | private CameraCaptureSession captureSession; 124 | /** 125 | * A reference to the opened {@link CameraDevice}. 126 | */ 127 | private CameraDevice cameraDevice; 128 | /** 129 | * The rotation in degrees of the camera sensor from the display. 130 | */ 131 | private Integer sensorOrientation; 132 | /** 133 | * The {@link android.util.Size} of camera preview. 134 | */ 135 | private Size previewSize; 136 | /** 137 | * An additional thread for running tasks that shouldn't block the UI. 138 | */ 139 | private HandlerThread backgroundThread; 140 | /** 141 | * A {@link Handler} for running tasks in the background. 142 | */ 143 | private Handler backgroundHandler; 144 | /** 145 | * An {@link ImageReader} that handles preview frame capture. 146 | */ 147 | private ImageReader previewReader; 148 | /** 149 | * {@link android.hardware.camera2.CaptureRequest.Builder} for the camera preview 150 | */ 151 | private CaptureRequest.Builder previewRequestBuilder; 152 | /** 153 | * {@link CaptureRequest} generated by {@link #previewRequestBuilder} 154 | */ 155 | private CaptureRequest previewRequest; 156 | /** 157 | * A {@link OnImageAvailableListener} to receive frames as they are available. 158 | */ 159 | private OnImageAvailableListener imageListener; 160 | /** 161 | * {@link android.hardware.camera2.CameraDevice.StateCallback} 162 | * is called when {@link CameraDevice} changes its state. 163 | */ 164 | private final CameraDevice.StateCallback stateCallback = 165 | new CameraDevice.StateCallback() { 166 | @Override 167 | public void onOpened(final CameraDevice cd) { 168 | // This method is called when the camera is opened. We start camera preview here. 169 | cameraDevice = cd; 170 | createCameraPreviewSession(); 171 | cameraOpenCloseLock.release(); 172 | } 173 | 174 | @Override 175 | public void onDisconnected(final CameraDevice cd) { 176 | cameraOpenCloseLock.release(); 177 | cd.close(); 178 | cameraDevice = null; 179 | } 180 | 181 | @Override 182 | public void onError(final CameraDevice cd, final int error) { 183 | cameraOpenCloseLock.release(); 184 | cd.close(); 185 | cameraDevice = null; 186 | final Activity activity = getActivity(); 187 | if (null != activity) { 188 | activity.finish(); 189 | } 190 | } 191 | }; 192 | private ConnectionCallback cameraConnectionCallback; 193 | /** 194 | * {@link android.view.TextureView.SurfaceTextureListener} handles several lifecycle events on a 195 | * {@link TextureView}. 196 | */ 197 | private final TextureView.SurfaceTextureListener surfaceTextureListener = 198 | new TextureView.SurfaceTextureListener() { 199 | @Override 200 | public void onSurfaceTextureAvailable( 201 | final SurfaceTexture texture, final int width, final int height) { 202 | openCamera(width, height); 203 | } 204 | 205 | @Override 206 | public void onSurfaceTextureSizeChanged( 207 | final SurfaceTexture texture, final int width, final int height) { 208 | configureTransform(width, height); 209 | } 210 | 211 | @Override 212 | public boolean onSurfaceTextureDestroyed(final SurfaceTexture texture) { 213 | return true; 214 | } 215 | 216 | @Override 217 | public void onSurfaceTextureUpdated(final SurfaceTexture texture) { 218 | } 219 | }; 220 | 221 | public CameraConnectionFragment() { 222 | this.layout = R.layout.camera_connection_fragment; 223 | this.inputSize = new Size(299, 299); 224 | this.cameraId = CameraActivity.cameraId; 225 | } 226 | 227 | /** 228 | * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose 229 | * width and height are at least as large as the minimum of both, or an exact match if possible. 230 | * 231 | * @param choices The list of sizes that the camera supports for the intended output class 232 | * @param width The minimum desired width 233 | * @param height The minimum desired height 234 | * @return The optimal {@code Size}, or an arbitrary one if none were big enough 235 | */ 236 | protected static Size chooseOptimalSize(final Size[] choices, final int width, final int height) { 237 | final int minSize = Math.max(Math.min(width, height), MINIMUM_PREVIEW_SIZE); 238 | final Size desiredSize = new Size(width, height); 239 | 240 | // Collect the supported resolutions that are at least as big as the preview Surface 241 | boolean exactSizeFound = false; 242 | final List bigEnough = new ArrayList(); 243 | 244 | for (final Size option : choices) { 245 | if (option.equals(desiredSize)) { 246 | // Set the size but don't return yet so that remaining sizes will still be logged. 247 | exactSizeFound = true; 248 | } 249 | 250 | if (option.getHeight() >= minSize && option.getWidth() >= minSize) { 251 | bigEnough.add(option); 252 | } 253 | } 254 | 255 | 256 | if (exactSizeFound) { 257 | return desiredSize; 258 | } 259 | 260 | // Pick the smallest of those, assuming we found any 261 | if (bigEnough.size() > 0) { 262 | final Size chosenSize = Collections.min(bigEnough, new CompareSizesByArea()); 263 | return chosenSize; 264 | } else { 265 | return choices[0]; 266 | } 267 | } 268 | 269 | @Override 270 | public void onCreate(Bundle savedInstanceState) { 271 | super.onCreate(savedInstanceState); 272 | 273 | this.cameraConnectionCallback = new ConnectionCallback() { 274 | @Override 275 | public void onPreviewSizeChosen(Size size, int rotation) { 276 | ((CameraActivity) requireContext()).onPreviewSizeChosen(size, rotation); 277 | } 278 | }; 279 | 280 | this.imageListener = (CameraActivity) requireContext(); 281 | } 282 | 283 | /** 284 | * Shows a {@link Toast} on the UI thread. 285 | * 286 | * @param text The message to show 287 | */ 288 | private void showToast(final String text) { 289 | final Activity activity = getActivity(); 290 | if (activity != null) { 291 | activity.runOnUiThread( 292 | () -> Toast.makeText(requireContext().getApplicationContext(), text, Toast.LENGTH_SHORT).show()); 293 | } 294 | } 295 | 296 | @Override 297 | public View onCreateView( 298 | final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { 299 | return inflater.inflate(layout, container, false); 300 | } 301 | 302 | @Override 303 | public void onViewCreated(final View view, final Bundle savedInstanceState) { 304 | textureView = view.findViewById(R.id.texture); 305 | } 306 | 307 | @Override 308 | public void onActivityCreated(final Bundle savedInstanceState) { 309 | super.onActivityCreated(savedInstanceState); 310 | } 311 | 312 | @Override 313 | public void onResume() { 314 | super.onResume(); 315 | startBackgroundThread(); 316 | 317 | // When the screen is turned off and turned back on, the SurfaceTexture is already 318 | // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open 319 | // a camera and start preview from here (otherwise, we wait until the surface is ready in 320 | // the SurfaceTextureListener). 321 | if (textureView.isAvailable()) { 322 | openCamera(textureView.getWidth(), textureView.getHeight()); 323 | } else { 324 | textureView.setSurfaceTextureListener(surfaceTextureListener); 325 | } 326 | } 327 | 328 | @Override 329 | public void onPause() { 330 | closeCamera(); 331 | stopBackgroundThread(); 332 | super.onPause(); 333 | } 334 | 335 | 336 | /** 337 | * Sets up member variables related to camera. 338 | */ 339 | private void setUpCameraOutputs() { 340 | final Activity activity = getActivity(); 341 | final CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); 342 | try { 343 | final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); 344 | 345 | final StreamConfigurationMap map = 346 | characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 347 | 348 | sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 349 | 350 | // Danger, W.R.! Attempting to use too large a preview size could exceed the camera 351 | // bus' bandwidth limitation, resulting in gorgeous previews but the storage of 352 | // garbage capture data. 353 | previewSize = 354 | chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), 355 | inputSize.getWidth(), 356 | inputSize.getHeight()); 357 | 358 | // We fit the aspect ratio of TextureView to the size of preview we picked. 359 | final int orientation = getResources().getConfiguration().orientation; 360 | if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 361 | textureView.setAspectRatio(previewSize.getWidth(), previewSize.getHeight()); 362 | } else { 363 | textureView.setAspectRatio(previewSize.getHeight(), previewSize.getWidth()); 364 | } 365 | } catch (final CameraAccessException ignored) { 366 | } catch (final NullPointerException e) { 367 | // Currently an NPE is thrown when the Camera2API is used but not supported on the 368 | // device this code runs. 369 | throw new RuntimeException(getString(R.string.camera_error)); 370 | } 371 | 372 | cameraConnectionCallback.onPreviewSizeChosen(previewSize, sensorOrientation); 373 | } 374 | 375 | /** 376 | * Opens the camera specified by {@link CameraConnectionFragment#cameraId}. 377 | */ 378 | private void openCamera(final int width, final int height) { 379 | setUpCameraOutputs(); 380 | configureTransform(width, height); 381 | final Activity activity = getActivity(); 382 | final CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); 383 | try { 384 | if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { 385 | throw new RuntimeException("Time out waiting to lock camera opening."); 386 | } 387 | if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 388 | return; 389 | } 390 | manager.openCamera(cameraId, stateCallback, backgroundHandler); 391 | } catch (final CameraAccessException e) { 392 | } catch (final InterruptedException e) { 393 | throw new RuntimeException("Interrupted while trying to lock camera opening.", e); 394 | } 395 | } 396 | 397 | /** 398 | * Closes the current {@link CameraDevice}. 399 | */ 400 | private void closeCamera() { 401 | try { 402 | cameraOpenCloseLock.acquire(); 403 | if (null != captureSession) { 404 | captureSession.close(); 405 | captureSession = null; 406 | } 407 | if (null != cameraDevice) { 408 | cameraDevice.close(); 409 | cameraDevice = null; 410 | } 411 | if (null != previewReader) { 412 | previewReader.close(); 413 | previewReader = null; 414 | } 415 | } catch (final InterruptedException e) { 416 | throw new RuntimeException("Interrupted while trying to lock camera closing.", e); 417 | } finally { 418 | cameraOpenCloseLock.release(); 419 | } 420 | } 421 | 422 | /** 423 | * Starts a background thread and its {@link Handler}. 424 | */ 425 | private void startBackgroundThread() { 426 | backgroundThread = new HandlerThread("ImageListener"); 427 | backgroundThread.start(); 428 | backgroundHandler = new Handler(backgroundThread.getLooper()); 429 | } 430 | 431 | /** 432 | * Stops the background thread and its {@link Handler}. 433 | */ 434 | private void stopBackgroundThread() { 435 | backgroundThread.quitSafely(); 436 | try { 437 | backgroundThread.join(); 438 | backgroundThread.quit(); 439 | backgroundThread = null; 440 | backgroundHandler = null; 441 | } catch (final InterruptedException e) { 442 | } 443 | } 444 | 445 | /** 446 | * Creates a new {@link CameraCaptureSession} for camera preview. 447 | */ 448 | private void createCameraPreviewSession() { 449 | try { 450 | final SurfaceTexture texture = textureView.getSurfaceTexture(); 451 | assert texture != null; 452 | 453 | // We configure the size of default buffer to be the size of camera preview we want. 454 | texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); 455 | 456 | // This is the output Surface we need to start preview. 457 | final Surface surface = new Surface(texture); 458 | 459 | // We set up a CaptureRequest.Builder with the output Surface. 460 | previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 461 | previewRequestBuilder.addTarget(surface); 462 | 463 | // Create the reader for the preview frames. 464 | previewReader = 465 | ImageReader.newInstance( 466 | previewSize.getWidth(), previewSize.getHeight(), ImageFormat.YUV_420_888, 2); 467 | 468 | previewReader.setOnImageAvailableListener(imageListener, backgroundHandler); 469 | previewRequestBuilder.addTarget(previewReader.getSurface()); 470 | 471 | // Here, we create a CameraCaptureSession for camera preview. 472 | cameraDevice.createCaptureSession( 473 | Arrays.asList(surface, previewReader.getSurface()), 474 | new CameraCaptureSession.StateCallback() { 475 | 476 | @Override 477 | public void onConfigured(@NonNull final CameraCaptureSession cameraCaptureSession) { 478 | // The camera is already closed 479 | if (null == cameraDevice) { 480 | return; 481 | } 482 | 483 | // When the session is ready, we start displaying the preview. 484 | captureSession = cameraCaptureSession; 485 | try { 486 | // Auto focus should be continuous for camera preview. 487 | previewRequestBuilder.set( 488 | CaptureRequest.CONTROL_AF_MODE, 489 | CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 490 | // Flash is automatically enabled when necessary. 491 | previewRequestBuilder.set( 492 | CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 493 | 494 | // Finally, we start displaying the camera preview. 495 | previewRequest = previewRequestBuilder.build(); 496 | /* 497 | * @throws IllegalStateException if this session is no longer active, either because the session 498 | * was explicitly closed, a new session has been created 499 | * or the camera device has been closed. 500 | */ 501 | // https://stackoverflow.com/questions/40146485/session-has-been-closed-further-changes-are-illegal 502 | new Handler().postDelayed(new Runnable() { 503 | @Override 504 | public void run() { 505 | try { 506 | if (captureSession != null) 507 | captureSession.setRepeatingRequest(previewRequest, 508 | captureCallback, null); 509 | } catch (CameraAccessException e) { 510 | showToast("Failed to start camera preview because it couldn't access camera"); 511 | } catch (IllegalStateException e) { 512 | showToast("Failed to start camera preview."); 513 | } 514 | } 515 | }, 500); 516 | 517 | } catch (final Exception ignored) { 518 | } 519 | } 520 | 521 | @Override 522 | public void onConfigureFailed(@NonNull final CameraCaptureSession cameraCaptureSession) { 523 | showToast("Failed"); 524 | } 525 | }, 526 | null); 527 | } catch (final CameraAccessException ignored) { 528 | } 529 | } 530 | 531 | /** 532 | * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`. 533 | * This method should be called after the camera preview size is determined in 534 | * setUpCameraOutputs and also the size of `mTextureView` is fixed. 535 | * 536 | * @param viewWidth The width of `mTextureView` 537 | * @param viewHeight The height of `mTextureView` 538 | */ 539 | private void configureTransform(final int viewWidth, final int viewHeight) { 540 | final Activity activity = getActivity(); 541 | if (null == textureView || null == previewSize || null == activity) { 542 | return; 543 | } 544 | final int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 545 | final Matrix matrix = new Matrix(); 546 | final RectF viewRect = new RectF(0, 0, viewWidth, viewHeight); 547 | final RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth()); 548 | final float centerX = viewRect.centerX(); 549 | final float centerY = viewRect.centerY(); 550 | if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { 551 | bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()); 552 | matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL); 553 | final float scale = 554 | Math.max( 555 | (float) viewHeight / previewSize.getHeight(), 556 | (float) viewWidth / previewSize.getWidth()); 557 | matrix.postScale(scale, scale, centerX, centerY); 558 | matrix.postRotate(90 * (rotation - 2), centerX, centerY); 559 | } else if (Surface.ROTATION_180 == rotation) { 560 | matrix.postRotate(180, centerX, centerY); 561 | } 562 | textureView.setTransform(matrix); 563 | } 564 | 565 | /** 566 | * Callback for Activities to use to initialize their data once the 567 | * selected preview size is known. 568 | */ 569 | public interface ConnectionCallback { 570 | void onPreviewSizeChosen(Size size, int cameraRotation); 571 | } 572 | 573 | /** 574 | * Compares two {@code Size}s based on their areas. 575 | */ 576 | static class CompareSizesByArea implements Comparator { 577 | @Override 578 | public int compare(final Size lhs, final Size rhs) { 579 | // We cast here to ensure the multiplications won't overflow 580 | return Long.signum( 581 | (long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight()); 582 | } 583 | } 584 | 585 | } 586 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/Classifier.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 4 | * Modifications copyright (C) 2018 Josef Steppan 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | http://www.apache.org/licenses/LICENSE-2.0 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 | import android.graphics.Bitmap; 18 | import android.graphics.RectF; 19 | 20 | import java.util.List; 21 | import java.util.Locale; 22 | 23 | /** 24 | * Generic interface for interacting with different recognition engines. 25 | */ 26 | public interface Classifier { 27 | List recognizeImage(Bitmap bitmap); 28 | 29 | /** 30 | * An immutable result returned by a Classifier describing what was recognized. 31 | */ 32 | class Recognition { 33 | /** 34 | * A unique identifier for what has been recognized. Specific to the class, not the instance of 35 | * the object. 36 | */ 37 | private final String id; 38 | 39 | /** 40 | * Display name for the recognition. 41 | */ 42 | private final String title; 43 | 44 | /** 45 | * A sortable score for how good the recognition is relative to others. Higher should be better. 46 | */ 47 | private final Float confidence; 48 | 49 | /** 50 | * Optional location within the source image for the location of the recognized object. 51 | */ 52 | private RectF location; 53 | 54 | public Recognition( 55 | final String id, final String title, final Float confidence, final RectF location) { 56 | this.id = id; 57 | this.title = title; 58 | this.confidence = confidence; 59 | this.location = location; 60 | } 61 | 62 | public String getId() { 63 | return id; 64 | } 65 | 66 | public String getTitle() { 67 | return title; 68 | } 69 | 70 | public Float getConfidence() { 71 | return confidence; 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | String resultString = ""; 77 | if (id != null) { 78 | resultString += "[" + id + "] "; 79 | } 80 | 81 | if (title != null) { 82 | resultString += title + " "; 83 | } 84 | 85 | if (confidence != null) { 86 | resultString += String.format(Locale.getDefault(), "(%.1f%%) ", confidence * 100.0f); 87 | } 88 | 89 | if (location != null) { 90 | resultString += location + " "; 91 | } 92 | 93 | return resultString.trim(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/ClassifierActivity.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | /* 4 | * Copyright 2016 The TensorFlow Authors. All Rights Reserved. 5 | * Modifications copyright (C) 2018 Josef Steppan 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import android.content.ContentResolver; 21 | import android.content.Context; 22 | import android.content.Intent; 23 | import android.database.Cursor; 24 | import android.graphics.Bitmap; 25 | import android.graphics.Bitmap.Config; 26 | import android.graphics.Canvas; 27 | import android.graphics.Matrix; 28 | import android.graphics.Paint; 29 | import android.media.ImageReader.OnImageAvailableListener; 30 | import android.net.Uri; 31 | import android.os.AsyncTask; 32 | import android.provider.MediaStore; 33 | import android.util.Size; 34 | import android.view.View; 35 | import android.widget.Toast; 36 | 37 | import com.jstappdev.dbclf.env.ImageUtils; 38 | 39 | import java.io.IOException; 40 | import java.util.List; 41 | 42 | 43 | public class ClassifierActivity extends CameraActivity implements OnImageAvailableListener { 44 | // mobilenet: 224, inception_v3: 299 45 | private static final int INPUT_SIZE = 299; 46 | private static final int IMAGE_MEAN = 128; 47 | private static final float IMAGE_STD = 128; 48 | // mobilenet: input, inception_v3: Mul, Keras: input_1 49 | private static final String INPUT_NAME = "Mul"; 50 | // output, inception(tf): final_result, Keras: output/Softmax 51 | private static final String OUTPUT_NAME = "final_result"; 52 | private static final String MODEL_FILE = "file:///android_asset/stripped.pb"; 53 | private static final boolean MAINTAIN_ASPECT = true; 54 | private Bitmap rgbFrameBitmap = null; 55 | private Bitmap croppedBitmap = null; 56 | private Matrix frameToCropTransform; 57 | 58 | private Classifier classifier; 59 | 60 | @Override 61 | void handleSendImage(Intent data) { 62 | final Uri imageUri = data.getParcelableExtra(Intent.EXTRA_STREAM); 63 | classifyLoadedImage(imageUri); 64 | } 65 | 66 | /** 67 | * user has chosen a picture from the image gallery 68 | */ 69 | @Override 70 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 71 | super.onActivityResult(requestCode, resultCode, data); 72 | 73 | if (resultCode == RESULT_OK && requestCode == PICK_IMAGE) 74 | classifyLoadedImage(data.getData()); 75 | } 76 | 77 | private void classifyLoadedImage(Uri imageUri) { 78 | updateResults(null); 79 | 80 | final int orientation = getOrientation(getApplicationContext(), imageUri); 81 | final ContentResolver contentResolver = this.getContentResolver(); 82 | 83 | try { 84 | final Bitmap croppedFromGallery; 85 | croppedFromGallery = resizeCropAndRotate(MediaStore.Images.Media.getBitmap(contentResolver, imageUri), orientation); 86 | 87 | runOnUiThread(() -> { 88 | setImage(croppedFromGallery); 89 | inferenceTask = new InferenceTask(); 90 | inferenceTask.execute(croppedFromGallery); 91 | }); 92 | } catch (IOException e) { 93 | Toast.makeText(getApplicationContext(), "Unable to load image", Toast.LENGTH_LONG).show(); 94 | } 95 | } 96 | 97 | // get orientation of picture 98 | public int getOrientation(Context context, Uri photoUri) { 99 | /* it's on the external media. */ 100 | try (final Cursor cursor = context.getContentResolver().query(photoUri, 101 | new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null) 102 | ) { 103 | if (cursor.getCount() != 1) { 104 | cursor.close(); 105 | return -1; 106 | } 107 | 108 | if (cursor != null && cursor.moveToFirst()) { 109 | final int r = cursor.getInt(0); 110 | cursor.close(); 111 | return r; 112 | } 113 | 114 | } catch (Exception e) { 115 | return -1; 116 | } 117 | return -1; 118 | } 119 | 120 | private Bitmap resizeCropAndRotate(Bitmap originalImage, int orientation) { 121 | Bitmap result = Bitmap.createBitmap(INPUT_SIZE, INPUT_SIZE, Config.ARGB_8888); 122 | 123 | final float originalWidth = originalImage.getWidth(); 124 | final float originalHeight = originalImage.getHeight(); 125 | 126 | final Canvas canvas = new Canvas(result); 127 | 128 | final float scale = INPUT_SIZE / originalWidth; 129 | 130 | final float xTranslation = 0.0f; 131 | final float yTranslation = (INPUT_SIZE - originalHeight * scale) / 2.0f; 132 | 133 | final Matrix transformation = new Matrix(); 134 | transformation.postTranslate(xTranslation, yTranslation); 135 | transformation.preScale(scale, scale); 136 | 137 | final Paint paint = new Paint(); 138 | paint.setFilterBitmap(true); 139 | 140 | canvas.drawBitmap(originalImage, transformation, paint); 141 | 142 | /* 143 | * if the orientation is not 0 (or -1, which means we don't know), we 144 | * have to do a rotation. 145 | */ 146 | if (orientation > 0) { 147 | final Matrix matrix = new Matrix(); 148 | matrix.postRotate(orientation); 149 | 150 | result = Bitmap.createBitmap(result, 0, 0, INPUT_SIZE, 151 | INPUT_SIZE, matrix, true); 152 | } 153 | 154 | return result; 155 | } 156 | 157 | @Override 158 | public void onPreviewSizeChosen(final Size size, final int rotation) { 159 | previewWidth = size.getWidth(); 160 | previewHeight = size.getHeight(); 161 | 162 | final int sensorOrientation = rotation - getScreenOrientation(); 163 | 164 | rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888); 165 | croppedBitmap = Bitmap.createBitmap(INPUT_SIZE, INPUT_SIZE, Config.ARGB_8888); 166 | 167 | frameToCropTransform = ImageUtils.getTransformationMatrix( 168 | previewWidth, previewHeight, 169 | INPUT_SIZE, INPUT_SIZE, 170 | sensorOrientation, MAINTAIN_ASPECT); 171 | 172 | final Matrix cropToFrameTransform = new Matrix(); 173 | frameToCropTransform.invert(cropToFrameTransform); 174 | } 175 | 176 | protected synchronized void initClassifier() { 177 | if (classifier == null) 178 | try { 179 | classifier = 180 | TensorFlowImageClassifier.create( 181 | getAssets(), 182 | MODEL_FILE, 183 | getResources().getStringArray(R.array.breeds_array), 184 | INPUT_SIZE, 185 | IMAGE_MEAN, 186 | IMAGE_STD, 187 | INPUT_NAME, 188 | OUTPUT_NAME); 189 | } catch (OutOfMemoryError e) { 190 | runOnUiThread(() -> { 191 | cameraButton.setEnabled(true); 192 | continuousInferenceButton.setChecked(false); 193 | Toast.makeText(getApplicationContext(), R.string.error_tf_init, Toast.LENGTH_LONG).show(); 194 | }); 195 | } 196 | } 197 | 198 | @Override 199 | protected void processImage() { 200 | if (!snapShot.get() && !continuousInference && !imageSet) { 201 | readyForNextImage(); 202 | return; 203 | } 204 | 205 | rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, 0, previewWidth, previewHeight); 206 | final Canvas canvas = new Canvas(croppedBitmap); 207 | canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null); 208 | 209 | if (snapShot.compareAndSet(true, false) || continuousInference) { 210 | final Bitmap finalCroppedBitmap = croppedBitmap.copy(croppedBitmap.getConfig(), false); 211 | 212 | runOnUiThread(() -> { 213 | if (!continuousInference && !imageSet) 214 | setImage(finalCroppedBitmap); 215 | 216 | inferenceTask = new InferenceTask(); 217 | inferenceTask.execute(finalCroppedBitmap); 218 | }); 219 | } 220 | } 221 | 222 | protected class InferenceTask extends AsyncTask> { 223 | @Override 224 | protected void onPreExecute() { 225 | if (!continuousInference) 226 | progressBar.setVisibility(View.VISIBLE); 227 | } 228 | 229 | @Override 230 | protected List doInBackground(Bitmap... bitmaps) { 231 | initClassifier(); 232 | 233 | if (!isCancelled() && classifier != null) { 234 | return classifier.recognizeImage(bitmaps[0]); 235 | } 236 | 237 | return null; 238 | } 239 | 240 | @Override 241 | protected void onPostExecute(List recognitions) { 242 | progressBar.setVisibility(View.GONE); 243 | 244 | if (!isCancelled()) 245 | updateResults(recognitions); 246 | 247 | readyForNextImage(); 248 | } 249 | } 250 | 251 | } 252 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/LegacyCameraConnectionFragment.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | /* 4 | * Copyright 2017 The TensorFlow Authors. All Rights Reserved. 5 | * Modifications copyright (C) 2018 Josef Steppan 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import android.graphics.SurfaceTexture; 21 | import android.hardware.Camera; 22 | import android.hardware.Camera.CameraInfo; 23 | import android.os.Bundle; 24 | import android.os.Handler; 25 | import android.os.HandlerThread; 26 | import android.util.Size; 27 | import android.util.SparseIntArray; 28 | import android.view.LayoutInflater; 29 | import android.view.Surface; 30 | import android.view.TextureView; 31 | import android.view.View; 32 | import android.view.ViewGroup; 33 | 34 | import androidx.fragment.app.Fragment; 35 | 36 | import com.jstappdev.dbclf.env.ImageUtils; 37 | 38 | import java.io.IOException; 39 | import java.util.List; 40 | 41 | public class LegacyCameraConnectionFragment extends Fragment { 42 | /** 43 | * Conversion from screen rotation to JPEG orientation. 44 | */ 45 | private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 46 | 47 | static { 48 | ORIENTATIONS.append(Surface.ROTATION_0, 90); 49 | ORIENTATIONS.append(Surface.ROTATION_90, 0); 50 | ORIENTATIONS.append(Surface.ROTATION_180, 270); 51 | ORIENTATIONS.append(Surface.ROTATION_270, 180); 52 | } 53 | 54 | private Camera camera; 55 | private Camera.PreviewCallback imageListener; 56 | private Size desiredSize; 57 | /** 58 | * The layout identifier to inflate for this Fragment. 59 | */ 60 | private int layout; 61 | /** 62 | * An {@link AutoFitTextureView} for camera preview. 63 | */ 64 | private AutoFitTextureView textureView; 65 | /** 66 | * {@link android.view.TextureView.SurfaceTextureListener} handles several lifecycle events on a 67 | * {@link TextureView}. 68 | */ 69 | private final TextureView.SurfaceTextureListener surfaceTextureListener = 70 | new TextureView.SurfaceTextureListener() { 71 | @Override 72 | public void onSurfaceTextureAvailable( 73 | final SurfaceTexture texture, final int width, final int height) { 74 | 75 | int index = getCameraId(); 76 | camera = Camera.open(index); 77 | 78 | try { 79 | Camera.Parameters parameters = camera.getParameters(); 80 | List focusModes = parameters.getSupportedFocusModes(); 81 | if (focusModes != null 82 | && focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 83 | parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 84 | } 85 | List cameraSizes = parameters.getSupportedPreviewSizes(); 86 | Size[] sizes = new Size[cameraSizes.size()]; 87 | int i = 0; 88 | for (Camera.Size size : cameraSizes) { 89 | sizes[i++] = new Size(size.width, size.height); 90 | } 91 | Size previewSize = 92 | CameraConnectionFragment.chooseOptimalSize( 93 | sizes, desiredSize.getWidth(), desiredSize.getHeight()); 94 | parameters.setPreviewSize(previewSize.getWidth(), previewSize.getHeight()); 95 | camera.setDisplayOrientation(90); 96 | camera.setParameters(parameters); 97 | camera.setPreviewTexture(texture); 98 | } catch (IOException exception) { 99 | camera.release(); 100 | } 101 | 102 | camera.setPreviewCallbackWithBuffer(imageListener); 103 | Camera.Size s = camera.getParameters().getPreviewSize(); 104 | camera.addCallbackBuffer(new byte[ImageUtils.getYUVByteSize(s.height, s.width)]); 105 | 106 | textureView.setAspectRatio(s.height, s.width); 107 | 108 | camera.startPreview(); 109 | } 110 | 111 | @Override 112 | public void onSurfaceTextureSizeChanged( 113 | final SurfaceTexture texture, final int width, final int height) { 114 | } 115 | 116 | @Override 117 | public boolean onSurfaceTextureDestroyed(final SurfaceTexture texture) { 118 | return true; 119 | } 120 | 121 | @Override 122 | public void onSurfaceTextureUpdated(final SurfaceTexture texture) { 123 | } 124 | }; 125 | /** 126 | * An additional thread for running tasks that shouldn't block the UI. 127 | */ 128 | private HandlerThread backgroundThread; 129 | 130 | public LegacyCameraConnectionFragment() { 131 | this.layout = R.layout.camera_connection_fragment; 132 | this.desiredSize = new Size(299, 299); 133 | } 134 | 135 | @Override 136 | public void onCreate(Bundle savedInstanceState) { 137 | super.onCreate(savedInstanceState); 138 | this.imageListener = (CameraActivity) requireContext(); 139 | } 140 | 141 | @Override 142 | public View onCreateView( 143 | final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { 144 | return inflater.inflate(layout, container, false); 145 | } 146 | 147 | @Override 148 | public void onViewCreated(final View view, final Bundle savedInstanceState) { 149 | textureView = view.findViewById(R.id.texture); 150 | } 151 | 152 | @Override 153 | public void onActivityCreated(final Bundle savedInstanceState) { 154 | super.onActivityCreated(savedInstanceState); 155 | } 156 | 157 | @Override 158 | public void onResume() { 159 | super.onResume(); 160 | startBackgroundThread(); 161 | // When the screen is turned off and turned back on, the SurfaceTexture is already 162 | // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open 163 | // a camera and start preview from here (otherwise, we wait until the surface is ready in 164 | // the SurfaceTextureListener). 165 | 166 | if (textureView.isAvailable() && camera != null) { 167 | camera.startPreview(); 168 | } else { 169 | textureView.setSurfaceTextureListener(surfaceTextureListener); 170 | } 171 | } 172 | 173 | @Override 174 | public void onPause() { 175 | stopCamera(); 176 | stopBackgroundThread(); 177 | super.onPause(); 178 | } 179 | 180 | /** 181 | * Starts a background thread and its {@link Handler}. 182 | */ 183 | private void startBackgroundThread() { 184 | backgroundThread = new HandlerThread("CameraBackground"); 185 | backgroundThread.start(); 186 | } 187 | 188 | /** 189 | * Stops the background thread and its {@link Handler}. 190 | */ 191 | private void stopBackgroundThread() { 192 | backgroundThread.quitSafely(); 193 | try { 194 | backgroundThread.join(); 195 | backgroundThread = null; 196 | } catch (final InterruptedException ignored) { 197 | } 198 | } 199 | 200 | private void stopCamera() { 201 | if (camera != null) { 202 | camera.stopPreview(); 203 | camera.setPreviewCallback(null); 204 | camera.release(); 205 | camera = null; 206 | } 207 | } 208 | 209 | private int getCameraId() { 210 | CameraInfo ci = new CameraInfo(); 211 | for (int i = 0; i < Camera.getNumberOfCameras(); i++) { 212 | Camera.getCameraInfo(i, ci); 213 | if (ci.facing == CameraInfo.CAMERA_FACING_BACK) 214 | return i; 215 | } 216 | return -1; // No camera found 217 | } 218 | } -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/ListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetManager; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Typeface; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.BaseExpandableListAdapter; 12 | import android.widget.ImageView; 13 | import android.widget.SectionIndexer; 14 | import android.widget.TextView; 15 | 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.text.Collator; 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.HashMap; 22 | import java.util.LinkedHashMap; 23 | import java.util.List; 24 | import java.util.Locale; 25 | 26 | public class ListAdapter extends BaseExpandableListAdapter implements SectionIndexer { 27 | 28 | private Context context; 29 | private List listDataHeader; // header titles 30 | // child data in format of header title, child title 31 | private HashMap listDataChild; 32 | // index for side index list 33 | private HashMap mapIndex; 34 | private String[] sections; 35 | 36 | ListAdapter(Context context, List listDataHeader, 37 | HashMap listChildData) { 38 | this.context = context; 39 | this.listDataHeader = listDataHeader; 40 | this.listDataChild = listChildData; 41 | 42 | // HashMap will prevent duplicates 43 | mapIndex = new LinkedHashMap(); 44 | for (int i = listDataHeader.size() - 1; i >= 0; i--) { 45 | mapIndex.put(listDataHeader.get(i).substring(0, 1).toUpperCase(Locale.getDefault()), i); 46 | } 47 | 48 | // create a list from the set to sort 49 | final ArrayList sectionList = new ArrayList(mapIndex.keySet()); 50 | 51 | final Collator coll = Collator.getInstance(Locale.getDefault()); 52 | coll.setStrength(Collator.PRIMARY); 53 | Collections.sort(sectionList, coll); 54 | 55 | sections = new String[sectionList.size()]; 56 | 57 | sectionList.toArray(sections); 58 | } 59 | 60 | private static Bitmap getBitmapFromAsset(Context context, String filePath) { 61 | final AssetManager assetManager = context.getAssets(); 62 | 63 | InputStream istr; 64 | Bitmap bitmap = null; 65 | try { 66 | istr = assetManager.open(filePath); 67 | bitmap = BitmapFactory.decodeStream(istr); 68 | } catch (IOException e) { 69 | try { 70 | istr = assetManager.open("nodata.jpg"); 71 | bitmap = BitmapFactory.decodeStream(istr); 72 | } catch (IOException ignored) { 73 | } 74 | } 75 | return bitmap; 76 | } 77 | 78 | @Override 79 | public Object getChild(int groupPosition, int childPosititon) { 80 | return this.listDataChild.get(this.listDataHeader.get(groupPosition)); 81 | } 82 | 83 | @Override 84 | public long getChildId(int groupPosition, int childPosition) { 85 | return childPosition; 86 | } 87 | 88 | @Override 89 | public View getChildView(int groupPosition, final int childPosition, 90 | boolean isLastChild, View convertView, ViewGroup parent) { 91 | 92 | final String childText = (String) getChild(groupPosition, childPosition); 93 | 94 | if (convertView == null) { 95 | LayoutInflater infalInflater = (LayoutInflater) this.context 96 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 97 | convertView = infalInflater.inflate(R.layout.list_item, parent, false); 98 | } 99 | 100 | final ImageView imageViewListChild = convertView.findViewById(R.id.breed_image); 101 | 102 | imageViewListChild.setImageBitmap(getBitmapFromAsset(context, childText)); 103 | return convertView; 104 | } 105 | 106 | @Override 107 | public int getChildrenCount(int groupPosition) { 108 | if (this.listDataChild.get(this.listDataHeader.get(groupPosition)) != null) 109 | return 1; 110 | else return 0; 111 | } 112 | 113 | @Override 114 | public Object getGroup(int groupPosition) { 115 | return this.listDataHeader.get(groupPosition); 116 | } 117 | 118 | @Override 119 | public int getGroupCount() { 120 | return this.listDataHeader.size(); 121 | } 122 | 123 | @Override 124 | public long getGroupId(int groupPosition) { 125 | return groupPosition; 126 | } 127 | 128 | @Override 129 | public View getGroupView(int groupPosition, boolean isExpanded, 130 | View convertView, ViewGroup parent) { 131 | 132 | final String headerTitle = (String) getGroup(groupPosition); 133 | if (convertView == null) { 134 | LayoutInflater infalInflater = (LayoutInflater) this.context 135 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 136 | convertView = infalInflater.inflate(R.layout.list_group, parent, false); 137 | } 138 | 139 | final TextView lblListHeader = convertView.findViewById(R.id.lblListHeader); 140 | lblListHeader.setTypeface(null, Typeface.BOLD); 141 | lblListHeader.setText(headerTitle); 142 | 143 | return convertView; 144 | } 145 | 146 | @Override 147 | public boolean hasStableIds() { 148 | return false; 149 | } 150 | 151 | @Override 152 | public boolean isChildSelectable(int groupPosition, int childPosition) { 153 | return true; 154 | } 155 | 156 | public int getPositionForSection(int section) { 157 | //noinspection ConstantConditions 158 | return mapIndex.get(sections[section]); 159 | } 160 | 161 | public int getSectionForPosition(int position) { 162 | return 0; 163 | } 164 | 165 | public Object[] getSections() { 166 | return sections; 167 | } 168 | } -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/RecognitionScoreView.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | import android.content.Context; 4 | import android.graphics.Typeface; 5 | import android.util.AttributeSet; 6 | import android.widget.TextView; 7 | 8 | // custom textview to show recognition results 9 | public class RecognitionScoreView extends TextView { 10 | 11 | public RecognitionScoreView(final Context context, final AttributeSet set) { 12 | super(context, set); 13 | this.setTypeface(Typeface.createFromAsset(context.getAssets(), "OpenSans-Regular.ttf")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/SimpleListActivity.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.net.Uri; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | import android.widget.ExpandableListAdapter; 11 | import android.widget.ExpandableListView; 12 | 13 | import java.text.Collator; 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Locale; 19 | 20 | public class SimpleListActivity extends Activity { 21 | 22 | private static String wikiLangSubDomain = ""; 23 | private ExpandableListView expListView; 24 | private List listDataHeader; 25 | private HashMap listDataChild; 26 | private ArrayList recogs; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | 32 | setContentView(R.layout.activity_list); 33 | 34 | final String lang = CameraActivity.preferredLanguageCode; 35 | if (CameraActivity.supportedLanguageCodes.contains(lang)) { 36 | wikiLangSubDomain = lang + "."; 37 | } 38 | 39 | recogs = getIntent().getStringArrayListExtra("recogs"); 40 | 41 | expListView = findViewById(R.id.lvExp); 42 | 43 | prepareListData(); 44 | 45 | final ExpandableListAdapter listAdapter = new ListAdapter(this, listDataHeader, listDataChild); 46 | 47 | expListView.setOnChildClickListener((parent, v, groupPosition, childPosition, id) -> { 48 | final String title = listDataHeader.get(groupPosition); 49 | final String searchText = title.replace(" ", "+"); 50 | 51 | final DialogInterface.OnClickListener dialogClickListener = (dialog, which) -> { 52 | switch (which) { 53 | case DialogInterface.BUTTON_POSITIVE: 54 | final String url = String.format("https://%swikipedia.org/w/index.php?search=%s&title=Special:Search", wikiLangSubDomain, searchText); 55 | 56 | final Intent i = new Intent(Intent.ACTION_VIEW); 57 | i.setData(Uri.parse(url)); 58 | startActivity(i); 59 | break; 60 | 61 | case DialogInterface.BUTTON_NEGATIVE: 62 | break; 63 | } 64 | }; 65 | 66 | (new AlertDialog.Builder(this)) 67 | .setMessage(R.string.searchFor).setTitle(title) 68 | .setNegativeButton(R.string.no, dialogClickListener) 69 | .setPositiveButton(R.string.yes, dialogClickListener).show(); 70 | 71 | return false; 72 | }); 73 | 74 | expListView.setFastScrollEnabled(true); 75 | expListView.setAdapter(listAdapter); 76 | } 77 | 78 | @Override 79 | public void onResume() { 80 | super.onResume(); 81 | 82 | if (null != recogs) 83 | for (int i = 0; i < listDataHeader.size(); i++) 84 | expListView.expandGroup(i); 85 | } 86 | 87 | /* 88 | * Preparing the list data 89 | */ 90 | private void prepareListData() { 91 | listDataHeader = new ArrayList<>(); 92 | listDataChild = new HashMap<>(); 93 | 94 | Collections.addAll(listDataHeader, getResources().getStringArray(R.array.breeds_array)); 95 | final String[] fileNames = getResources().getStringArray(R.array.file_names); 96 | 97 | // load file names 98 | for (int i = 0; i < listDataHeader.size(); i++) { 99 | listDataChild.put(listDataHeader.get(i), fileNames[i]); 100 | } 101 | 102 | if (null != recogs) { 103 | listDataHeader = new ArrayList<>(); 104 | listDataHeader.addAll(recogs); 105 | expListView.setFastScrollAlwaysVisible(false); 106 | } else { 107 | Locale locale; 108 | 109 | if (CameraActivity.supportedLanguageCodes.contains(CameraActivity.preferredLanguageCode)) { 110 | locale = new Locale(CameraActivity.preferredLanguageCode); 111 | } else { 112 | locale = Locale.getDefault(); 113 | } 114 | 115 | final Collator coll = Collator.getInstance(locale); 116 | coll.setStrength(Collator.PRIMARY); 117 | Collections.sort(listDataHeader, coll); 118 | expListView.setFastScrollAlwaysVisible(true); 119 | } 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/TensorFlowImageClassifier.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf; 2 | 3 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 4 | * Modifications copyright (C) 2018 Josef Steppan 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | http://www.apache.org/licenses/LICENSE-2.0 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 | import android.content.res.AssetManager; 18 | import android.graphics.Bitmap; 19 | 20 | import org.tensorflow.Operation; 21 | import org.tensorflow.contrib.android.TensorFlowInferenceInterface; 22 | 23 | import java.io.IOException; 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.List; 27 | import java.util.PriorityQueue; 28 | import java.util.Vector; 29 | 30 | /** 31 | * A classifier specialized to label images using TensorFlow. 32 | */ 33 | public class TensorFlowImageClassifier implements Classifier { 34 | // Only return this many results with at least this confidence. 35 | private static final int MAX_RESULTS = 3; 36 | private static final float THRESHOLD = 0.1f; 37 | 38 | // Config values. 39 | private String inputName; 40 | private String outputName; 41 | private int inputSize; 42 | private int imageMean; 43 | private float imageStd; 44 | 45 | // Pre-allocated buffers. 46 | private Vector labels = new Vector(); 47 | private int[] intValues; 48 | private float[] floatValues; 49 | private float[] outputs; 50 | private String[] outputNames; 51 | 52 | private boolean logStats = false; 53 | 54 | private TensorFlowInferenceInterface inferenceInterface; 55 | 56 | private TensorFlowImageClassifier() { 57 | } 58 | 59 | /** 60 | * Initializes a native TensorFlow session for classifying images. 61 | * 62 | * @param assetManager The asset manager to be used to load assets. 63 | * @param modelFilename The filepath of the model GraphDef protocol buffer. 64 | * @param labels String array of labels. 65 | * @param inputSize The input size. A square image of inputSize x inputSize is assumed. 66 | * @param imageMean The assumed mean of the image values. 67 | * @param imageStd The assumed std of the image values. 68 | * @param inputName The label of the image input node. 69 | * @param outputName The label of the output node. 70 | * @throws IOException 71 | */ 72 | public static Classifier create( 73 | AssetManager assetManager, 74 | String modelFilename, 75 | String[] labels, 76 | int inputSize, 77 | int imageMean, 78 | float imageStd, 79 | String inputName, 80 | String outputName) { 81 | final TensorFlowImageClassifier c = new TensorFlowImageClassifier(); 82 | c.inputName = inputName; 83 | c.outputName = outputName; 84 | 85 | // Read the label names into memory. 86 | Collections.addAll(c.labels, labels); 87 | 88 | c.inferenceInterface = new TensorFlowInferenceInterface(assetManager, modelFilename); 89 | 90 | // The shape of the output is [N, NUM_CLASSES], where N is the batch size. 91 | final Operation operation = c.inferenceInterface.graphOperation(outputName); 92 | final int numClasses = (int) operation.output(0).shape().size(1); 93 | 94 | // Ideally, inputSize could have been retrieved from the shape of the input operation. Alas, 95 | // the placeholder node for input in the graphdef typically used does not specify a shape, so it 96 | // must be passed in as a parameter. 97 | c.inputSize = inputSize; 98 | c.imageMean = imageMean; 99 | c.imageStd = imageStd; 100 | 101 | // Pre-allocate buffers. 102 | c.outputNames = new String[]{outputName}; 103 | c.intValues = new int[inputSize * inputSize]; 104 | c.floatValues = new float[inputSize * inputSize * 3]; 105 | c.outputs = new float[numClasses]; 106 | 107 | return c; 108 | } 109 | 110 | 111 | @Override 112 | public List recognizeImage(final Bitmap bitmap) { 113 | 114 | // Preprocess the image data from 0-255 int to normalized float based 115 | // on the provided parameters. 116 | bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); 117 | for (int i = 0; i < intValues.length; ++i) { 118 | final int val = intValues[i]; 119 | floatValues[i * 3 + 0] = (((val >> 16) & 0xFF) - imageMean) / imageStd; 120 | floatValues[i * 3 + 1] = (((val >> 8) & 0xFF) - imageMean) / imageStd; 121 | floatValues[i * 3 + 2] = ((val & 0xFF) - imageMean) / imageStd; 122 | } 123 | 124 | // Copy the input data into TensorFlow. 125 | inferenceInterface.feed(inputName, floatValues, 1, inputSize, inputSize, 3); 126 | 127 | // Run the inference call. 128 | inferenceInterface.run(outputNames, logStats); 129 | 130 | // Copy the output Tensor back into the output array. 131 | inferenceInterface.fetch(outputName, outputs); 132 | 133 | // Find the best classifications. 134 | PriorityQueue pq = 135 | new PriorityQueue( 136 | 3, 137 | (lhs, rhs) -> { 138 | // Intentionally reversed to put high confidence at the head of the queue. 139 | return Float.compare(rhs.getConfidence(), lhs.getConfidence()); 140 | }); 141 | 142 | for (int i = 0; i < outputs.length; ++i) { 143 | if (outputs[i] > THRESHOLD) { 144 | pq.add( 145 | new Recognition( 146 | "" + i, labels.size() > i ? labels.get(i) : "unknown", outputs[i], null)); 147 | } 148 | } 149 | final ArrayList recognitions = new ArrayList(); 150 | final int recognitionsSize = Math.min(pq.size(), MAX_RESULTS); 151 | for (int i = 0; i < recognitionsSize; ++i) { 152 | recognitions.add(pq.poll()); 153 | } 154 | return recognitions; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/com/jstappdev/dbclf/env/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package com.jstappdev.dbclf.env; 2 | 3 | /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 4 | * Modifications copyright (C) 2018 Josef Steppan 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | http://www.apache.org/licenses/LICENSE-2.0 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 | import android.graphics.Matrix; 18 | 19 | /** 20 | * Utility class for manipulating images. 21 | **/ 22 | public class ImageUtils { 23 | 24 | // This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their ranges 25 | // are normalized to eight bits. 26 | static final int kMaxChannelValue = 262143; 27 | 28 | private static int YUV2RGB(int y, int u, int v) { 29 | // Adjust and check YUV values 30 | y = (y - 16) < 0 ? 0 : (y - 16); 31 | u -= 128; 32 | v -= 128; 33 | 34 | // This is the floating point equivalent. We do the conversion in integer 35 | // because some Android devices do not have floating point in hardware. 36 | // nR = (int)(1.164 * nY + 2.018 * nU); 37 | // nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU); 38 | // nB = (int)(1.164 * nY + 1.596 * nV); 39 | int y1192 = 1192 * y; 40 | int r = (y1192 + 1634 * v); 41 | int g = (y1192 - 833 * v - 400 * u); 42 | int b = (y1192 + 2066 * u); 43 | 44 | // Clipping RGB values to be inside boundaries [ 0 , kMaxChannelValue ] 45 | r = r > kMaxChannelValue ? kMaxChannelValue : (r < 0 ? 0 : r); 46 | g = g > kMaxChannelValue ? kMaxChannelValue : (g < 0 ? 0 : g); 47 | b = b > kMaxChannelValue ? kMaxChannelValue : (b < 0 ? 0 : b); 48 | 49 | return 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 50 | } 51 | 52 | public static void convertYUV420SPToARGB8888( 53 | byte[] input, 54 | int width, 55 | int height, 56 | int[] output) { 57 | 58 | // Java implementation of YUV420SP to ARGB8888 converting 59 | final int frameSize = width * height; 60 | for (int j = 0, yp = 0; j < height; j++) { 61 | int uvp = frameSize + (j >> 1) * width; 62 | int u = 0; 63 | int v = 0; 64 | 65 | for (int i = 0; i < width; i++, yp++) { 66 | int y = 0xff & input[yp]; 67 | if ((i & 1) == 0) { 68 | v = 0xff & input[uvp++]; 69 | u = 0xff & input[uvp++]; 70 | } 71 | 72 | output[yp] = YUV2RGB(y, u, v); 73 | } 74 | } 75 | } 76 | 77 | public static void convertYUV420ToARGB8888( 78 | byte[] yData, 79 | byte[] uData, 80 | byte[] vData, 81 | int width, 82 | int height, 83 | int yRowStride, 84 | int uvRowStride, 85 | int uvPixelStride, 86 | int[] out) { 87 | 88 | int yp = 0; 89 | for (int j = 0; j < height; j++) { 90 | int pY = yRowStride * j; 91 | int pUV = uvRowStride * (j >> 1); 92 | 93 | for (int i = 0; i < width; i++) { 94 | int uv_offset = pUV + (i >> 1) * uvPixelStride; 95 | 96 | out[yp++] = YUV2RGB( 97 | 0xff & yData[pY + i], 98 | 0xff & uData[uv_offset], 99 | 0xff & vData[uv_offset]); 100 | } 101 | } 102 | } 103 | 104 | /** 105 | * Utility method to compute the allocated size in bytes of a YUV420SP image 106 | * of the given dimensions. 107 | */ 108 | public static int getYUVByteSize(final int width, final int height) { 109 | // The luminance plane requires 1 byte per pixel. 110 | final int ySize = width * height; 111 | 112 | // The UV plane works on 2x2 blocks, so dimensions with odd size must be rounded up. 113 | // Each 2x2 block takes 2 bytes to encode, one each for U and V. 114 | final int uvSize = ((width + 1) / 2) * ((height + 1) / 2) * 2; 115 | 116 | return ySize + uvSize; 117 | } 118 | 119 | /** 120 | * Returns a transformation matrix from one reference frame into another. 121 | * Handles cropping (if maintaining aspect ratio is desired) and rotation. 122 | * 123 | * @param srcWidth Width of source frame. 124 | * @param srcHeight Height of source frame. 125 | * @param dstWidth Width of destination frame. 126 | * @param dstHeight Height of destination frame. 127 | * @param applyRotation Amount of rotation to apply from one frame to another. 128 | * Must be a multiple of 90. 129 | * @param maintainAspectRatio If true, will ensure that scaling in x and y remains constant, 130 | * cropping the image if necessary. 131 | * @return The transformation fulfilling the desired requirements. 132 | */ 133 | public static Matrix getTransformationMatrix( 134 | final int srcWidth, 135 | final int srcHeight, 136 | final int dstWidth, 137 | final int dstHeight, 138 | final int applyRotation, 139 | final boolean maintainAspectRatio) { 140 | final Matrix matrix = new Matrix(); 141 | 142 | if (applyRotation != 0) { 143 | // Translate so center of image is at origin. 144 | matrix.postTranslate(-srcWidth / 2.0f, -srcHeight / 2.0f); 145 | 146 | // Rotate around origin. 147 | matrix.postRotate(applyRotation); 148 | } 149 | 150 | // Account for the already applied rotation, if any, and then determine how 151 | // much scaling is needed for each axis. 152 | final boolean transpose = (Math.abs(applyRotation) + 90) % 180 == 0; 153 | 154 | final int inWidth = transpose ? srcHeight : srcWidth; 155 | final int inHeight = transpose ? srcWidth : srcHeight; 156 | 157 | // Apply scaling if necessary. 158 | if (inWidth != dstWidth || inHeight != dstHeight) { 159 | final float scaleFactorX = dstWidth / (float) inWidth; 160 | final float scaleFactorY = dstHeight / (float) inHeight; 161 | 162 | if (maintainAspectRatio) { 163 | // Scale by minimum factor so that dst is filled completely while 164 | // maintaining the aspect ratio. Some image may fall off the edge. 165 | final float scaleFactor = Math.max(scaleFactorX, scaleFactorY); 166 | matrix.postScale(scaleFactor, scaleFactor); 167 | } else { 168 | // Scale exactly to fill dst from src. 169 | matrix.postScale(scaleFactorX, scaleFactorY); 170 | } 171 | } 172 | 173 | if (applyRotation != 0) { 174 | // Translate back from origin centered reference to destination frame. 175 | matrix.postTranslate(dstWidth / 2.0f, dstHeight / 2.0f); 176 | } 177 | 178 | return matrix; 179 | } 180 | } 181 | --------------------------------------------------------------------------------