├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── FaceDetectAccessControl.gif ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ ├── android-extend.jar │ ├── armeabi-v7a │ │ ├── libArcSoft_FDEngine.so │ │ ├── libArcSoft_FREngine.so │ │ ├── libArcSoft_FTEngine.so │ │ ├── libcache.so │ │ ├── libimage.so │ │ ├── libmpbase.so │ │ ├── librender.so │ │ ├── libserial.so │ │ └── libvideo.so │ ├── armeabi │ │ ├── libArcSoft_FDEngine.so │ │ ├── libArcSoft_FREngine.so │ │ ├── libArcSoft_FTEngine.so │ │ ├── libcache.so │ │ ├── libimage.so │ │ ├── libmpbase.so │ │ ├── librender.so │ │ ├── libserial.so │ │ └── libvideo.so │ ├── facedetection.jar │ ├── facerecognition.jar │ └── facetracking.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── dev │ │ └── brian │ │ └── arcsoftdemo1 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── dev │ │ │ └── brian │ │ │ └── arcsoftdemo1 │ │ │ ├── Application.java │ │ │ ├── DetecterActivity.java │ │ │ ├── FaceDB.java │ │ │ ├── MainActivity.java │ │ │ ├── PermissionActivity.java │ │ │ └── RegisterActivity.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_sync.png │ │ ├── drawable-mdpi │ │ └── ic_sync.png │ │ ├── drawable-xhdpi │ │ ├── ic_sync.png │ │ ├── welcom.jpg │ │ └── welcom1.jpg │ │ ├── drawable-xxhdpi │ │ └── ic_sync.png │ │ ├── layout │ │ ├── activity_camera.xml │ │ ├── activity_register.xml │ │ ├── activity_welcome.xml │ │ ├── dialog_register.xml │ │ └── main_test.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── cloud_sync.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── dev │ └── brian │ └── arcsoftdemo1 │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.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 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | *.jks 45 | 46 | # External native build folder generated in Android Studio 2.2 and later 47 | .externalNativeBuild 48 | 49 | # Google Services (e.g. APIs or Firebase) 50 | google-services.json 51 | 52 | # Freeline 53 | freeline.py 54 | freeline/ 55 | freeline_project_description.json 56 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /FaceDetectAccessControl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/FaceDetectAccessControl.gif -------------------------------------------------------------------------------- /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 | # FaceDetectAccessControl 2 | 虹软智慧校园项目-人脸识别门禁端 3 | 目前已完成:人脸识别,人脸对比,人脸追踪,欢迎界面,特征值存储,小窗口预览 4 | 待完成:等服务器做好后,实现与服务器数据交互 5 | 6 | ![image](https://github.com/wangchenhao006/FaceDetectAccessControl/blob/master/FaceDetectAccessControl.gif) 7 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion "26.0.1" 6 | defaultConfig { 7 | applicationId "dev.brian.arcsoftdemo" 8 | minSdkVersion 15 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | sourceSets{ 22 | main{ 23 | jniLibs.srcDirs=['libs'] 24 | } 25 | } 26 | } 27 | 28 | dependencies { 29 | compile fileTree(include: ['*.jar'], dir: 'libs') 30 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 31 | exclude group: 'com.android.support', module: 'support-annotations' 32 | }) 33 | compile 'com.android.support:appcompat-v7:26.+' 34 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 35 | testCompile 'junit:junit:4.12' 36 | } 37 | -------------------------------------------------------------------------------- /app/libs/android-extend.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/android-extend.jar -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libArcSoft_FDEngine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libArcSoft_FDEngine.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libArcSoft_FREngine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libArcSoft_FREngine.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libArcSoft_FTEngine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libArcSoft_FTEngine.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libcache.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libcache.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libimage.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libimage.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libmpbase.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libmpbase.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/librender.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/librender.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libserial.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libserial.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libvideo.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi-v7a/libvideo.so -------------------------------------------------------------------------------- /app/libs/armeabi/libArcSoft_FDEngine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libArcSoft_FDEngine.so -------------------------------------------------------------------------------- /app/libs/armeabi/libArcSoft_FREngine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libArcSoft_FREngine.so -------------------------------------------------------------------------------- /app/libs/armeabi/libArcSoft_FTEngine.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libArcSoft_FTEngine.so -------------------------------------------------------------------------------- /app/libs/armeabi/libcache.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libcache.so -------------------------------------------------------------------------------- /app/libs/armeabi/libimage.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libimage.so -------------------------------------------------------------------------------- /app/libs/armeabi/libmpbase.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libmpbase.so -------------------------------------------------------------------------------- /app/libs/armeabi/librender.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/librender.so -------------------------------------------------------------------------------- /app/libs/armeabi/libserial.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libserial.so -------------------------------------------------------------------------------- /app/libs/armeabi/libvideo.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/armeabi/libvideo.so -------------------------------------------------------------------------------- /app/libs/facedetection.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/facedetection.jar -------------------------------------------------------------------------------- /app/libs/facerecognition.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/facerecognition.jar -------------------------------------------------------------------------------- /app/libs/facetracking.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/libs/facetracking.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\ProgramFile\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/dev/brian/arcsoftdemo1/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("dev.brian.arcsoftdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/dev/brian/arcsoftdemo1/Application.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Matrix; 6 | import android.media.ExifInterface; 7 | import android.util.Log; 8 | 9 | /** 10 | * 作者: jiayi.zhang 11 | * 时间: 2017/11/8 12 | * 描述: 13 | */ 14 | 15 | public class Application extends android.app.Application { 16 | private final String TAG = this.getClass().toString(); 17 | FaceDB mFaceDB; 18 | 19 | @Override 20 | public void onCreate() { 21 | super.onCreate(); 22 | mFaceDB = new FaceDB(this.getExternalCacheDir().getPath()); 23 | } 24 | 25 | /** 26 | * @param path 27 | * @return 28 | */ 29 | public static Bitmap decodeImage(String path) { 30 | Bitmap res; 31 | try { 32 | ExifInterface exif = new ExifInterface(path); 33 | int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); 34 | 35 | BitmapFactory.Options op = new BitmapFactory.Options(); 36 | op.inSampleSize = 1; 37 | op.inJustDecodeBounds = false; 38 | //op.inMutable = true; 39 | res = BitmapFactory.decodeFile(path, op); 40 | //rotate and scale. 41 | Matrix matrix = new Matrix(); 42 | 43 | if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { 44 | matrix.postRotate(90); 45 | } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { 46 | matrix.postRotate(180); 47 | } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { 48 | matrix.postRotate(270); 49 | } 50 | 51 | Bitmap temp = Bitmap.createBitmap(res, 0, 0, res.getWidth(), res.getHeight(), matrix, true); 52 | Log.d("com.arcsoft", "check target Image:" + temp.getWidth() + "X" + temp.getHeight()); 53 | 54 | if (!temp.equals(res)) { 55 | res.recycle(); 56 | } 57 | return temp; 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/dev/brian/arcsoftdemo1/DetecterActivity.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.res.Configuration; 6 | import android.graphics.Bitmap; 7 | import android.graphics.BitmapFactory; 8 | import android.graphics.Canvas; 9 | import android.graphics.Color; 10 | import android.graphics.ImageFormat; 11 | import android.graphics.Matrix; 12 | import android.graphics.Paint; 13 | import android.graphics.PorterDuff; 14 | import android.graphics.Rect; 15 | import android.graphics.YuvImage; 16 | import android.hardware.Camera; 17 | import android.os.Bundle; 18 | import android.os.Handler; 19 | import android.util.Log; 20 | import android.view.MotionEvent; 21 | import android.view.Surface; 22 | import android.view.SurfaceHolder; 23 | import android.view.View; 24 | import android.widget.ImageView; 25 | import android.widget.TextView; 26 | 27 | import com.arcsoft.facerecognition.AFR_FSDKEngine; 28 | import com.arcsoft.facerecognition.AFR_FSDKError; 29 | import com.arcsoft.facerecognition.AFR_FSDKFace; 30 | import com.arcsoft.facerecognition.AFR_FSDKMatching; 31 | import com.arcsoft.facerecognition.AFR_FSDKVersion; 32 | import com.arcsoft.facetracking.AFT_FSDKEngine; 33 | import com.arcsoft.facetracking.AFT_FSDKError; 34 | import com.arcsoft.facetracking.AFT_FSDKFace; 35 | import com.arcsoft.facetracking.AFT_FSDKVersion; 36 | import com.guo.android_extend.java.AbsLoop; 37 | import com.guo.android_extend.java.ExtByteArrayOutputStream; 38 | import com.guo.android_extend.tools.CameraHelper; 39 | import com.guo.android_extend.widget.CameraFrameData; 40 | import com.guo.android_extend.widget.CameraGLSurfaceView; 41 | import com.guo.android_extend.widget.CameraSurfaceView; 42 | 43 | import java.io.IOException; 44 | import java.util.ArrayList; 45 | import java.util.List; 46 | 47 | import static android.content.ContentValues.TAG; 48 | 49 | /** 50 | * 作者: jiayi.zhang 51 | * 时间: 2017/11/8 52 | * 描述: 53 | */ 54 | 55 | @SuppressWarnings("deprecation") 56 | public class DetecterActivity extends Activity implements CameraSurfaceView.OnCameraListener, View.OnTouchListener, Camera.AutoFocusCallback { 57 | private final String TAG = this.getClass().getSimpleName(); 58 | 59 | private int mWidth, mHeight, mFormat; 60 | private CameraSurfaceView mSurfaceView; 61 | private CameraGLSurfaceView mGLSurfaceView; 62 | 63 | private Camera mCamera; 64 | 65 | AFT_FSDKVersion version = new AFT_FSDKVersion(); 66 | AFT_FSDKEngine engine = new AFT_FSDKEngine(); 67 | List result = new ArrayList<>(); 68 | 69 | byte[] mImageNV21 = null; 70 | FRAbsLoop mFRAbsLoop = null; 71 | AFT_FSDKFace mAFT_FSDKFace = null; 72 | Handler mHandler; 73 | //屏幕方向; 74 | int orientation; 75 | 76 | //一段时间未检测到人脸就将人脸框变淡 77 | Runnable hide = new Runnable() { 78 | @Override 79 | public void run() { 80 | mTextView.setAlpha(0.5f); 81 | mImageView.setImageAlpha(128); 82 | } 83 | }; 84 | 85 | 86 | class FRAbsLoop extends AbsLoop { 87 | 88 | AFR_FSDKVersion version = new AFR_FSDKVersion(); 89 | AFR_FSDKEngine engine = new AFR_FSDKEngine(); 90 | AFR_FSDKFace result = new AFR_FSDKFace(); 91 | //这一步不是很理解 92 | List mResgist = ((Application)DetecterActivity.this.getApplicationContext()).mFaceDB.mRegister; 93 | 94 | @Override 95 | public void setup() { 96 | //人脸识别引擎 97 | AFR_FSDKError error = engine.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key); 98 | Log.d(TAG, "AFR_FSDK_InitialEngine = " + error.getCode()); 99 | error = engine.AFR_FSDK_GetVersion(version); 100 | Log.d(TAG, "FR=" + version.toString() + "," + error.getCode()); //(210, 178 - 478, 446), degree = 1 780, 2208 - 1942, 3370 101 | } 102 | 103 | @Override 104 | public void loop() { 105 | if (mImageNV21 != null) { 106 | AFR_FSDKError error = engine.AFR_FSDK_ExtractFRFeature(mImageNV21, mWidth, mHeight, AFR_FSDKEngine.CP_PAF_NV21, mAFT_FSDKFace.getRect(), mAFT_FSDKFace.getDegree(), result); 107 | Log.d(TAG, "Face=" + result.getFeatureData()[0] + "," + result.getFeatureData()[1] + "," + result.getFeatureData()[2] + "," + error.getCode()); 108 | //匹配度 109 | AFR_FSDKMatching score = new AFR_FSDKMatching(); 110 | // orientation = getApplicationContext().getResources().getConfiguration().orientation; 111 | // Log.d(TAG, "surfaceCreated: -----------------------current orientation = " + orientation); 112 | float max = 0.0f; 113 | String name = null; 114 | for (FaceDB.FaceRegist fr : mResgist) { 115 | for (AFR_FSDKFace face : fr.mFaceList) { 116 | error = engine.AFR_FSDK_FacePairMatching(result, face, score); 117 | Log.d(TAG, "Score:" + score.getScore() + ", AFR_FSDK_FacePairMatching=" + error.getCode()); 118 | if (max < score.getScore()) { 119 | max = score.getScore(); 120 | name = fr.mName; 121 | } 122 | } 123 | } 124 | 125 | //crop 126 | byte[] data = mImageNV21; 127 | YuvImage yuv = new YuvImage(data, ImageFormat.NV21, mWidth, mHeight, null); 128 | ExtByteArrayOutputStream ops = new ExtByteArrayOutputStream(); 129 | //转为jpeg 130 | yuv.compressToJpeg(mAFT_FSDKFace.getRect(), 80, ops); 131 | final Bitmap bmp = BitmapFactory.decodeByteArray(ops.getByteArray(), 0, ops.getByteArray().length); 132 | //因为前置,所以要镜像 133 | final Bitmap modBm = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig()); 134 | Canvas canvas = new Canvas(modBm); 135 | Paint paint = new Paint(); 136 | paint.setColor(Color.BLACK); 137 | paint.setAntiAlias(true); 138 | Matrix matrix = new Matrix(); 139 | //matrix.setRotate(90, bm.getWidth()/2, bm.getHeight()/2); 140 | //matrix.setTranslate(20, 20); 141 | //镜子效果 142 | matrix.setScale(-1, 1); 143 | matrix.postTranslate(bmp.getWidth(), 0); 144 | canvas.drawBitmap(bmp, matrix, paint); 145 | 146 | try { 147 | ops.close(); 148 | } catch (IOException e) { 149 | e.printStackTrace(); 150 | } 151 | 152 | if (max > 0.6f) { 153 | //fr success. 154 | final float max_score = max; 155 | Log.d(TAG, "fit Score:" + max + ", NAME:" + name); 156 | final String mNameShow = name; 157 | mHandler.removeCallbacks(hide); 158 | //传回信息 159 | mHandler.post(new Runnable() { 160 | @Override 161 | public void run() { 162 | 163 | mTextView.setAlpha(1.0f); 164 | mTextView.setText(mNameShow); 165 | mTextView.setTextColor(Color.RED); 166 | mTextView1.setVisibility(View.VISIBLE); 167 | //mTextView1.setText("置信度:" + (float)((int)(max_score * 1000)) / 1000.0); 168 | mTextView1.setText("欢迎回家!"); 169 | mTextView1.setTextColor(Color.RED); 170 | mImageView.setRotation( orientation==1?90:0); 171 | mImageView.setImageAlpha(255); 172 | mImageView.setImageBitmap(modBm); 173 | 174 | 175 | } 176 | }); 177 | } else { 178 | final String mNameShow = "未识别"; 179 | DetecterActivity.this.runOnUiThread(new Runnable() { 180 | @Override 181 | public void run() { 182 | mTextView.setAlpha(1.0f); 183 | mTextView1.setVisibility(View.INVISIBLE); 184 | mTextView.setText(mNameShow); 185 | mTextView.setTextColor(Color.RED); 186 | mImageView.setImageAlpha(255); 187 | mImageView.setRotation( orientation==1?90:0); 188 | mImageView.setImageBitmap(modBm); 189 | } 190 | }); 191 | } 192 | mImageNV21 = null; 193 | } 194 | 195 | } 196 | 197 | @Override 198 | public void over() { 199 | //销毁识别引擎 200 | AFR_FSDKError error = engine.AFR_FSDK_UninitialEngine(); 201 | Log.d(TAG, "AFR_FSDK_UninitialEngine : " + error.getCode()); 202 | } 203 | } 204 | 205 | private TextView mTextView; 206 | private TextView mTextView1; 207 | private ImageView mImageView; 208 | private ImageView mImageSync; 209 | 210 | 211 | /* (non-Javadoc) 212 | * @see android.app.Activity#onCreate(android.os.Bundle) 213 | */ 214 | @Override 215 | protected void onCreate(Bundle savedInstanceState) { 216 | // TODO Auto-generated method stub 217 | super.onCreate(savedInstanceState); 218 | this.setContentView(R.layout.activity_camera); 219 | mImageSync=(ImageView)findViewById(R.id.imageSync); 220 | mImageSync.setImageResource(R.mipmap.cloud_sync); 221 | mImageSync.setOnClickListener(new View.OnClickListener() { 222 | @Override 223 | public void onClick(View v) { 224 | 225 | } 226 | 227 | }); 228 | mGLSurfaceView = (CameraGLSurfaceView) findViewById(R.id.glsurfaceView); 229 | //点击变焦 230 | mGLSurfaceView.setOnTouchListener(this); 231 | mSurfaceView = (CameraSurfaceView) findViewById(R.id.surfaceView); 232 | mSurfaceView.setOnCameraListener(this); 233 | orientation = getApplicationContext().getResources().getConfiguration().orientation; 234 | Log.d(TAG, "surfaceCreated: -----------------------current orientation = " + orientation); 235 | //因为使用前置摄像头,所以使用镜像布局,并调整角度 236 | mSurfaceView.setupGLSurafceView(mGLSurfaceView, true, true, orientation==1?270:0); 237 | mSurfaceView.debug_print_fps(true, false); 238 | 239 | //snap 240 | mTextView = (TextView) findViewById(R.id.textView); 241 | mTextView.setText(""); 242 | mTextView1 = (TextView) findViewById(R.id.textView1); 243 | mTextView1.setText(""); 244 | 245 | mImageView = (ImageView) findViewById(R.id.imageView); 246 | 247 | mHandler = new Handler(); 248 | mWidth = 1280; 249 | mHeight = 960; 250 | mFormat = ImageFormat.NV21; 251 | 252 | //人脸追踪引擎 253 | AFT_FSDKError err = engine.AFT_FSDK_InitialFaceEngine(FaceDB.appid, FaceDB.ft_key, AFT_FSDKEngine.AFT_OPF_0_HIGHER_EXT, 16, 5); 254 | Log.d(TAG, "AFT_FSDK_InitialFaceEngine =" + err.getCode()); 255 | err = engine.AFT_FSDK_GetVersion(version); 256 | Log.d(TAG, "AFT_FSDK_GetVersion:" + version.toString() + "," + err.getCode()); 257 | 258 | mFRAbsLoop = new FRAbsLoop(); 259 | mFRAbsLoop.start(); 260 | } 261 | 262 | /* (non-Javadoc) 263 | * @see android.app.Activity#onDestroy() 264 | */ 265 | @Override 266 | protected void onDestroy() { 267 | // TODO Auto-generated method stub 268 | super.onDestroy(); 269 | mFRAbsLoop.shutdown(); 270 | //销毁人脸追踪引擎 271 | AFT_FSDKError err = engine.AFT_FSDK_UninitialFaceEngine(); 272 | Log.d(TAG, "AFT_FSDK_UninitialFaceEngine =" + err.getCode()); 273 | } 274 | 275 | /** 276 | * setupCamera 在SurfaceView被创建起来的时候,会被触发 277 | * @return 278 | */ 279 | @Override 280 | public Camera setupCamera() { 281 | // TODO 调整预览显示 282 | mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); 283 | 284 | try { 285 | Camera.Parameters parameters = mCamera.getParameters(); 286 | //todo 这里参数有问题,会不能正常设置 287 | // parameters.setPreviewSize(mWidth, mHeight); 288 | // parameters.setPreviewFormat(mFormat); 289 | 290 | for( Camera.Size size : parameters.getSupportedPreviewSizes()) { 291 | Log.d(TAG, "SIZE:" + size.width + "x" + size.height); 292 | } 293 | for( Integer format : parameters.getSupportedPreviewFormats()) { 294 | Log.d(TAG, "FORMAT:" + format); 295 | } 296 | 297 | //显示出你的手机摄像头支持预览的范围 298 | List fps = parameters.getSupportedPreviewFpsRange(); 299 | for(int[] count : fps) { 300 | Log.d(TAG, "T:"); 301 | for (int data : count) { 302 | Log.d(TAG, "V=" + data); 303 | } 304 | } 305 | //parameters.setPreviewFpsRange(15000, 30000); 306 | //parameters.setExposureCompensation(parameters.getMaxExposureCompensation()); 307 | //parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO); 308 | //parameters.setAntibanding(Camera.Parameters.ANTIBANDING_AUTO); 309 | //parmeters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 310 | //parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO); 311 | //parameters.setColorEffect(Camera.Parameters.EFFECT_NONE); 312 | // orientation = getApplicationContext().getResources().getConfiguration().orientation; 313 | // Log.d(TAG, "surfaceCreated: -----------------------current orientation = " + orientation); 314 | 315 | mCamera.setParameters(parameters); 316 | } catch (Exception e) { 317 | e.printStackTrace(); 318 | } 319 | if (mCamera != null) { 320 | mWidth = mCamera.getParameters().getPreviewSize().width; 321 | mHeight = mCamera.getParameters().getPreviewSize().height; 322 | } 323 | return mCamera; 324 | } 325 | 326 | 327 | 328 | /** 329 | * setupChanged 在SurfaceView 有变化时被触发,一般情况这个SurfaceView 只用来获取数据不会触发。 330 | */ 331 | @Override 332 | public void setupChanged(int format, int width, int height) { 333 | 334 | 335 | } 336 | 337 | /** 338 | * startPreviewLater 在需要启动Preview的时机会被调用,返回false则在UI创建完之后立即启动, 339 | * 否则不启动预览,由使用者自己控制启动时机。 340 | * @return 341 | */ 342 | @Override 343 | public boolean startPreviewLater() { 344 | // TODO Auto-generated method stub 345 | return false; 346 | } 347 | 348 | /** 349 | * onPreview 在启动Preview之后会被调用,返回相应的图像数据和时间戳,注意这里的时间戳不是底层驱动的时间戳。 350 | * @param data 351 | * @param width 352 | * @param height 353 | * @param format 354 | * @param timestamp 355 | * @return 356 | */ 357 | @Override 358 | public Object onPreview(byte[] data, int width, int height, int format, long timestamp) { 359 | AFT_FSDKError err = engine.AFT_FSDK_FaceFeatureDetect(data, width, height, AFT_FSDKEngine.CP_PAF_NV21, result); 360 | Log.d(TAG, "AFT_FSDK_FaceFeatureDetect =" + err.getCode()); 361 | Log.d(TAG, "Face=" + result.size()); 362 | for (AFT_FSDKFace face : result) { 363 | Log.d(TAG, "Face:" + face.toString()); 364 | } 365 | if (mImageNV21 == null) { 366 | if (!result.isEmpty()) { 367 | mAFT_FSDKFace = result.get(0).clone(); 368 | mImageNV21 = data.clone(); 369 | } 370 | //如果检测不到人脸,一段时间后自动变淡 371 | else { 372 | mHandler.postDelayed(hide, 3000); 373 | } 374 | } 375 | //copy rects 376 | Rect[] rects = new Rect[result.size()]; 377 | for (int i = 0; i < result.size(); i++) { 378 | rects[i] = new Rect(result.get(i).getRect()); 379 | } 380 | //clear result. 381 | result.clear(); 382 | //return the rects for render. 383 | return rects; 384 | } 385 | 386 | /** 387 | * onBeforeRender 在渲染图像数据传递到 GLRender 之前会触发,这里可以对图像数据再次修改,例如在上面画框之类的操作都可以。 388 | * 、但是实测发现画框应该在after中操作 389 | * @param data 390 | */ 391 | @Override 392 | public void onBeforeRender(CameraFrameData data) { 393 | 394 | } 395 | 396 | /** 397 | * onAfterRender 则在渲染完成之后被触发,这里可以做一些资源释放之类的操作,也可以什么都不做。 398 | * @param data 399 | */ 400 | @Override 401 | public void onAfterRender(CameraFrameData data) { 402 | mGLSurfaceView.getGLES2Render().draw_rect((Rect[])data.getParams(), Color.GREEN, 2); 403 | } 404 | 405 | @Override 406 | public boolean onTouch(View v, MotionEvent event) { 407 | CameraHelper.touchFocus(mCamera, event, v, this); 408 | 409 | return false; 410 | } 411 | 412 | @Override 413 | public void onAutoFocus(boolean success, Camera camera) { 414 | if (success) { 415 | Log.d(TAG, "Camera Focus SUCCESS!"); 416 | } 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /app/src/main/java/dev/brian/arcsoftdemo1/FaceDB.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.util.Log; 4 | 5 | import com.arcsoft.facerecognition.AFR_FSDKEngine; 6 | import com.arcsoft.facerecognition.AFR_FSDKError; 7 | import com.arcsoft.facerecognition.AFR_FSDKFace; 8 | import com.arcsoft.facerecognition.AFR_FSDKVersion; 9 | import com.guo.android_extend.java.ExtInputStream; 10 | import com.guo.android_extend.java.ExtOutputStream; 11 | 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.FileNotFoundException; 15 | import java.io.FileOutputStream; 16 | import java.io.IOException; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * 作者: jiayi.zhang 22 | * 时间: 2017/11/8 23 | * 描述: 24 | */ 25 | 26 | public class FaceDB { 27 | private final String TAG = this.getClass().toString(); 28 | 29 | public static String appid = "GCqwWt65YRwBwhAtPnyCzGnwrtTPeKvDgiFyRWAEBzY6"; 30 | public static String ft_key = "drT1LGJFnqb4MvzAUSuajXqMSyh5kg7SPyWVXePKRcs"; 31 | public static String fd_key = "drT1LGJFnqb4MvzAUSuajXxWrEqR2ccLHMEcHaKf71s"; 32 | public static String fr_key = "drT1LGJFnqb4MvzAUSuajYTATHXAECz7WBpE17bDzY8"; 33 | 34 | 35 | String mDBPath; 36 | List mRegister; 37 | AFR_FSDKEngine mFREngine; 38 | AFR_FSDKVersion mFRVersion; 39 | boolean mUpgrade; 40 | 41 | class FaceRegist { 42 | String mName; 43 | List mFaceList; 44 | 45 | public FaceRegist(String name) { 46 | mName = name; 47 | mFaceList = new ArrayList<>(); 48 | } 49 | } 50 | 51 | public FaceDB(String path) { 52 | mDBPath = path; 53 | mRegister = new ArrayList<>(); 54 | mFRVersion = new AFR_FSDKVersion(); 55 | mUpgrade = false; 56 | mFREngine = new AFR_FSDKEngine(); 57 | AFR_FSDKError error = mFREngine.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key); 58 | if (error.getCode() != AFR_FSDKError.MOK) { 59 | Log.e(TAG, "AFR_FSDK_InitialEngine fail! error code :" + error.getCode()); 60 | } else { 61 | mFREngine.AFR_FSDK_GetVersion(mFRVersion); 62 | Log.d(TAG, "AFR_FSDK_GetVersion=" + mFRVersion.toString()); 63 | } 64 | } 65 | 66 | public void destroy() { 67 | if (mFREngine != null) { 68 | mFREngine.AFR_FSDK_UninitialEngine(); 69 | } 70 | } 71 | 72 | private boolean saveInfo() { 73 | try { 74 | FileOutputStream fs = new FileOutputStream(mDBPath + "/face.txt"); 75 | ExtOutputStream bos = new ExtOutputStream(fs); 76 | bos.writeString(mFRVersion.toString() + "," + mFRVersion.getFeatureLevel()); 77 | bos.close(); 78 | fs.close(); 79 | return true; 80 | } catch (FileNotFoundException e) { 81 | e.printStackTrace(); 82 | } catch (IOException e) { 83 | e.printStackTrace(); 84 | } 85 | return false; 86 | } 87 | 88 | private boolean loadInfo() { 89 | try { 90 | FileInputStream fs = new FileInputStream(mDBPath + "/face.txt"); 91 | ExtInputStream bos = new ExtInputStream(fs); 92 | //load version 93 | String version_saved = bos.readString(); 94 | if (version_saved.equals(mFRVersion.toString() + "," + mFRVersion.getFeatureLevel())) { 95 | mUpgrade = true; 96 | } 97 | //load all regist name. 98 | if (version_saved != null) { 99 | for (String name = bos.readString(); name != null; name = bos.readString()) { 100 | mRegister.add(new FaceRegist(new String(name))); 101 | } 102 | } 103 | bos.close(); 104 | fs.close(); 105 | return true; 106 | } catch (FileNotFoundException e) { 107 | e.printStackTrace(); 108 | } catch (IOException e) { 109 | e.printStackTrace(); 110 | } 111 | return false; 112 | } 113 | 114 | public boolean loadFaces() { 115 | if (loadInfo()) { 116 | try { 117 | for (FaceRegist face : mRegister) { 118 | Log.d(TAG, "load name:" + face.mName + "'s face feature data."); 119 | FileInputStream fs = new FileInputStream(mDBPath + "/" + face.mName + ".data"); 120 | ExtInputStream bos = new ExtInputStream(fs); 121 | AFR_FSDKFace afr = null; 122 | do { 123 | if (afr != null) { 124 | if (mUpgrade) { 125 | //upgrade data. 126 | } 127 | face.mFaceList.add(afr); 128 | } 129 | afr = new AFR_FSDKFace(); 130 | } while (bos.readBytes(afr.getFeatureData())); 131 | bos.close(); 132 | fs.close(); 133 | } 134 | return true; 135 | } catch (FileNotFoundException e) { 136 | e.printStackTrace(); 137 | } catch (IOException e) { 138 | e.printStackTrace(); 139 | } 140 | } else { 141 | if (!saveInfo()) { 142 | Log.e(TAG, "save fail!"); 143 | } 144 | } 145 | return false; 146 | } 147 | 148 | public void addFace(String name, AFR_FSDKFace face) { 149 | try { 150 | //check if already registered. 151 | boolean add = true; 152 | for (FaceRegist frface : mRegister) { 153 | if (frface.mName.equals(name)) { 154 | frface.mFaceList.add(face); 155 | add = false; 156 | break; 157 | } 158 | } 159 | if (add) { // not registered. 160 | FaceRegist frface = new FaceRegist(name); 161 | frface.mFaceList.add(face); 162 | mRegister.add(frface); 163 | } 164 | 165 | if (!new File(mDBPath + "/face.txt").exists()) { 166 | if (!saveInfo()) { 167 | Log.e(TAG, "save fail!"); 168 | } 169 | } 170 | 171 | //save name 172 | FileOutputStream fs = new FileOutputStream(mDBPath + "/face.txt", true); 173 | ExtOutputStream bos = new ExtOutputStream(fs); 174 | bos.writeString(name); 175 | bos.close(); 176 | fs.close(); 177 | 178 | //save feature 179 | fs = new FileOutputStream(mDBPath + "/" + name + ".data", true); 180 | bos = new ExtOutputStream(fs); 181 | bos.writeBytes(face.getFeatureData()); 182 | bos.close(); 183 | fs.close(); 184 | } catch (FileNotFoundException e) { 185 | e.printStackTrace(); 186 | } catch (IOException e) { 187 | e.printStackTrace(); 188 | } 189 | } 190 | public boolean upgrade() { 191 | return false; 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /app/src/main/java/dev/brian/arcsoftdemo1/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.ContentValues; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | import android.content.Intent; 9 | import android.database.Cursor; 10 | import android.graphics.Bitmap; 11 | import android.net.Uri; 12 | import android.os.Build; 13 | import android.provider.DocumentsContract; 14 | import android.provider.MediaStore; 15 | import android.os.Bundle; 16 | import android.util.Log; 17 | import android.view.View; 18 | import android.widget.Toast; 19 | 20 | public class MainActivity extends Activity implements View.OnClickListener,AlertDialog.OnClickListener { 21 | private final String TAG = this.getClass().toString(); 22 | 23 | private static final int REQUEST_CODE_IMAGE_CAMERA = 1; 24 | private static final int REQUEST_CODE_IMAGE_OP = 2; 25 | private static final int REQUEST_CODE_OP = 3; 26 | 27 | private Uri mPath; 28 | 29 | /* (non-Javadoc) 30 | * @see android.app.Activity#onCreate(android.os.Bundle) 31 | */ 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | // TODO Auto-generated method stub 35 | super.onCreate(savedInstanceState); 36 | this.setContentView(R.layout.main_test); 37 | //注册人脸 38 | View v = this.findViewById(R.id.button1); 39 | v.setOnClickListener(this); 40 | //识别人脸 41 | v = this.findViewById(R.id.button2); 42 | v.setOnClickListener(this); 43 | } 44 | 45 | /* (non-Javadoc) 46 | * @see android.app.Activity#onDestroy() 47 | */ 48 | @Override 49 | protected void onDestroy() { 50 | // TODO Auto-generated method stub 51 | super.onDestroy(); 52 | } 53 | 54 | /** 55 | * 当子模块的事情做完之后就回到主界面,或许还同时返回一些子模块完成的数据交给主Activity处理 56 | * @param requestCode 57 | * @param resultCode 58 | * @param data 59 | */ 60 | @Override 61 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 62 | super.onActivityResult(requestCode, resultCode, data); 63 | 64 | //打开图片,检测图片人脸信息 65 | if (requestCode == REQUEST_CODE_IMAGE_OP && resultCode == RESULT_OK) { 66 | Log.i(TAG, "onActivityResult 1"); 67 | mPath = data.getData(); 68 | String file = getPath(mPath); 69 | Bitmap bmp = Application.decodeImage(file); 70 | if (bmp == null || bmp.getWidth() <= 0 || bmp.getHeight() <= 0 ) { 71 | Log.e(TAG, "error"); 72 | } else { 73 | Log.i(TAG, "bmp [" + bmp.getWidth() + "," + bmp.getHeight()); 74 | } 75 | startOilPainting(bmp, file); 76 | } 77 | //获取照片后,人脸注册步骤 78 | else if (requestCode == REQUEST_CODE_OP) { 79 | Log.i(TAG, "onActivityResult 2"); 80 | Log.i(TAG, "RESULT =" + resultCode); 81 | if (data == null) { 82 | return; 83 | } 84 | Bundle bundle = data.getExtras(); 85 | String path = bundle.getString("imagePath"); 86 | Log.i(TAG, "path="+path); 87 | } 88 | //唤起照相机拍摄照片 89 | else if (requestCode == REQUEST_CODE_IMAGE_CAMERA && resultCode == RESULT_OK) { 90 | Log.i(TAG, "onActivityResult 3"); 91 | String file = getPath(mPath); 92 | Bitmap bmp = Application.decodeImage(file); 93 | startOilPainting(bmp, file); 94 | } 95 | } 96 | 97 | @Override 98 | public void onClick(View paramView) { 99 | 100 | switch (paramView.getId()) { 101 | case R.id.button2: 102 | if( ((Application)getApplicationContext()).mFaceDB.mRegister.isEmpty() ) { 103 | Toast.makeText(this, "没有注册人脸,请先注册!", Toast.LENGTH_SHORT).show(); 104 | } else { 105 | //跳转检测界面 106 | Intent it = new Intent(MainActivity.this, DetecterActivity.class); 107 | startActivityForResult(it, REQUEST_CODE_OP); 108 | } 109 | break; 110 | case R.id.button1: 111 | new AlertDialog.Builder(this) 112 | .setTitle("请选择注册方式") 113 | .setIcon(android.R.drawable.ic_dialog_info) 114 | .setItems(new String[]{"打开图片", "拍摄照片"}, this) 115 | .show(); 116 | break; 117 | default:; 118 | } 119 | } 120 | 121 | /** 122 | * @param uri 123 | * @return 124 | */ 125 | private String getPath(Uri uri) { 126 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 127 | if (DocumentsContract.isDocumentUri(this, uri)) { 128 | final String docId = DocumentsContract.getDocumentId(uri); 129 | final String[] split = docId.split(":"); 130 | final String type = split[0]; 131 | 132 | Uri contentUri = null; 133 | if ("image".equals(type)) { 134 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 135 | } else if ("video".equals(type)) { 136 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 137 | return null; 138 | } else if ("audio".equals(type)) { 139 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 140 | return null; 141 | } 142 | 143 | final String selection = "_id=?"; 144 | final String[] selectionArgs = new String[] { 145 | split[1] 146 | }; 147 | 148 | return getDataColumn(this, contentUri, selection, selectionArgs); 149 | } 150 | } 151 | String[] proj = { MediaStore.Images.Media.DATA }; 152 | Cursor actualimagecursor = managedQuery(uri, proj,null,null,null); 153 | int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 154 | actualimagecursor.moveToFirst(); 155 | String img_path = actualimagecursor.getString(actual_image_column_index); 156 | String end = img_path.substring(img_path.length() - 4); 157 | if (0 != end.compareToIgnoreCase(".jpg") && 0 != end.compareToIgnoreCase(".png")) { 158 | return null; 159 | } 160 | return img_path; 161 | } 162 | 163 | /** 164 | * Get the value of the data column for this Uri. This is useful for 165 | * MediaStore Uris, and other file-based ContentProviders. 166 | * 167 | * @param context The context. 168 | * @param uri The Uri to query. 169 | * @param selection (Optional) Filter used in the query. 170 | * @param selectionArgs (Optional) Selection arguments used in the query. 171 | * @return The value of the _data column, which is typically a file path. 172 | */ 173 | public static String getDataColumn(Context context, Uri uri, String selection, 174 | String[] selectionArgs) { 175 | 176 | Cursor cursor = null; 177 | final String column = "_data"; 178 | final String[] projection = { 179 | column 180 | }; 181 | 182 | try { 183 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, 184 | null); 185 | if (cursor != null && cursor.moveToFirst()) { 186 | final int index = cursor.getColumnIndexOrThrow(column); 187 | return cursor.getString(index); 188 | } 189 | } finally { 190 | if (cursor != null) 191 | cursor.close(); 192 | } 193 | return null; 194 | } 195 | 196 | /** 197 | * 传入imagepath 路径,跳转注册逻辑 198 | * @param mBitmap 199 | */ 200 | private void startOilPainting(Bitmap mBitmap, String file) { 201 | Intent it = new Intent(MainActivity.this, RegisterActivity.class); 202 | //todo learn bundle 203 | Bundle bundle = new Bundle(); 204 | bundle.putString("imagePath", file); 205 | it.putExtras(bundle); 206 | startActivityForResult(it, REQUEST_CODE_OP); 207 | } 208 | 209 | @Override 210 | public void onClick(DialogInterface dialog, int which) { 211 | switch (which){ 212 | case 1: 213 | Intent getImageByCamera = new Intent( 214 | "android.media.action.IMAGE_CAPTURE"); 215 | ContentValues values = new ContentValues(1); 216 | 217 | values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); 218 | mPath = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 219 | getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, mPath); 220 | 221 | startActivityForResult(getImageByCamera, REQUEST_CODE_IMAGE_CAMERA); 222 | break; 223 | case 0: 224 | Intent getImageByalbum = new Intent(Intent.ACTION_GET_CONTENT); 225 | getImageByalbum.addCategory(Intent.CATEGORY_OPENABLE); 226 | getImageByalbum.setType("image/jpeg"); 227 | startActivityForResult(getImageByalbum, REQUEST_CODE_IMAGE_OP); 228 | break; 229 | default:; 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /app/src/main/java/dev/brian/arcsoftdemo1/PermissionActivity.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.app.ProgressDialog; 6 | import android.content.Intent; 7 | import android.content.pm.PackageManager; 8 | import android.os.Bundle; 9 | import android.os.Handler; 10 | import android.os.Process; 11 | import android.widget.Toast; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * 作者: jiayi.zhang 18 | * 时间: 2017/11/8 19 | * 描述: 20 | */ 21 | 22 | public class PermissionActivity extends Activity { 23 | public static int PERMISSION_REQ = 0x123456; 24 | 25 | private String[] mPermission = new String[]{ 26 | Manifest.permission.INTERNET, 27 | Manifest.permission.CAMERA, 28 | Manifest.permission.WRITE_EXTERNAL_STORAGE 29 | }; 30 | 31 | private List mRequestPermission = new ArrayList(); 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { 37 | for (String one : mPermission) { 38 | if (PackageManager.PERMISSION_GRANTED != this.checkPermission(one, Process.myPid(), Process.myUid())) { 39 | mRequestPermission.add(one); 40 | } 41 | } 42 | if (!mRequestPermission.isEmpty()) { 43 | this.requestPermissions(mRequestPermission.toArray(new String[mRequestPermission.size()]), PERMISSION_REQ); 44 | return; 45 | } 46 | } 47 | startActiviy(); 48 | } 49 | 50 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 51 | // 版本兼容 52 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) { 53 | return; 54 | } 55 | if (requestCode == PERMISSION_REQ) { 56 | for (int i = 0; i < grantResults.length; i++) { 57 | for (String one : mPermission) { 58 | if (permissions[i].equals(one) && grantResults[i] == PackageManager.PERMISSION_GRANTED) { 59 | mRequestPermission.remove(one); 60 | } 61 | } 62 | } 63 | startActiviy(); 64 | } 65 | } 66 | 67 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 68 | if (requestCode == PERMISSION_REQ) { 69 | if (resultCode == 0) { 70 | this.finish(); 71 | } 72 | } 73 | } 74 | 75 | public void startActiviy() { 76 | if (mRequestPermission.isEmpty()) { 77 | final ProgressDialog mProgressDialog = new ProgressDialog(this); 78 | mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 79 | mProgressDialog.setTitle("loading register data..."); 80 | mProgressDialog.setCancelable(false); 81 | 82 | // mProgressDialog.show(); 83 | //加载启动图片 84 | setContentView(R.layout.activity_welcome); 85 | //后台处理耗时任务 86 | Integer time = 2000; //设置等待时间,单位为毫秒 87 | Handler handler = new Handler(); 88 | //当计时结束时,跳转至主界面 89 | handler.postDelayed(new Runnable() { 90 | @Override 91 | public void run() { 92 | Application app = (Application) PermissionActivity.this.getApplicationContext(); 93 | app.mFaceDB.loadFaces(); 94 | PermissionActivity.this.runOnUiThread(new Runnable() { 95 | @Override 96 | public void run() { 97 | //mProgressDialog.cancel(); 98 | //跳转主界面 99 | Intent intent = new Intent(PermissionActivity.this, DetecterActivity.class); 100 | startActivityForResult(intent, PERMISSION_REQ); 101 | } 102 | }); 103 | } 104 | }, time); 105 | 106 | // new Thread(new Runnable() { 107 | // @Override 108 | // public void run() { 109 | // Application app = (Application) PermissionActivity.this.getApplicationContext(); 110 | // app.mFaceDB.loadFaces(); 111 | // PermissionActivity.this.runOnUiThread(new Runnable() { 112 | // @Override 113 | // public void run() { 114 | // mProgressDialog.cancel(); 115 | // //跳转主界面 116 | // Intent intent = new Intent(PermissionActivity.this, DetecterActivity.class); 117 | // startActivityForResult(intent, PERMISSION_REQ); 118 | // } 119 | // }); 120 | // } 121 | // }).start(); 122 | } else { 123 | Toast.makeText(this, "PERMISSION DENIED!", Toast.LENGTH_LONG).show(); 124 | new Handler().postDelayed(new Runnable() { 125 | @Override 126 | public void run() { 127 | PermissionActivity.this.finish(); 128 | } 129 | }, 3000); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/dev/brian/arcsoftdemo1/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package dev.brian.arcsoftdemo1; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.graphics.Bitmap; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.Paint; 10 | import android.graphics.Rect; 11 | import android.os.Bundle; 12 | import android.os.Message; 13 | import android.text.InputFilter; 14 | import android.util.Log; 15 | import android.view.LayoutInflater; 16 | import android.view.SurfaceHolder; 17 | import android.view.SurfaceView; 18 | import android.view.View; 19 | import android.widget.EditText; 20 | import android.widget.Toast; 21 | 22 | import com.arcsoft.facedetection.AFD_FSDKEngine; 23 | import com.arcsoft.facedetection.AFD_FSDKError; 24 | import com.arcsoft.facedetection.AFD_FSDKFace; 25 | import com.arcsoft.facedetection.AFD_FSDKVersion; 26 | import com.arcsoft.facerecognition.AFR_FSDKEngine; 27 | import com.arcsoft.facerecognition.AFR_FSDKError; 28 | import com.arcsoft.facerecognition.AFR_FSDKFace; 29 | import com.arcsoft.facerecognition.AFR_FSDKVersion; 30 | import com.guo.android_extend.image.ImageConverter; 31 | import com.guo.android_extend.widget.ExtImageView; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | /** 37 | * 作者: jiayi.zhang 38 | * 时间: 2017/11/8 39 | * 描述: 40 | */ 41 | 42 | public class RegisterActivity extends Activity implements SurfaceHolder.Callback, DialogInterface.OnClickListener { 43 | private final String TAG = this.getClass().toString(); 44 | private final static int MSG_CODE = 0x1000; 45 | private final static int MSG_EVENT_REG = 0x1001; 46 | private final static int MSG_EVENT_NO_FACE = 0x1002; 47 | private final static int MSG_EVENT_NO_FEATURE = 0x1003; 48 | private final static int MSG_EVENT_FD_ERROR = 0x1004; 49 | private final static int MSG_EVENT_FR_ERROR = 0x1005; 50 | private UIHandler mUIHandler; 51 | // Intent data. 52 | private String mFilePath; 53 | 54 | private SurfaceView mSurfaceView; 55 | private SurfaceHolder mSurfaceHolder; 56 | private Bitmap mBitmap; 57 | private Rect src = new Rect(); 58 | private Rect dst = new Rect(); 59 | private Thread view; 60 | private EditText mEditText; 61 | private ExtImageView mExtImageView; 62 | private AFR_FSDKFace mAFR_FSDKFace; 63 | 64 | @Override 65 | protected void onCreate(Bundle savedInstanceState) { 66 | // TODO Auto-generated method stub 67 | super.onCreate(savedInstanceState); 68 | this.setContentView(R.layout.activity_register); 69 | //initial data. 70 | if (!getIntentData(getIntent().getExtras())) { 71 | Log.e(TAG, "getIntentData fail!"); 72 | this.finish(); 73 | } 74 | 75 | mUIHandler = new UIHandler(); 76 | mBitmap = Application.decodeImage(mFilePath); 77 | src.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); 78 | mSurfaceView = (SurfaceView) this.findViewById(R.id.surfaceView); 79 | mSurfaceView.getHolder().addCallback(this); 80 | //图像转换->对选择图片进行人脸检测->展示图片->人脸识别->将人脸信息注册 81 | view = new Thread(new Runnable() { 82 | @Override 83 | public void run() { 84 | while (mSurfaceHolder == null) { 85 | try { 86 | Thread.sleep(100); 87 | } catch (InterruptedException e) { 88 | e.printStackTrace(); 89 | } 90 | } 91 | 92 | byte[] data = new byte[mBitmap.getWidth() * mBitmap.getHeight() * 3 / 2]; 93 | //图像转换 94 | ImageConverter convert = new ImageConverter(); 95 | convert.initial(mBitmap.getWidth(), mBitmap.getHeight(), ImageConverter.CP_PAF_NV21); 96 | if (convert.convert(mBitmap, data)) { 97 | Log.d(TAG, "convert ok!"); 98 | } 99 | convert.destroy(); 100 | 101 | AFD_FSDKEngine engine = new AFD_FSDKEngine(); 102 | AFD_FSDKVersion version = new AFD_FSDKVersion(); 103 | List result = new ArrayList(); 104 | //初始化人脸检测引擎 105 | AFD_FSDKError err = engine.AFD_FSDK_InitialFaceEngine(FaceDB.appid, FaceDB.fd_key, AFD_FSDKEngine.AFD_OPF_0_HIGHER_EXT, 16, 5); 106 | Log.d(TAG, "AFD_FSDK_InitialFaceEngine = " + err.getCode()); 107 | if (err.getCode() != AFD_FSDKError.MOK) { 108 | Message reg = Message.obtain();//从整个Messge池中返回一个新的Message实例,通过obtainMessage能避免重复Message创建对象。 109 | reg.what = MSG_CODE; 110 | reg.arg1 = MSG_EVENT_FD_ERROR; 111 | reg.arg2 = err.getCode(); 112 | mUIHandler.sendMessage(reg); 113 | } 114 | err = engine.AFD_FSDK_GetVersion(version); 115 | Log.d(TAG, "AFD_FSDK_GetVersion =" + version.toString() + ", " + err.getCode()); 116 | //检测输入的图像中存在的人脸 117 | err = engine.AFD_FSDK_StillImageFaceDetection(data, mBitmap.getWidth(), mBitmap.getHeight(), AFD_FSDKEngine.CP_PAF_NV21, result); 118 | Log.d(TAG, "AFD_FSDK_StillImageFaceDetection =" + err.getCode() + "<" + result.size()); 119 | while (mSurfaceHolder != null) { 120 | Canvas canvas = mSurfaceHolder.lockCanvas(); 121 | if (canvas != null) { 122 | Paint mPaint = new Paint(); 123 | //判断横向有无适配屏幕 124 | boolean fit_horizontal = canvas.getWidth() / (float) src.width() < canvas.getHeight() / (float) src.height() ? true : false; 125 | float scale = 1.0f; 126 | 127 | if (fit_horizontal) { 128 | scale = canvas.getWidth() / (float) src.width(); 129 | dst.left = 0; 130 | dst.top = (canvas.getHeight() - (int) (src.height() * scale)) / 2; 131 | dst.right = dst.left + canvas.getWidth(); 132 | dst.bottom = dst.top + (int) (src.height() * scale); 133 | } else { 134 | scale = canvas.getHeight() / (float) src.height(); 135 | dst.left = (canvas.getWidth() - (int) (src.width() * scale)) / 2; 136 | dst.top = 0; 137 | dst.right = dst.left + (int) (src.width() * scale); 138 | dst.bottom = dst.top + canvas.getHeight(); 139 | } 140 | 141 | canvas.drawBitmap(mBitmap, src, dst, mPaint); 142 | canvas.save(); 143 | canvas.scale((float) dst.width() / (float) src.width(), (float) dst.height() / (float) src.height()); 144 | canvas.translate(dst.left / scale, dst.top / scale); 145 | for (AFD_FSDKFace face : result) { 146 | mPaint.setColor(Color.RED); 147 | mPaint.setStrokeWidth(10.0f); 148 | mPaint.setStyle(Paint.Style.STROKE); 149 | //画框 150 | canvas.drawRect(face.getRect(), mPaint); 151 | } 152 | 153 | canvas.restore(); 154 | mSurfaceHolder.unlockCanvasAndPost(canvas); 155 | break; 156 | } 157 | } 158 | 159 | if (!result.isEmpty()) { 160 | //人脸识别引擎 161 | AFR_FSDKVersion version1 = new AFR_FSDKVersion(); 162 | AFR_FSDKEngine engine1 = new AFR_FSDKEngine(); 163 | AFR_FSDKFace result1 = new AFR_FSDKFace(); 164 | AFR_FSDKError error1 = engine1.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key); 165 | Log.d("com.arcsoft", "AFR_FSDK_InitialEngine = " + error1.getCode()); 166 | if (error1.getCode() != AFD_FSDKError.MOK) { 167 | Message reg = Message.obtain(); 168 | reg.what = MSG_CODE; 169 | reg.arg1 = MSG_EVENT_FR_ERROR; 170 | reg.arg2 = error1.getCode(); 171 | mUIHandler.sendMessage(reg); 172 | } 173 | error1 = engine1.AFR_FSDK_GetVersion(version1); 174 | Log.d("com.arcsoft", "FR=" + version.toString() + "," + error1.getCode()); //(210, 178 - 478, 446), degree = 1 780, 2208 - 1942, 3370 175 | error1 = engine1.AFR_FSDK_ExtractFRFeature(data, mBitmap.getWidth(), mBitmap.getHeight(), AFR_FSDKEngine.CP_PAF_NV21, new Rect(result.get(0).getRect()), result.get(0).getDegree(), result1); 176 | Log.d("com.arcsoft", "Face=" + result1.getFeatureData()[0] + "," + result1.getFeatureData()[1] + "," + result1.getFeatureData()[2] + "," + error1.getCode()); 177 | 178 | //检测人脸成功就将人脸信息发到服务器 179 | if (error1.getCode() == error1.MOK) { 180 | mAFR_FSDKFace = result1.clone(); 181 | int width = result.get(0).getRect().width(); 182 | int height = result.get(0).getRect().height(); 183 | Bitmap face_bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 184 | Canvas face_canvas = new Canvas(face_bitmap); 185 | face_canvas.drawBitmap(mBitmap, result.get(0).getRect(), new Rect(0, 0, width, height), null); 186 | Message reg = Message.obtain(); 187 | reg.what = MSG_CODE; 188 | reg.arg1 = MSG_EVENT_REG; 189 | reg.obj = face_bitmap; 190 | mUIHandler.sendMessage(reg); 191 | } 192 | //否则就发送检测不到信息 193 | else { 194 | Message reg = Message.obtain(); 195 | reg.what = MSG_CODE; 196 | reg.arg1 = MSG_EVENT_NO_FEATURE; 197 | mUIHandler.sendMessage(reg); 198 | } 199 | //销毁人脸识别引擎 200 | error1 = engine1.AFR_FSDK_UninitialEngine(); 201 | Log.d("com.arcsoft", "AFR_FSDK_UninitialEngine : " + error1.getCode()); 202 | } else { 203 | Message reg = Message.obtain(); 204 | reg.what = MSG_CODE; 205 | reg.arg1 = MSG_EVENT_NO_FACE; 206 | mUIHandler.sendMessage(reg); 207 | } 208 | //销毁人脸检测引擎 209 | err = engine.AFD_FSDK_UninitialFaceEngine(); 210 | Log.d(TAG, "AFD_FSDK_UninitialFaceEngine =" + err.getCode()); 211 | } 212 | }); 213 | view.start(); 214 | 215 | } 216 | 217 | /** 218 | * @param bundle 219 | * @note bundle data : 220 | * String imagePath 221 | */ 222 | private boolean getIntentData(Bundle bundle) { 223 | try { 224 | mFilePath = bundle.getString("imagePath"); 225 | if (mFilePath == null || mFilePath.isEmpty()) { 226 | return false; 227 | } 228 | Log.i(TAG, "getIntentData:" + mFilePath); 229 | return true; 230 | } catch (Exception e) { 231 | e.printStackTrace(); 232 | } 233 | return false; 234 | } 235 | 236 | @Override 237 | public void surfaceCreated(SurfaceHolder holder) { 238 | mSurfaceHolder = holder; 239 | } 240 | 241 | @Override 242 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 243 | 244 | } 245 | 246 | @Override 247 | public void surfaceDestroyed(SurfaceHolder holder) { 248 | mSurfaceHolder = null; 249 | try { 250 | view.join(); 251 | } catch (InterruptedException e) { 252 | e.printStackTrace(); 253 | } 254 | } 255 | 256 | @Override 257 | public void onClick(DialogInterface dialog, int which) { 258 | if (which == -1) { 259 | ((Application) this.getApplicationContext()).mFaceDB.addFace(mEditText.getText().toString(), mAFR_FSDKFace); 260 | } 261 | this.finish(); 262 | } 263 | 264 | class UIHandler extends android.os.Handler { 265 | @Override 266 | public void handleMessage(Message msg) { 267 | super.handleMessage(msg); 268 | if (msg.what == MSG_CODE) { 269 | //如果为注册事件 270 | //todo 将这里注册步骤提取,用来和服务器交互 271 | if (msg.arg1 == MSG_EVENT_REG) { 272 | LayoutInflater inflater = LayoutInflater.from(RegisterActivity.this); 273 | View layout = inflater.inflate(R.layout.dialog_register, null); 274 | mEditText = (EditText) layout.findViewById(R.id.editview); 275 | //对输入的文字进行过滤,不超过16 276 | mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(16)}); 277 | mExtImageView = (ExtImageView) layout.findViewById(R.id.extimageview); 278 | //msg的obj为人脸图片 279 | mExtImageView.setImageBitmap((Bitmap) msg.obj); 280 | new AlertDialog.Builder(RegisterActivity.this) 281 | .setTitle("请输入注册名字") 282 | .setIcon(android.R.drawable.ic_dialog_info) 283 | .setView(layout) 284 | .setPositiveButton("确定", RegisterActivity.this) 285 | .setNegativeButton("取消", RegisterActivity.this) 286 | .show(); 287 | } else if (msg.arg1 == MSG_EVENT_NO_FEATURE) { 288 | Toast.makeText(RegisterActivity.this, "人脸特征无法检测,请换一张图片", Toast.LENGTH_SHORT).show(); 289 | } else if (msg.arg1 == MSG_EVENT_NO_FACE) { 290 | Toast.makeText(RegisterActivity.this, "没有检测到人脸,请换一张图片", Toast.LENGTH_SHORT).show(); 291 | } else if (msg.arg1 == MSG_EVENT_FD_ERROR) { 292 | Toast.makeText(RegisterActivity.this, "FD初始化失败,错误码:" + msg.arg2, Toast.LENGTH_SHORT).show(); 293 | } else if (msg.arg1 == MSG_EVENT_FR_ERROR) { 294 | Toast.makeText(RegisterActivity.this, "FR初始化失败,错误码:" + msg.arg2, Toast.LENGTH_SHORT).show(); 295 | } 296 | } 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/src/main/res/drawable-hdpi/ic_sync.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/src/main/res/drawable-mdpi/ic_sync.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/src/main/res/drawable-xhdpi/ic_sync.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/welcom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/src/main/res/drawable-xhdpi/welcom.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/welcom1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/src/main/res/drawable-xhdpi/welcom1.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchenhao006/FaceDetectAccessControl/c4b8821fee12bfc31a97511d4459c83378d000d8/app/src/main/res/drawable-xxhdpi/ic_sync.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 19 | 20 | 26 | 27 | 37 | 38 | 48 | 49 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_register.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_welcome.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 19 | 20 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_register.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 18 | 19 |