├── .gitignore
├── .idea
├── encodings.xml
├── gradle.xml
├── misc.xml
├── runConfigurations.xml
└── vcs.xml
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── armeabi-v7a
│ │ ├── libFaceDetectorJni.so
│ │ ├── libFaceRecognizerJni.so
│ │ ├── libPointDetectorJni.so
│ │ └── libholiday.so
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── itfitness
│ │ └── seetaface2
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── SeetaFaceDetector2.0.ats
│ ├── java
│ │ └── com
│ │ │ └── itfitness
│ │ │ └── seetaface2
│ │ │ ├── FaceDetectorActivity.java
│ │ │ ├── FaceRecognizerActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── PointDetectorActivity.java
│ │ │ ├── engine
│ │ │ └── FaceEngine.java
│ │ │ ├── facefind
│ │ │ └── FaceFindActivity.java
│ │ │ ├── facelogin
│ │ │ ├── FaceInitActivity.java
│ │ │ ├── FaceLoginActivity.java
│ │ │ └── LoginActivity.java
│ │ │ ├── utils
│ │ │ ├── ConvertUtil.java
│ │ │ └── FileUtil.java
│ │ │ └── widget
│ │ │ ├── FaceCameraView.java
│ │ │ └── FaceRectView.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── heying.jpg
│ │ ├── ic_launcher_background.xml
│ │ ├── seetaface.jpg
│ │ ├── tang01.png
│ │ ├── tang02.jpg
│ │ ├── tang03.jpg
│ │ ├── tang04.jpg
│ │ ├── tang05.png
│ │ ├── tang06.png
│ │ ├── tang07.jpg
│ │ ├── tang08.jpg
│ │ ├── tang09.png
│ │ └── tang10.jpg
│ │ ├── layout
│ │ ├── activity_facedetector.xml
│ │ ├── activity_facefind.xml
│ │ ├── activity_facelogin.xml
│ │ ├── activity_facerecognizer.xml
│ │ ├── activity_login.xml
│ │ ├── activity_main.xml
│ │ └── activity_pointdetector.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── 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
│ └── com
│ └── itfitness
│ └── seetaface2
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── seetalibrary
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── seeta
│ │ └── sdk
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── seeta
│ │ │ └── sdk
│ │ │ ├── FaceDetector2.java
│ │ │ ├── FaceRecognizer2.java
│ │ │ ├── PointDetector2.java
│ │ │ ├── SeetaImageData.java
│ │ │ ├── SeetaPointF.java
│ │ │ └── SeetaRect.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── seeta
│ └── sdk
│ └── ExampleUnitTest.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion "29.0.1"
6 | defaultConfig {
7 | applicationId "com.itfitness.seetaface2"
8 | minSdkVersion 15
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | ndk {
14 | abiFilters 'armeabi-v7a'
15 | }
16 | }
17 | sourceSets {
18 | main {
19 | jniLibs.srcDirs = ['libs']
20 | }
21 | }
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(dir: 'libs', include: ['*.jar'])
32 | implementation 'com.android.support:appcompat-v7:28.0.0'
33 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
34 | testImplementation 'junit:junit:4.12'
35 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
36 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
37 | implementation project(path: ':seetalibrary')
38 | }
39 |
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libFaceDetectorJni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/libs/armeabi-v7a/libFaceDetectorJni.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libFaceRecognizerJni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/libs/armeabi-v7a/libFaceRecognizerJni.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libPointDetectorJni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/libs/armeabi-v7a/libPointDetectorJni.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libholiday.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/libs/armeabi-v7a/libholiday.so
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/itfitness/seetaface2/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2;
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 | * Instrumented 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() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.itfitness.seetaface2", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/assets/SeetaFaceDetector2.0.ats:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/assets/SeetaFaceDetector2.0.ats
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/FaceDetectorActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Rect;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.os.Bundle;
11 | import android.view.View;
12 | import android.widget.Button;
13 | import android.widget.ImageView;
14 | import com.itfitness.seetaface2.engine.FaceEngine;
15 | import com.itfitness.seetaface2.utils.ConvertUtil;
16 | import com.seeta.sdk.SeetaImageData;
17 | import com.seeta.sdk.SeetaRect;
18 |
19 | public class FaceDetectorActivity extends AppCompatActivity {
20 | private Button mBt;
21 | private ImageView mImg;
22 | private SeetaRect[] faceRects;
23 | private Bitmap bitmap;
24 | private SeetaImageData seetaImageData;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_facedetector);
30 | //将模型拷贝到SD卡中
31 | //FileUtil.CopyAssets(this,"SeetaFaceDetector2.0.ats",Environment.getExternalStorageDirectory()+ File.separator+"SeetaFaceDetector2.0.ats");
32 | initView();
33 | initFace();
34 | mBt.setOnClickListener(new View.OnClickListener() {
35 | @Override
36 | public void onClick(View v) {
37 | //如果图像中检测出人脸了再进行绘制
38 | if(faceRects.length>0){
39 | //这里必须进行copy否则修改不了
40 | Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, true);
41 | //利用Bitmap创建Canvas,为了在图像上绘制人脸区域
42 | Canvas canvas = new Canvas(copy);
43 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
44 | paint.setStyle(Paint.Style.STROKE);
45 | paint.setStrokeWidth(3);
46 | //绘制出所有的检测出来的人脸的区域
47 | for(int i = 0 ; i < faceRects.length ; i++){
48 | paint.setColor(Color.BLUE);
49 | SeetaRect faceRect = faceRects[i];
50 | Rect rect = new Rect(faceRect.x,faceRect.y,faceRect.x+faceRect.width,faceRect.y+faceRect.height);
51 | canvas.drawRect(rect,paint);
52 | }
53 | mImg.setImageBitmap(copy);
54 | }
55 | }
56 | });
57 | }
58 |
59 | /**
60 | * 初始化人脸检测器
61 | */
62 | private void initFace() {
63 | //初始化检测器(参数是模型在SD卡的位置)
64 | bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.heying);
65 | //利用SeetaFace2提供的转换方法获取SeetaRect(人脸识别结果)
66 | seetaImageData = ConvertUtil.ConvertToSeetaImageData(bitmap);
67 | if(FaceEngine.FACEDETECTOR!=null){
68 | faceRects = FaceEngine.FACEDETECTOR.Detect(seetaImageData);
69 | }
70 | }
71 |
72 | private void initView() {
73 | mBt = findViewById(R.id.bt_face);
74 | mImg = findViewById(R.id.img);
75 | }
76 |
77 | @Override
78 | protected void onDestroy() {
79 | super.onDestroy();
80 | //用了一个引擎后就不需要释放了
81 | // FaceEngine.FACEDETECTOR.dispose();
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/FaceRecognizerActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Rect;
9 | import android.os.Bundle;
10 | import android.os.Handler;
11 | import android.os.Message;
12 | import android.support.v7.app.AppCompatActivity;
13 | import android.util.Log;
14 | import android.view.View;
15 | import android.widget.Button;
16 | import android.widget.ImageView;
17 | import android.widget.Toast;
18 |
19 | import com.itfitness.seetaface2.engine.FaceEngine;
20 | import com.itfitness.seetaface2.utils.ConvertUtil;
21 | import com.seeta.sdk.SeetaImageData;
22 | import com.seeta.sdk.SeetaPointF;
23 | import com.seeta.sdk.SeetaRect;
24 |
25 | /**
26 | * 人脸匹配
27 | */
28 | public class FaceRecognizerActivity extends AppCompatActivity {
29 | private Button mBt;
30 | private ImageView mImg;
31 | private int registerIndex;
32 | private boolean moduleFlag = false;
33 | private Handler handler = new Handler(){
34 | @Override
35 | public void handleMessage(Message msg) {
36 | super.handleMessage(msg);
37 | mImg.setImageBitmap((Bitmap) msg.obj);
38 | }
39 | };
40 | @Override
41 | protected void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | setContentView(R.layout.activity_facerecognizer);
44 | //将模型拷贝到SD卡中
45 | initView();
46 | initFace();
47 | mBt.setOnClickListener(new View.OnClickListener() {
48 | @Override
49 | public void onClick(View v) {
50 | //如果人脸模型初始化成功了再操作
51 | if(moduleFlag){
52 | Toast.makeText(FaceRecognizerActivity.this, "匹配中请稍等", Toast.LENGTH_SHORT).show();
53 | new Thread(new Runnable() {
54 | @Override
55 | public void run() {
56 | //加载进行匹配的图像
57 | Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tang08);
58 | //这里必须进行copy否则修改不了
59 | Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, true);
60 | //利用Bitmap创建Canvas,为了在图像上绘制人脸区域
61 | Canvas canvas = new Canvas(copy);
62 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
63 | paint.setColor(Color.RED);
64 | paint.setStyle(Paint.Style.STROKE);
65 | paint.setStrokeWidth(3);
66 | SeetaImageData seetaImageData = ConvertUtil.ConvertToSeetaImageData(bitmap);
67 | //人脸检测
68 | SeetaRect[] detects = FaceEngine.FACEDETECTOR.Detect(seetaImageData);
69 | if(detects.length>0){
70 | //将所有检测到的人脸与注册到数据库的人脸进行匹配
71 | for(int i = 0 ; i < detects.length ; i++){
72 | SeetaRect faceRect = detects[i];
73 | SeetaPointF[] seetaPoints = FaceEngine.POINTDETECTOR.Detect(seetaImageData, faceRect);//根据检测到的人脸进行特征点检测
74 | float[] similarity = new float[1];//用来存储人脸相似度值
75 | int targetIndex = FaceEngine.FACERECOGNIZER.Recognize(seetaImageData, seetaPoints, similarity);//匹配
76 | Log.e("人脸匹配",targetIndex+"======="+registerIndex+"====="+similarity[0]);
77 | //如果匹配值大于0.7说明是同一个人
78 | if(similarity[0]>0.7){
79 | //将匹配出来的人脸区域绘制出来
80 | Rect rect = new Rect(faceRect.x,faceRect.y,faceRect.x+faceRect.width,faceRect.y+faceRect.height);
81 | canvas.drawRect(rect,paint);
82 | }
83 | }
84 | //通知主线程更新UI
85 | Message obtain = Message.obtain();
86 | obtain.obj = copy;
87 | handler.sendMessage(obtain);
88 | }
89 | }
90 | }).start();
91 | }else {
92 | Toast.makeText(FaceRecognizerActivity.this, "人脸模型尚未初始化成功请稍等", Toast.LENGTH_SHORT).show();
93 | }
94 | }
95 | });
96 | }
97 |
98 | /**
99 | * 初始化人脸检测器
100 | */
101 | private void initFace() {
102 | new Thread(new Runnable() {
103 | @Override
104 | public void run() {
105 | Bitmap registBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tang01);
106 | //利用SeetaFace2提供的转换方法获取SeetaRect(人脸识别结果)
107 | SeetaImageData RegistSeetaImageData = ConvertUtil.ConvertToSeetaImageData(registBitmap);
108 | SeetaRect[] faceRects = FaceEngine.FACEDETECTOR.Detect(RegistSeetaImageData);
109 | if(faceRects.length>0){
110 | //获取人脸区域(这里只有一个所以取0)
111 | SeetaRect faceRect = faceRects[0];
112 | SeetaPointF[] seetaPoints = FaceEngine.POINTDETECTOR.Detect(RegistSeetaImageData, faceRect);//根据检测到的人脸进行特征点检测
113 | registerIndex = FaceEngine.FACERECOGNIZER.Register(RegistSeetaImageData, seetaPoints);//将人脸注册到SeetaFace2数据库
114 | }
115 | runOnUiThread(new Runnable() {
116 | @Override
117 | public void run() {
118 | Toast.makeText(FaceRecognizerActivity.this, "人脸模型初始化成功", Toast.LENGTH_SHORT).show();
119 | }
120 | });
121 | //模型加载标记
122 | moduleFlag = true;
123 | }
124 | }).start();
125 | }
126 |
127 | private void initView() {
128 | mBt = findViewById(R.id.bt_face);
129 | mImg = findViewById(R.id.img);
130 | }
131 |
132 | @Override
133 | protected void onDestroy() {
134 | super.onDestroy();
135 | //释放
136 | //用了一个引擎后就不需要释放了
137 | // if(FaceEngine.FACEDETECTOR!=null){
138 | // FaceEngine.FACEDETECTOR.dispose();
139 | // }
140 | if(FaceEngine.FACERECOGNIZER!=null){
141 | FaceEngine.FACERECOGNIZER.Clear();//清空注册的人脸
142 | // FaceEngine.FACERECOGNIZER.dispose();
143 | }
144 | // if(FaceEngine.POINTDETECTOR!=null){
145 | // FaceEngine.POINTDETECTOR.dispose();
146 | // }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.View;
8 | import android.widget.Toast;
9 |
10 | import com.itfitness.seetaface2.engine.FaceEngine;
11 | import com.itfitness.seetaface2.facefind.FaceFindActivity;
12 | import com.itfitness.seetaface2.facelogin.FaceLoginActivity;
13 |
14 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
15 | @Override
16 | protected void onCreate(@Nullable Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_main);
19 | //初始化引擎
20 | FaceEngine.init();
21 | setClickListener(R.id.bt_one);
22 | setClickListener(R.id.bt_two);
23 | setClickListener(R.id.bt_three);
24 | setClickListener(R.id.bt_four);
25 | setClickListener(R.id.bt_five);
26 | }
27 | private void setClickListener(int id){
28 | findViewById(id).setOnClickListener(this);
29 | }
30 | @Override
31 | public void onClick(View v) {
32 | if(!FaceEngine.INIT_SUCCESS){
33 | Toast.makeText(this, "引擎尚未加载完毕请稍等", Toast.LENGTH_SHORT).show();
34 | return;
35 | }
36 | switch (v.getId()){
37 | case R.id.bt_one:
38 | gotoActivity(FaceDetectorActivity.class);
39 | break;
40 | case R.id.bt_two:
41 | gotoActivity(PointDetectorActivity.class);
42 | break;
43 | case R.id.bt_three:
44 | gotoActivity(FaceRecognizerActivity.class);
45 | break;
46 | case R.id.bt_four:
47 | gotoActivity(FaceLoginActivity.class);
48 | break;
49 | case R.id.bt_five:
50 | gotoActivity(FaceFindActivity.class);
51 | break;
52 | }
53 | }
54 | private void gotoActivity(Class clazz){
55 | startActivity(new Intent(this,clazz));
56 | }
57 |
58 | @Override
59 | protected void onDestroy() {
60 | super.onDestroy();
61 | //释放
62 | //用了一个引擎后就不需要释放了
63 | if(FaceEngine.FACEDETECTOR!=null){
64 | FaceEngine.FACEDETECTOR.dispose();
65 | }
66 | if(FaceEngine.FACERECOGNIZER!=null){
67 | FaceEngine.FACERECOGNIZER.Clear();//清空注册的人脸
68 | FaceEngine.FACERECOGNIZER.dispose();
69 | }
70 | if(FaceEngine.POINTDETECTOR!=null){
71 | FaceEngine.POINTDETECTOR.dispose();
72 | }
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/PointDetectorActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.os.Bundle;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.view.View;
11 | import android.widget.Button;
12 | import android.widget.ImageView;
13 |
14 | import com.itfitness.seetaface2.engine.FaceEngine;
15 | import com.itfitness.seetaface2.utils.ConvertUtil;
16 | import com.seeta.sdk.SeetaImageData;
17 | import com.seeta.sdk.SeetaPointF;
18 | import com.seeta.sdk.SeetaRect;
19 |
20 | /**
21 | * 特征点检测
22 | */
23 | public class PointDetectorActivity extends AppCompatActivity {
24 | private Button mBt;
25 | private ImageView mImg;
26 | private SeetaRect[] faceRects;
27 | private Bitmap bitmap;
28 | private SeetaImageData seetaImageData;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_pointdetector);
34 | //将模型拷贝到SD卡中
35 | //FileUtil.CopyAssets(this,"SeetaFaceDetector2.0.ats",Environment.getExternalStorageDirectory()+ File.separator+"SeetaFaceDetector2.0.ats");
36 | initView();
37 | initFace();
38 | mBt.setOnClickListener(new View.OnClickListener() {
39 | @Override
40 | public void onClick(View v) {
41 | //如果图像中检测出人脸了再进行绘制
42 | if(faceRects.length>0){
43 | //这里必须进行copy否则修改不了
44 | Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, true);
45 | //利用Bitmap创建Canvas,为了在图像上绘制人脸区域
46 | Canvas canvas = new Canvas(copy);
47 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
48 | paint.setColor(Color.RED);
49 | paint.setStyle(Paint.Style.STROKE);
50 | paint.setStrokeWidth(3);
51 | //绘制出所有的检测出来的人脸的区域
52 | for(int i = 0 ; i < faceRects.length ; i++){
53 | SeetaRect faceRect = faceRects[i];
54 | SeetaPointF[] seetaPoints = FaceEngine.POINTDETECTOR.Detect(seetaImageData, faceRect);//根据检测到的人脸进行特征点检测
55 | if(seetaPoints.length>0){
56 | for(SeetaPointF seetaPoint:seetaPoints){
57 | //绘制特征点
58 | canvas.drawCircle((float) seetaPoint.x,(float) seetaPoint.y,5,paint);
59 | }
60 | }
61 | }
62 | mImg.setImageBitmap(copy);
63 | }
64 | }
65 | });
66 | }
67 |
68 | /**
69 | * 初始化人脸检测器
70 | */
71 | private void initFace() {
72 | //初始化检测器(参数是模型在SD卡的位置)
73 | bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.heying);
74 | //利用SeetaFace2提供的转换方法获取SeetaRect(人脸识别结果)
75 | seetaImageData = ConvertUtil.ConvertToSeetaImageData(bitmap);
76 | faceRects = FaceEngine.FACEDETECTOR.Detect(seetaImageData);
77 | }
78 |
79 | private void initView() {
80 | mBt = findViewById(R.id.bt_face);
81 | mImg = findViewById(R.id.img);
82 | }
83 |
84 | @Override
85 | protected void onDestroy() {
86 | super.onDestroy();
87 | //用了一个引擎后就不需要释放了
88 | // if(FaceEngine.FACEDETECTOR!=null){
89 | // FaceEngine.FACEDETECTOR.dispose();
90 | // }
91 | // if(FaceEngine.POINTDETECTOR!=null){
92 | // FaceEngine.POINTDETECTOR.dispose();
93 | // }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/engine/FaceEngine.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.engine;
2 |
3 | import android.os.Environment;
4 |
5 | import com.seeta.sdk.FaceDetector2;
6 | import com.seeta.sdk.FaceRecognizer2;
7 | import com.seeta.sdk.PointDetector2;
8 |
9 | import java.io.File;
10 |
11 | public class FaceEngine {
12 | public static FaceDetector2 FACEDETECTOR;
13 | public static PointDetector2 POINTDETECTOR;
14 | public static FaceRecognizer2 FACERECOGNIZER;
15 | public static boolean INIT_SUCCESS = false;//是否加载成功
16 | /**
17 | * 初始化引擎
18 | */
19 | public static void init(){
20 | new Thread(new Runnable() {
21 | @Override
22 | public void run() {
23 | FACEDETECTOR = new FaceDetector2(Environment.getExternalStorageDirectory()+ File.separator+"seetaface"+File.separator+"SeetaFaceDetector2.0.ats");
24 | POINTDETECTOR = new PointDetector2(Environment.getExternalStorageDirectory()+ File.separator+"seetaface"+File.separator+"SeetaPointDetector2.0.pts5.ats"); //特征点
25 | FACERECOGNIZER = new FaceRecognizer2(Environment.getExternalStorageDirectory()+ File.separator+"seetaface"+File.separator+"SeetaFaceRecognizer2.0.ats"); //人脸匹配
26 | INIT_SUCCESS = true;
27 | }
28 | }).start();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/facefind/FaceFindActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.facefind;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.graphics.ImageFormat;
7 | import android.graphics.Matrix;
8 | import android.graphics.Rect;
9 | import android.graphics.YuvImage;
10 | import android.hardware.Camera;
11 | import android.os.Bundle;
12 | import android.os.Handler;
13 | import android.os.Message;
14 | import android.support.annotation.Nullable;
15 | import android.support.v7.app.AppCompatActivity;
16 |
17 | import com.itfitness.seetaface2.R;
18 | import com.itfitness.seetaface2.engine.FaceEngine;
19 | import com.itfitness.seetaface2.utils.ConvertUtil;
20 | import com.itfitness.seetaface2.widget.FaceCameraView;
21 | import com.itfitness.seetaface2.widget.FaceRectView;
22 | import com.seeta.sdk.SeetaImageData;
23 | import com.seeta.sdk.SeetaRect;
24 |
25 | import java.io.ByteArrayOutputStream;
26 |
27 | public class FaceFindActivity extends AppCompatActivity {
28 | private FaceCameraView faceCameraView;
29 | private FaceRectView faceRectView;
30 | private boolean isScaing = false;
31 | @SuppressLint("HandlerLeak")
32 | private Handler handler = new Handler() {
33 | @Override
34 | public void handleMessage(Message msg) {
35 | super.handleMessage(msg);
36 | faceRectView.setFaceDatas((SeetaRect[]) msg.obj);
37 | isScaing = false;
38 | }
39 | };
40 |
41 | @Override
42 | protected void onCreate(@Nullable Bundle savedInstanceState) {
43 | super.onCreate(savedInstanceState);
44 | setContentView(R.layout.activity_facefind);
45 | initView();
46 | initPreViewCallback();
47 | }
48 |
49 | private void initPreViewCallback() {
50 | faceCameraView.setPreviewCallback(new FaceCameraView.PreviewCallback() {
51 | @Override
52 | public void onPreview(final byte[] data, final Camera camera) {
53 | if (FaceEngine.FACEDETECTOR != null && FaceEngine.FACERECOGNIZER != null && FaceEngine.POINTDETECTOR != null) {
54 | new Thread(new Runnable() {
55 | @Override
56 | public void run() {
57 | //识别中不处理其他帧数据
58 | if (!isScaing) {
59 | isScaing = true;
60 | try {
61 | //获取Camera预览尺寸
62 | Camera.Size size = camera.getParameters().getPreviewSize();
63 | //将帧数据转为bitmap
64 | YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
65 | if (image != null) {
66 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
67 | image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);
68 | Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
69 | //纠正图像的旋转角度问题
70 | Matrix m = new Matrix();
71 | m.setRotate(-90, (float) bmp.getWidth() / 2, (float) bmp.getHeight() / 2);
72 | Bitmap bm = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
73 | SeetaImageData loginSeetaImageData = ConvertUtil.ConvertToSeetaImageData(bm);
74 | SeetaRect[] faceRects = FaceEngine.FACEDETECTOR.Detect(loginSeetaImageData);
75 | if(faceRects.length>0){
76 | Message obtain = Message.obtain();
77 | obtain.obj = faceRects;
78 | handler.sendMessage(obtain);
79 | }
80 | }
81 | } catch (Exception ex) {
82 | isScaing = false;
83 | }
84 | }
85 | }
86 | }
87 | ).start();
88 | }
89 | }
90 | });
91 | }
92 |
93 | private void initView() {
94 | faceCameraView = findViewById(R.id.camera_findface);
95 | faceRectView = findViewById(R.id.facerect);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/facelogin/FaceInitActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.facelogin;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.ImageFormat;
6 | import android.graphics.Matrix;
7 | import android.graphics.Rect;
8 | import android.graphics.YuvImage;
9 | import android.hardware.Camera;
10 | import android.os.Bundle;
11 | import android.os.Handler;
12 | import android.os.Message;
13 | import android.support.v7.app.AppCompatActivity;
14 | import android.widget.Toast;
15 |
16 | import com.itfitness.seetaface2.R;
17 | import com.itfitness.seetaface2.widget.FaceCameraView;
18 | import com.itfitness.seetaface2.engine.FaceEngine;
19 | import com.itfitness.seetaface2.utils.ConvertUtil;
20 | import com.seeta.sdk.SeetaImageData;
21 | import com.seeta.sdk.SeetaPointF;
22 | import com.seeta.sdk.SeetaRect;
23 |
24 | import java.io.ByteArrayOutputStream;
25 |
26 | public class FaceInitActivity extends AppCompatActivity{
27 | private FaceCameraView faceInitCameraView;
28 | private boolean isScanning = false;
29 | Handler handler = new Handler() {
30 | @Override
31 | public void handleMessage(Message msg) {
32 | super.handleMessage(msg);
33 | Toast.makeText(FaceInitActivity.this, "信息录入成功", Toast.LENGTH_SHORT).show();
34 | finish();
35 | }
36 | };
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_login);
41 | initView();
42 | }
43 | private void initView(){
44 | faceInitCameraView = (FaceCameraView) findViewById(R.id.camera2);
45 | faceInitCameraView.setPreviewCallback(new FaceCameraView.PreviewCallback() {
46 | @Override
47 | public void onPreview(final byte[] data, final Camera camera) {
48 | if(FaceEngine.FACEDETECTOR!=null&&FaceEngine.FACERECOGNIZER!=null&&FaceEngine.POINTDETECTOR!=null){
49 | new Thread(new Runnable() {
50 | @Override
51 | public void run() {
52 | //识别中不处理其他帧数据
53 | if (!isScanning) {
54 | isScanning = true;
55 | try {
56 | //获取Camera预览尺寸
57 | Camera.Size size = camera.getParameters().getPreviewSize();
58 | //将帧数据转为bitmap
59 | YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
60 | if (image != null) {
61 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
62 | image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);
63 | Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
64 | //纠正图像的旋转角度问题
65 | Matrix m = new Matrix();
66 | m.setRotate(-90, (float) bmp.getWidth() / 2, (float) bmp.getHeight() / 2);
67 | Bitmap bm = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
68 | SeetaImageData RegistSeetaImageData = ConvertUtil.ConvertToSeetaImageData(bm);
69 | SeetaRect[] faceRects = FaceEngine.FACEDETECTOR.Detect(RegistSeetaImageData);
70 | if(faceRects.length>0){
71 | //获取人脸区域(这里只有一个所以取0)
72 | SeetaRect faceRect = faceRects[0];
73 | SeetaPointF[] seetaPoints = FaceEngine.POINTDETECTOR.Detect(RegistSeetaImageData, faceRect);//根据检测到的人脸进行特征点检测
74 | FaceEngine.FACERECOGNIZER.Register(RegistSeetaImageData, seetaPoints);//将人脸注册到SeetaFace2数据库
75 | handler.sendEmptyMessage(0);
76 | }else {
77 | //如果检测不到人脸给予如下提示
78 | runOnUiThread(new Runnable() {
79 | @Override
80 | public void run() {
81 | Toast.makeText(FaceInitActivity.this, "请保持手机不要晃动", Toast.LENGTH_SHORT).show();
82 | }
83 | });
84 | isScanning = false;
85 | }
86 | }
87 | } catch (Exception ex) {
88 | isScanning = false;
89 | }
90 | }
91 | }
92 | }
93 | ).start();
94 | }
95 | }
96 | });
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/facelogin/FaceLoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.facelogin;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.View;
8 | import com.itfitness.seetaface2.R;
9 |
10 | import static com.itfitness.seetaface2.engine.FaceEngine.FACERECOGNIZER;
11 |
12 | public class FaceLoginActivity extends AppCompatActivity implements View.OnClickListener {
13 | @Override
14 | protected void onCreate(@Nullable Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_facelogin);
17 | setClickListener(R.id.bt_initfacedata);
18 | setClickListener(R.id.bt_facelogin);
19 | }
20 |
21 | private void setClickListener(int id){
22 | findViewById(id).setOnClickListener(this);
23 | }
24 | @Override
25 | public void onClick(View v) {
26 | switch (v.getId()){
27 | case R.id.bt_initfacedata:
28 | //录入人脸信息
29 | gotoActivity(FaceInitActivity.class);
30 | break;
31 | case R.id.bt_facelogin:
32 | //人脸登录
33 | gotoActivity(LoginActivity.class);
34 | break;
35 | }
36 | }
37 | private void gotoActivity(Class clazz){
38 | startActivity(new Intent(this,clazz));
39 | }
40 |
41 | @Override
42 | protected void onDestroy() {
43 | super.onDestroy();
44 | //清空人脸数据
45 | if(FACERECOGNIZER!=null){
46 | FACERECOGNIZER.Clear();
47 | // FACERECOGNIZER.dispose();
48 | }
49 | //用了一个引擎后就不需要释放了
50 | // if(POINTDETECTOR!=null){
51 | // POINTDETECTOR.dispose();
52 | // }
53 | // if(FACEDETECTOR!=null){
54 | // FACEDETECTOR.dispose();
55 | // }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/facelogin/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.facelogin;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.ImageFormat;
6 | import android.graphics.Matrix;
7 | import android.graphics.Rect;
8 | import android.graphics.YuvImage;
9 | import android.hardware.Camera;
10 | import android.os.Bundle;
11 | import android.os.Handler;
12 | import android.os.Message;
13 | import android.support.v7.app.AppCompatActivity;
14 | import android.widget.Toast;
15 | import com.itfitness.seetaface2.R;
16 | import com.itfitness.seetaface2.widget.FaceCameraView;
17 | import com.itfitness.seetaface2.engine.FaceEngine;
18 | import com.itfitness.seetaface2.utils.ConvertUtil;
19 | import com.seeta.sdk.SeetaImageData;
20 | import com.seeta.sdk.SeetaPointF;
21 | import com.seeta.sdk.SeetaRect;
22 | import java.io.ByteArrayOutputStream;
23 | public class LoginActivity extends AppCompatActivity{
24 | private FaceCameraView faceCameraView;
25 | private boolean isScanning = false;
26 | private int failedCount = 0;//失败次数
27 | Handler handler = new Handler() {
28 | @Override
29 | public void handleMessage(Message msg) {
30 | super.handleMessage(msg);
31 | switch (msg.what){
32 | case 0:
33 | failedCount++;
34 | if(failedCount>=5){
35 | Toast.makeText(LoginActivity.this, "人脸不匹配,登录失败", Toast.LENGTH_SHORT).show();
36 | finish();
37 | }
38 | isScanning = false;
39 | break;
40 | case 1:
41 | Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
42 | finish();
43 | break;
44 | }
45 | }
46 | };
47 | @Override
48 | protected void onCreate(Bundle savedInstanceState) {
49 | super.onCreate(savedInstanceState);
50 | setContentView(R.layout.activity_login);
51 | initView();
52 | }
53 | private void initView(){
54 | faceCameraView = (FaceCameraView) findViewById(R.id.camera2);
55 | faceCameraView.setPreviewCallback(new FaceCameraView.PreviewCallback() {
56 | @Override
57 | public void onPreview(final byte[] data, final Camera camera) {
58 | if(FaceEngine.FACEDETECTOR!=null&&FaceEngine.FACERECOGNIZER!=null&&FaceEngine.POINTDETECTOR!=null){
59 | new Thread(new Runnable() {
60 | @Override
61 | public void run() {
62 | //识别中不处理其他帧数据
63 | if (!isScanning) {
64 | isScanning = true;
65 | try {
66 | //获取Camera预览尺寸
67 | Camera.Size size = camera.getParameters().getPreviewSize();
68 | //将帧数据转为bitmap
69 | YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
70 | if (image != null) {
71 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
72 | image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);
73 | Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
74 | //纠正图像的旋转角度问题
75 | Matrix m = new Matrix();
76 | m.setRotate(-90, (float) bmp.getWidth() / 2, (float) bmp.getHeight() / 2);
77 | Bitmap bm = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
78 | SeetaImageData loginSeetaImageData = ConvertUtil.ConvertToSeetaImageData(bm);
79 | SeetaRect[] faceRects = FaceEngine.FACEDETECTOR.Detect(loginSeetaImageData);
80 | if(faceRects.length>0){
81 | //获取人脸区域(这里只有一个所以取0)
82 | SeetaRect faceRect = faceRects[0];
83 | SeetaPointF[] seetaPoints = FaceEngine.POINTDETECTOR.Detect(loginSeetaImageData, faceRect);//根据检测到的人脸进行特征点检测
84 | float[] similarity = new float[1];//用来存储人脸相似度值
85 | FaceEngine.FACERECOGNIZER.Recognize(loginSeetaImageData, seetaPoints, similarity);//匹配
86 | if(similarity[0]>0.7){
87 | handler.sendEmptyMessage(1);
88 | }else {
89 | handler.sendEmptyMessage(0);
90 | }
91 | }else {
92 | runOnUiThread(new Runnable() {
93 | @Override
94 | public void run() {
95 | Toast.makeText(LoginActivity.this, "请保持手机不要晃动", Toast.LENGTH_SHORT).show();
96 | }
97 | });
98 | isScanning = false;
99 | }
100 | }
101 | } catch (Exception ex) {
102 | isScanning = false;
103 | }
104 | }
105 | }
106 | }
107 | ).start();
108 | }
109 | }
110 | });
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/utils/ConvertUtil.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.utils;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 |
6 | import com.itfitness.seetaface2.R;
7 | import com.seeta.sdk.SeetaImageData;
8 |
9 | import java.nio.ByteBuffer;
10 |
11 | public class ConvertUtil {
12 | /**
13 | * 转换生成SeetaImageData
14 | * @param bitmap
15 | * @return
16 | */
17 | public static SeetaImageData ConvertToSeetaImageData(Bitmap bitmap) {
18 | Bitmap bmp_src = bitmap.copy(Bitmap.Config.ARGB_8888, true); // true is RGBA
19 | //SeetaImageData大小与原图像一致,但是通道数为3个通道即BGR
20 | SeetaImageData imageData = new SeetaImageData(bmp_src.getWidth(), bmp_src.getHeight(), 3);
21 | imageData.data = getPixelsBGR(bmp_src);
22 | return imageData;
23 | }
24 |
25 | /**
26 | * 提取图像中的BGR像素
27 | * @param image
28 | * @return
29 | */
30 | public static byte[] getPixelsBGR(Bitmap image) {
31 | // calculate how many bytes our image consists of
32 | int bytes = image.getByteCount();
33 |
34 | ByteBuffer buffer = ByteBuffer.allocate(bytes); // Create a new buffer
35 | image.copyPixelsToBuffer(buffer); // Move the byte data to the buffer
36 |
37 | byte[] temp = buffer.array(); // Get the underlying array containing the data.
38 |
39 | byte[] pixels = new byte[(temp.length/4) * 3]; // Allocate for BGR
40 |
41 | // Copy pixels into place
42 | for (int i = 0; i < temp.length/4; i++) {
43 |
44 | pixels[i * 3] = temp[i * 4 + 2]; //B
45 | pixels[i * 3 + 1] = temp[i * 4 + 1]; //G
46 | pixels[i * 3 + 2] = temp[i * 4 ]; //R
47 |
48 | }
49 |
50 | return pixels;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/utils/FileUtil.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.utils;
2 |
3 | import android.content.Context;
4 |
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.InputStream;
8 |
9 | public class FileUtil {
10 | /**
11 | *
12 | * @param context 上下文对象
13 | * @param oldPath assets目录中要拷贝的文件名
14 | * @param newPath 放到SD卡中的文件名
15 | */
16 | public static void CopyAssets(Context context, String oldPath, String newPath) {
17 | try {
18 | String fileNames[] = context.getAssets().list(oldPath);// 获取assets目录下的所有文件及目录名
19 | if (fileNames.length > 0) {// 如果是目录
20 | File file = new File(newPath);
21 | file.mkdirs();// 如果文件夹不存在,则递归
22 | for (String fileName : fileNames) {
23 | CopyAssets(context, oldPath + "/" + fileName, newPath + "/" + fileName);
24 | }
25 | } else {// 如果是文件
26 | InputStream is = context.getAssets().open(oldPath);
27 | FileOutputStream fos = new FileOutputStream(new File(newPath));
28 | byte[] buffer = new byte[1024];
29 | int byteCount = 0;
30 | while ((byteCount = is.read(buffer)) != -1) {// 循环从输入流读取
31 | // buffer字节
32 | fos.write(buffer, 0, byteCount);// 将读取的输入流写入到输出流
33 | }
34 | fos.flush();// 刷新缓冲区
35 | is.close();
36 | fos.close();
37 | }
38 | } catch (Exception e) {
39 | e.printStackTrace();
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/widget/FaceCameraView.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.widget;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageManager;
5 | import android.graphics.ImageFormat;
6 | import android.hardware.Camera;
7 | import android.util.AttributeSet;
8 | import android.util.DisplayMetrics;
9 | import android.view.SurfaceHolder;
10 | import android.view.SurfaceView;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * 自定义相机
16 | */
17 |
18 | public class FaceCameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {
19 | private Camera mCamera;//相机
20 | private boolean isSupportAutoFocus;//是否支持自动对焦
21 | private int screenHeight;//屏幕的高度
22 | private int screenWidth;//屏幕的宽度
23 | private boolean isPreviewing;//是否在预览
24 | private PreviewCallback previewCallback;//相机预览的回调
25 | public FaceCameraView(Context context) {
26 | super(context);
27 | init();
28 | }
29 |
30 | public FaceCameraView(Context context, AttributeSet attrs) {
31 | super(context, attrs);
32 | init();
33 | }
34 |
35 | public FaceCameraView(Context context, AttributeSet attrs, int defStyleAttr) {
36 | super(context, attrs, defStyleAttr);
37 | init();
38 | }
39 |
40 | private void init() {
41 | DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
42 | screenWidth = dm.heightPixels;
43 | screenHeight = dm.widthPixels;
44 | isSupportAutoFocus = getContext().getPackageManager().hasSystemFeature(
45 | PackageManager.FEATURE_CAMERA_AUTOFOCUS);
46 | getHolder().addCallback(this);
47 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
48 | }
49 |
50 | public void setPreviewCallback(PreviewCallback previewCallback) {
51 | this.previewCallback = previewCallback;
52 | }
53 |
54 | /**
55 | * Camera帧数据回调用
56 | */
57 | @Override
58 | public void onPreviewFrame(final byte[] data, final Camera camera) {
59 | camera.addCallbackBuffer(data);
60 | if(previewCallback!=null){
61 | previewCallback.onPreview(data,camera);
62 | }
63 | }
64 |
65 | /**
66 | * 摄像头自动聚焦
67 | */
68 | Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
69 | public void onAutoFocus(boolean success, Camera camera) {
70 | postDelayed(doAutoFocus, 500);
71 | }
72 | };
73 | private Runnable doAutoFocus = new Runnable() {
74 | public void run() {
75 | if (mCamera != null) {
76 | try {
77 | mCamera.autoFocus(autoFocusCB);
78 | } catch (Exception e) {
79 | }
80 | }
81 | }
82 | };
83 |
84 | /**
85 | * 打开指定摄像头
86 | */
87 | public void openCamera() {
88 | Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
89 | for (int cameraId = 0; cameraId < Camera.getNumberOfCameras(); cameraId++) {
90 | Camera.getCameraInfo(cameraId, cameraInfo);
91 | //打开前置摄像头
92 | if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
93 | try {
94 | mCamera = Camera.open(cameraId);
95 | } catch (Exception e) {
96 | if (mCamera != null) {
97 | mCamera.release();
98 | mCamera = null;
99 | }
100 | }
101 | break;
102 | }
103 | }
104 | }
105 |
106 | @Override
107 | public void surfaceCreated(SurfaceHolder holder) {
108 | try {
109 | releaseCamera();
110 | openCamera();
111 | } catch (Exception e) {
112 | mCamera = null;
113 | }
114 | }
115 |
116 | /**
117 | * 加载相机配置
118 | */
119 | private void initCamera() {
120 | try {
121 | mCamera.setPreviewDisplay(getHolder());//当前控件显示相机数据
122 | mCamera.setDisplayOrientation(90);//调整预览角度
123 | setCameraParameters();
124 | startPreview();//打开相机
125 | } catch (Exception e) {
126 | releaseCamera();
127 | }
128 | }
129 |
130 | /**
131 | * 配置相机参数
132 | */
133 | private void setCameraParameters() {
134 | Camera.Parameters parameters = mCamera.getParameters();
135 | List sizes = parameters.getSupportedPreviewSizes();
136 | //确定前面定义的预览宽高是camera支持的,不支持取就更大的
137 | for (int i = 0; i < sizes.size(); i++) {
138 | if ((sizes.get(i).width >= screenWidth && sizes.get(i).height >= screenHeight) || i == sizes.size() - 1) {
139 | screenWidth = sizes.get(i).width;
140 | screenHeight = sizes.get(i).height;
141 | break;
142 | }
143 | }
144 | //设置最终确定的预览大小
145 | parameters.setPreviewSize(screenWidth, screenHeight);
146 | mCamera.setParameters(parameters);
147 | }
148 |
149 | /**
150 | * 释放相机
151 | */
152 | private void releaseCamera() {
153 | if (mCamera != null) {
154 | stopPreview();
155 | mCamera.setPreviewCallback(null);
156 | mCamera.release();
157 | mCamera = null;
158 | }
159 | }
160 |
161 | /**
162 | * 停止预览
163 | */
164 | private void stopPreview() {
165 | if (mCamera != null && isPreviewing) {
166 | mCamera.stopPreview();
167 | isPreviewing = false;
168 | }
169 | }
170 |
171 | /**
172 | * 开始预览
173 | */
174 | public void startPreview() {
175 | if (mCamera != null) {
176 | mCamera.addCallbackBuffer(new byte[((screenWidth * screenHeight) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)) / 8]);
177 | mCamera.setPreviewCallbackWithBuffer(this);
178 | mCamera.startPreview();
179 | if (isSupportAutoFocus) {
180 | mCamera.autoFocus(autoFocusCB);
181 | }
182 | isPreviewing = true;
183 | }
184 | }
185 |
186 | @Override
187 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
188 | stopPreview();
189 | initCamera();
190 | }
191 |
192 | @Override
193 | public void surfaceDestroyed(SurfaceHolder holder) {
194 | releaseCamera();
195 | }
196 |
197 | public interface PreviewCallback {
198 | /**
199 | * 相机预览的回调接口
200 | * @param data
201 | * @param camera
202 | */
203 | void onPreview(final byte[] data, final Camera camera);
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/app/src/main/java/com/itfitness/seetaface2/widget/FaceRectView.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2.widget;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.RectF;
9 | import android.support.annotation.Nullable;
10 | import android.util.AttributeSet;
11 | import android.util.Log;
12 | import android.view.View;
13 |
14 | import com.seeta.sdk.SeetaRect;
15 |
16 | /**
17 | * 用于绘制识别出来的人脸区域
18 | */
19 | public class FaceRectView extends View {
20 | private Paint mPaint;
21 | private SeetaRect[] faceRects;
22 |
23 | public FaceRectView(Context context) {
24 | this(context, null);
25 | }
26 |
27 | public FaceRectView(Context context, @Nullable AttributeSet attrs) {
28 | this(context, attrs, 0);
29 | }
30 |
31 | public FaceRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
32 | super(context, attrs, defStyleAttr);
33 | init();
34 | }
35 |
36 | private void init() {
37 | //初始化画笔
38 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
39 | mPaint.setColor(Color.GREEN);//绿色画笔
40 | mPaint.setStyle(Paint.Style.STROKE);
41 | mPaint.setStrokeWidth(5);
42 | }
43 |
44 | @Override
45 | protected void onDraw(Canvas canvas) {
46 | super.onDraw(canvas);
47 | Log.e("绘制","非空");
48 | if (faceRects!=null && faceRects.length > 0) {
49 | Log.e("绘制","非空");
50 | for (SeetaRect faceRect : faceRects) {
51 | Log.e("绘制",faceRect.x+"===="+faceRect.y+"====="+faceRect.width+"====="+faceRect.height);
52 | canvas.drawRect(new RectF(faceRect.x, faceRect.y, faceRect.x + faceRect.width, faceRect.y + faceRect.height), mPaint);
53 | }
54 | }else {
55 | Log.e("绘制","空");
56 | }
57 | }
58 |
59 | /**
60 | * 设置人脸数据
61 | *
62 | * @param faceRects
63 | */
64 | public void setFaceDatas(SeetaRect[] faceRects) {
65 | Log.e("设置",faceRects[0].x+"===="+faceRects[0].y+"====="+faceRects[0].width+"====="+faceRects[0].height);
66 | this.faceRects = faceRects;
67 | invalidate();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/heying.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/heying.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seetaface.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/seetaface.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang01.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang02.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang03.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang04.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang05.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang06.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang07.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang07.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang08.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang08.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang09.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tang10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/drawable/tang10.jpg
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_facedetector.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_facefind.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_facelogin.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_facerecognizer.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
19 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
17 |
22 |
27 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_pointdetector.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Seetaface2
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/test/java/com/itfitness/seetaface2/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.itfitness.seetaface2;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.4.1'
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | jcenter()
21 |
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 |
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/myml666/Seetaface2/f56847e73e8cc1e430e6d641dcf7191078c8f70c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 26 09:29:04 CST 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-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/seetalibrary/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/seetalibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion "29.0.1"
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 15
10 | targetSdkVersion 28
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 |
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: 'libs', include: ['*.jar'])
29 |
30 | implementation 'com.android.support:appcompat-v7:28.0.0'
31 | testImplementation 'junit:junit:4.12'
32 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
34 | }
35 |
--------------------------------------------------------------------------------
/seetalibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/seetalibrary/src/androidTest/java/com/seeta/sdk/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
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 | * Instrumented 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() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.seeta.sdk.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/java/com/seeta/sdk/FaceDetector2.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 |
4 | public class FaceDetector2
5 | {
6 | static {
7 | System.loadLibrary("FaceDetectorJni");
8 | }
9 |
10 | public long impl = 0;
11 |
12 | private native void construct(String model);
13 | public native void dispose();
14 |
15 | /**
16 | * \brief construct an facedetector
17 | * \param model model path
18 | */
19 | public FaceDetector2(String model) {
20 | this.construct(model);
21 | }
22 |
23 |
24 | protected void finalize() throws Throwable {
25 | super.finalize();
26 | this.dispose();
27 | }
28 |
29 | /**
30 | * \brief detect faces
31 | * \param image [in]
32 | * \return an array of rectangle, contains each faces location
33 | * \note return 0 length array if no face detected
34 | * \note faces were sorted by width * length
35 | */
36 | public native SeetaRect[] Detect(SeetaImageData img);
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/java/com/seeta/sdk/FaceRecognizer2.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 |
4 | public class FaceRecognizer2
5 | {
6 | static {
7 | System.loadLibrary("FaceRecognizerJni");
8 | }
9 |
10 | public long impl = 0;
11 |
12 | private native void construct(String model);
13 | public native void dispose();
14 |
15 | public FaceRecognizer2() {
16 | this("");
17 | }
18 |
19 | /**
20 | * \brief construct an facerecognizer
21 | * \param model model path
22 | */
23 | public FaceRecognizer2(String model) {
24 | this.construct(model);
25 | }
26 |
27 | protected void finalize() throws Throwable {
28 | super.finalize();
29 | this.dispose();
30 | }
31 |
32 | /**
33 | * \brief return similarity of two faces
34 | * \param image1 [in] the original image of face1
35 | * \param landmarks1 [in] the detected landmarks of face1
36 | * \param image2 [in] the original image of face2
37 | * \param landmarks2 [in] the detected landmarks of face2
38 | * \return return similarity of face1 and face2
39 | * \note the detected landmarks must have number of PointDetector2::LandmarkNum
40 | * \note return 0 if failed
41 | */
42 | public native float Compare(SeetaImageData image1, SeetaPointF[] landmarks1,
43 | SeetaImageData image2, SeetaPointF[] landmarks2);
44 |
45 | /**
46 | * \brief register faces to database, return the index of registered face
47 | * \param image [in] the original image of face
48 | * \param landmarks [in] the detected landmarks of face
49 | * \return index of registered face
50 | * \note the detected landmarks must have number of PointDetector2::LandmarkNum
51 | * \note return -1 if faild.
52 | */
53 | public native int Register(SeetaImageData image, SeetaPointF[] landmarks);
54 |
55 | /**
56 | * \brief clear all registered face
57 | */
58 | public native void Clear();
59 |
60 | /**
61 | * \brief get the number of registerd faces
62 | * \return the number of registerd faces
63 | */
64 | public native int MaxRegisterIndex();
65 |
66 | /**
67 | * \brief recognize the given face from database, return the most similar face's index
68 | * \param image [in] the original image of face
69 | * \param landmarks [in] the detected landmarks of face
70 | * \param similarity [out] the most similarity , note similarity must be one length array of float
71 | * \return the most similar face's index
72 | * \note return -1 if faild.
73 | * \sa Register
74 | */
75 | public native int Recognize(SeetaImageData image, SeetaPointF[] landmarks, float[] similarity);
76 |
77 | /**
78 | * \brief recognize the given face from database, return each similarity of database
79 | * \param image [in] the original image of face
80 | * \param landmarks [in] the detected landmarks of face
81 | * \return an array of similarity, with length MaxRegisterIndex
82 | * \note using index returned by Register to get exact face's similarity
83 | * \sa Register
84 | * \sa MaxRegisterIndex
85 | */
86 | public native float[] RecognizeEx(SeetaImageData image, SeetaPointF[] landmarks);
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/java/com/seeta/sdk/PointDetector2.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 | public class PointDetector2
4 | {
5 | static {
6 | System.loadLibrary("PointDetectorJni");
7 | }
8 | public long impl = 0;
9 |
10 | private native void construct(String model);
11 | public native void dispose();
12 |
13 | /**
14 | * \brief construct an pointdetector
15 | * \param model model path
16 | */
17 | public PointDetector2(String model) {
18 | this.construct(model);
19 | }
20 |
21 | protected void finalize() throws Throwable {
22 | super.finalize();
23 | this.dispose();
24 | }
25 |
26 | /**
27 | * \brief get number of landmarks can be detected
28 | * \return number of landmarks can be detected
29 | */
30 | public native int LandmarkNum();
31 |
32 | /**
33 | * \brief detect points on face
34 | * \param image [in] the orignal image
35 | * \param face [in] detected face location
36 | * \return an array of points, contains each point location, with length of LandmarkNum
37 | * \sa LandmarkNum
38 | */
39 | public native SeetaPointF[] Detect(SeetaImageData image, SeetaRect face);
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/java/com/seeta/sdk/SeetaImageData.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 | public class SeetaImageData
4 | {
5 | public SeetaImageData(int width, int height, int channels) {
6 | this.data = new byte[width * height * channels];
7 | this.width = width;
8 | this.height = height;
9 | this.channels = channels;
10 | }
11 |
12 | public SeetaImageData(int width, int height) {
13 | this(width, height, 1);
14 | }
15 |
16 | public byte[] data;
17 | public int width;
18 | public int height;
19 | public int channels;
20 | }
21 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/java/com/seeta/sdk/SeetaPointF.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 | public class SeetaPointF
4 | {
5 | public double x;
6 | public double y;
7 | }
8 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/java/com/seeta/sdk/SeetaRect.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 | public class SeetaRect
4 | {
5 | public int x;
6 | public int y;
7 | public int width;
8 | public int height;
9 | }
10 |
--------------------------------------------------------------------------------
/seetalibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SeetaLibrary
3 |
4 |
--------------------------------------------------------------------------------
/seetalibrary/src/test/java/com/seeta/sdk/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.seeta.sdk;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':seetalibrary'
2 |
--------------------------------------------------------------------------------