1
1
#include < jni.h>
2
2
#include < string>
3
+ #include < dirent.h>
4
+ #include < unordered_map>
3
5
#include < android/log.h>
4
6
#include < android/bitmap.h>
7
+ #include < dlib/image_io.h>
5
8
6
9
#include < dlib/dnn.h>
7
10
#include < dlib/image_processing/frontal_face_detector.h>
@@ -15,6 +18,47 @@ using namespace dlib;
15
18
#define LOGI (...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
16
19
#define LOGE (...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
17
20
21
+
22
+ template <template <int ,template <typename >class ,int ,typename > class block , int N, template <typename >class BN , typename SUBNET>
23
+ using residual = dlib::add_prev1<block<N,BN,1 ,dlib::tag1<SUBNET>>>;
24
+
25
+ template <template <int ,template <typename >class ,int ,typename > class block , int N, template <typename >class BN , typename SUBNET>
26
+ using residual_down = dlib::add_prev2<dlib::avg_pool<2 ,2 ,2 ,2 ,dlib::skip1<dlib::tag2<block<N,BN,2 ,dlib::tag1<SUBNET>>>>>>;
27
+
28
+ template <int N, template <typename > class BN , int stride, typename SUBNET>
29
+ using block = BN<dlib::con<N,3 ,3 ,1 ,1 ,dlib::relu<BN<dlib::con<N,3 ,3 ,stride,stride,SUBNET>>>>>;
30
+
31
+ template <int N, typename SUBNET> using ares = dlib::relu<residual<block,N,dlib::affine,SUBNET>>;
32
+ template <int N, typename SUBNET> using ares_down = dlib::relu<residual_down<block,N,dlib::affine,SUBNET>>;
33
+
34
+ template <typename SUBNET> using alevel0 = ares_down<256 ,SUBNET>;
35
+ template <typename SUBNET> using alevel1 = ares<256 ,ares<256 ,ares_down<256 ,SUBNET>>>;
36
+ template <typename SUBNET> using alevel2 = ares<128 ,ares<128 ,ares_down<128 ,SUBNET>>>;
37
+ template <typename SUBNET> using alevel3 = ares<64 ,ares<64 ,ares<64 ,ares_down<64 ,SUBNET>>>>;
38
+ template <typename SUBNET> using alevel4 = ares<32 ,ares<32 ,ares<32 ,SUBNET>>>;
39
+
40
+ using anet_type = dlib::loss_metric<dlib::fc_no_bias<128 , dlib::avg_pool_everything<
41
+ alevel0<
42
+ alevel1<
43
+ alevel2<
44
+ alevel3<
45
+ alevel4<
46
+ dlib::max_pool<3 ,3 ,2 ,2 ,dlib::relu<dlib::affine<dlib::con<32 ,7 ,7 ,2 ,2 ,
47
+ dlib::input_rgb_image_sized<150 >
48
+ >>>>>>>>>>>>;
49
+
50
+ dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();
51
+ dlib::shape_predictor sp;
52
+ anet_type net;
53
+
54
+ // std::vector<matrix<float, 0, 1>> known_faces;
55
+
56
+ std::unordered_map<std::string, matrix<float , 0 , 1 >> known_faces;
57
+
58
+ typedef matrix<float , 0 , 1 > sample_type;
59
+ typedef linear_kernel<sample_type> lin_kernel;
60
+ multiclass_linear_decision_function<lin_kernel, string> df;
61
+
18
62
typedef struct
19
63
{
20
64
uint8_t alpha;
@@ -23,51 +67,144 @@ typedef struct
23
67
uint8_t blue;
24
68
} argb;
25
69
70
+
71
+
26
72
extern " C"
27
- JNIEXPORT jstring JNICALL
28
- Java_com_google_android_gms_samples_vision_face_facetracker_CustomDetector_test (JNIEnv *env,
29
- jobject instance,
30
- jobject bmp) {
31
- AndroidBitmapInfo infocolor;
32
- void * pixelscolor;
33
- int y;
34
- int x;
35
- int ret;
36
- if ((ret = AndroidBitmap_getInfo (env, bmp, &infocolor)) < 0 ) {
37
- LOGE (" AndroidBitmap_getInfo() failed ! error=%d" , ret);
38
- return env->NewStringUTF (" Image broken" );
39
- }
40
- LOGI (" color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d" ,
41
- infocolor.width ,infocolor.height ,infocolor.stride ,infocolor.format ,infocolor.flags );
73
+ {
74
+ JNIEXPORT jstring JNICALL
75
+ Java_com_google_android_gms_samples_vision_face_facetracker_CustomDetector_test (JNIEnv *env,
76
+ jobject instance,
77
+ jobject bmp) {
78
+ AndroidBitmapInfo infocolor;
79
+ void *pixelscolor;
80
+ int y;
81
+ int x;
82
+ int ret;
83
+ array2d<rgb_pixel> img;
84
+ if ((ret = AndroidBitmap_getInfo (env, bmp, &infocolor)) < 0 ) {
85
+ LOGE (" AndroidBitmap_getInfo() failed ! error=%d" , ret);
86
+ return env->NewStringUTF (" Image broken" );
87
+ }
88
+ LOGI (" color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d" ,
89
+ infocolor.width , infocolor.height , infocolor.stride , infocolor.format , infocolor.flags );
42
90
43
- if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
44
- LOGE (" Bitmap format is not RGBA_8888 !" );
45
- return env->NewStringUTF (" Image broken 2" );
46
- }
91
+ if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
92
+ LOGE (" Bitmap format is not RGBA_8888 !" );
93
+ return env->NewStringUTF (" Image broken 2" );
94
+ }
47
95
48
- if ((ret = AndroidBitmap_lockPixels (env, bmp, &pixelscolor)) < 0 ) {
49
- LOGE (" AndroidBitmap_lockPixels() failed ! error=%d" , ret);
50
- }
96
+ if ((ret = AndroidBitmap_lockPixels (env, bmp, &pixelscolor)) < 0 ) {
97
+ LOGE (" AndroidBitmap_lockPixels() failed ! error=%d" , ret);
98
+ }
99
+
100
+ img.set_size (infocolor.height , infocolor.width );
101
+ for (y = 0 ; y < infocolor.height ; y++) { // todo: performance
102
+ argb *line = (argb *) pixelscolor;
103
+ for (x = 0 ; x < infocolor.width ; ++x) {
104
+ rgb_pixel p (line[x].red , line[x].green , line[x].blue );
105
+ img[y][x] = p;
106
+ }
107
+ pixelscolor = (char *) pixelscolor + infocolor.stride ;
108
+ }
109
+
110
+ // todo: smth wrong with colors
111
+ // dlib::save_bmp(img, "/storage/emulated/0/Movies/test2.bmp");
112
+
113
+ std::vector<dlib::rectangle> dets = detector (img);
114
+ LOGI (" detected size %d" , dets.size ());
115
+
116
+ if (dets.size () > 0 ){
117
+ auto face = dets.front ();
118
+ std::vector<matrix<rgb_pixel>> faces;
119
+ int x = face.left ();
120
+ int y = face.top ();
121
+ int width = face.width ();
122
+ int height = face.height ();
123
+
124
+ auto shape = sp (img, face);
125
+ matrix<rgb_pixel> face_chip;
126
+ extract_image_chip (img, get_face_chip_details (shape, 150 , 0.25 ), face_chip);
127
+ faces.push_back (move (face_chip));
51
128
52
- for (y=0 ;y<infocolor.height ;y++) {
53
- argb * line = (argb *) pixelscolor;
54
- pixelscolor = (char *)pixelscolor + infocolor.stride ;
129
+ std::vector<matrix<float , 0 , 1 >> face_descriptors = net (faces);
130
+
131
+ if (face_descriptors.size () > 0 )
132
+ {
133
+ matrix<float , 0 , 1 > face_desc = face_descriptors[0 ];
134
+ LOGI (" recognized" );
135
+ for (auto & i : known_faces) {
136
+ if ( length (face_desc - i.second ) < 0.5 ) // todo: extrace thresh
137
+ {
138
+ return env->NewStringUTF (i.first .c_str ());
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ LOGI (" unlocking pixels" );
145
+ AndroidBitmap_unlockPixels (env, bmp);
146
+
147
+ const char *returnValue = " Unknown" ;
148
+ return env->NewStringUTF (returnValue);
55
149
}
150
+ }
56
151
57
- // array2d<rgb_pixel> img;
58
- // img.set_size(infocolor.height, infocolor.width);
59
- // for (int y = 0; y < infocolor.height; y++){
60
- // for (int x = 0; x < infocolor.width; x++){
61
- // img[y][x] = pixelscolor[y * infocolor.width + x];
62
- // }
63
- // }
152
+ extern " C"
153
+ JNIEXPORT jint JNICALL
154
+ Java_com_google_android_gms_samples_vision_face_facetracker_FaceTrackerActivity_loadResources (
155
+ JNIEnv *env, jobject instance)
156
+ {
157
+
158
+ LOGI (" load resource" );
159
+ FILE *file1 = fopen (" /storage/emulated/0/Download/shape_predictor_5_face_landmarks.dat" , " r+" );
160
+ FILE *file2 = fopen (" /storage/emulated/0/Download/dlib_face_recognition_resnet_model_v1.dat" ,
161
+ " r+" );
162
+ FILE *file3 = fopen (" /storage/emulated/0/Download/faces_linear.svm" , " r+" );
64
163
164
+ if (file1 != NULL && file2 != NULL && file3 != NULL ) {
165
+ fclose (file1);
166
+ fclose (file2);
167
+ fclose (file3);
168
+ dlib::deserialize (" /storage/emulated/0/Download/shape_predictor_5_face_landmarks.dat" )
169
+ >> sp;
170
+ dlib::deserialize (" /storage/emulated/0/Download/dlib_face_recognition_resnet_model_v1.dat" )
171
+ >> net;
172
+ dlib::deserialize (" /storage/emulated/0/Download/faces_linear.svm" ) >> df;
65
173
66
- LOGI (" unlocking pixels" );
67
- AndroidBitmap_unlockPixels (env, bmp);
174
+ DIR *d;
175
+ char *p1,*p2;
176
+ int ret;
177
+ struct dirent *dir;
178
+ d = opendir (" /storage/emulated/0/Download" );
179
+ if (d)
180
+ {
181
+ LOGI (" Loading feature vectors using *.vec" , p1);
182
+ while ((dir = readdir (d)) != NULL )
183
+ {
184
+ p1=strtok (dir->d_name ," ." );
185
+ p2=strtok (NULL ," ." );
186
+ if (p2!=NULL )
187
+ {
188
+ ret=strcmp (p2," vec" );
189
+ if (ret==0 )
190
+ {
191
+ std::string name = std::string (p1);
192
+ std::string file = name + " .vec" ;
193
+ matrix<float , 0 , 1 > face_vector;
194
+ dlib::deserialize (" /storage/emulated/0/Download/" + file) >> face_vector;
195
+ known_faces.insert ({name, face_vector});
68
196
197
+ // printf("%s\t",p1);
198
+ // LOGI("item %s", p1);
199
+ }
200
+ }
69
201
202
+ }
203
+ closedir (d);
204
+ }
205
+ } else {
206
+ return 1 ; // failed
207
+ }
70
208
71
- const char *returnValue = " test" ;
72
- return env->NewStringUTF (returnValue);
209
+ return 0 ;
73
210
}
0 commit comments