Skip to content

Commit 9045e43

Browse files
authored
facedb and debug info (#70)
* Small bug in identifying faces when enrolling * Sort out debug logging and add a face ID count to dump
1 parent 7d29e36 commit 9045e43

File tree

4 files changed

+109
-83
lines changed

4 files changed

+109
-83
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ myconfig.h
44
.clang_complete
55
.gcc-flags.json
66
.pio
7+
.vscode

app_httpd.cpp

Lines changed: 80 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@
2626
#include "src/logo.h"
2727
#include "storage.h"
2828

29-
//#define DEBUG_STREAM_DATA // Debug: dump info for each stream frame on serial port
30-
3129
// Functions from the main .ino
3230
extern void flashLED(int flashtime);
3331
extern void setLamp(int newVal);
3432

35-
// External variables declared in main .ino
33+
// External variables declared in the main .ino
3634
extern char myName[];
3735
extern char myVer[];
3836
extern IPAddress ip;
@@ -51,6 +49,7 @@ extern int lampVal;
5149
extern int8_t detection_enabled;
5250
extern int8_t recognition_enabled;
5351
extern bool filesystem;
52+
extern bool debugData;
5453
extern int sketchSize;
5554
extern int sketchSpace;
5655
extern String sketchMD5;
@@ -96,6 +95,7 @@ httpd_handle_t camera_httpd = NULL;
9695
static mtmn_config_t mtmn_config = {0};
9796
static int8_t is_enrolling = 0;
9897
static face_id_list id_list = {0};
98+
int id_list_alloc = 0;
9999

100100
static ra_filter_t * ra_filter_init(ra_filter_t * filter, size_t sample_size){
101101
memset(filter, 0, sizeof(ra_filter_t));
@@ -110,22 +110,20 @@ static ra_filter_t * ra_filter_init(ra_filter_t * filter, size_t sample_size){
110110
return filter;
111111
}
112112

113-
#if defined(DEBUG_STREAM_DATA)
114-
static int ra_filter_run(ra_filter_t * filter, int value) {
115-
if(!filter->values){
116-
return value;
117-
}
118-
filter->sum -= filter->values[filter->index];
119-
filter->values[filter->index] = value;
120-
filter->sum += filter->values[filter->index];
121-
filter->index++;
122-
filter->index = filter->index % filter->size;
123-
if (filter->count < filter->size) {
124-
filter->count++;
125-
}
126-
return filter->sum / filter->count;
127-
}
128-
#endif
113+
static int ra_filter_run(ra_filter_t * filter, int value) {
114+
if(!filter->values){
115+
return value;
116+
}
117+
filter->sum -= filter->values[filter->index];
118+
filter->values[filter->index] = value;
119+
filter->sum += filter->values[filter->index];
120+
filter->index++;
121+
filter->index = filter->index % filter->size;
122+
if (filter->count < filter->size) {
123+
filter->count++;
124+
}
125+
return filter->sum / filter->count;
126+
}
129127

130128
static void rgb_print(dl_matrix3du_t *image_matrix, uint32_t color, const char * str){
131129
fb_data_t fb;
@@ -209,16 +207,17 @@ static int run_face_recognition(dl_matrix3du_t *image_matrix, box_array_t *net_b
209207
}
210208
if (align_face(net_boxes, image_matrix, aligned_face) == ESP_OK){
211209
if (is_enrolling == 1){
210+
int8_t this_face = id_list.tail;
212211
int8_t left_sample_face = enroll_face(&id_list, aligned_face);
213212

214213
if(left_sample_face == (ENROLL_CONFIRM_TIMES - 1)){
215-
Serial.printf("Enrolling Face ID: %d\n", id_list.tail);
214+
Serial.printf("Enrolling Face ID: %d\n", this_face);
216215
}
217-
Serial.printf("Enrolling Face ID: %d sample %d\n", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
218-
rgb_printf(image_matrix, FACE_COLOR_CYAN, "ID[%u] Sample[%u]", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
216+
Serial.printf("Enrolling Face ID: %d sample %d\n", this_face, ENROLL_CONFIRM_TIMES - left_sample_face);
217+
rgb_printf(image_matrix, FACE_COLOR_CYAN, "ID[%u] Sample[%u]", this_face, ENROLL_CONFIRM_TIMES - left_sample_face);
219218
if (left_sample_face == 0){
220219
is_enrolling = 0;
221-
Serial.printf("Enrolled Face ID: %d\n", id_list.tail);
220+
Serial.printf("Enrolled Face ID: %d\n", this_face);
222221
}
223222
} else {
224223
matched_id = recognize_face(&id_list, aligned_face);
@@ -255,7 +254,9 @@ static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size
255254
static esp_err_t capture_handler(httpd_req_t *req){
256255
camera_fb_t * fb = NULL;
257256
esp_err_t res = ESP_OK;
258-
257+
258+
Serial.println("Capture Requested");
259+
259260
flashLED(75); // little flash of status LED
260261

261262
int64_t fr_start = esp_timer_get_time();
@@ -338,7 +339,9 @@ static esp_err_t capture_handler(httpd_req_t *req){
338339
}
339340

340341
int64_t fr_end = esp_timer_get_time();
341-
Serial.printf("FACE: %uB %ums %s%d\n", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start)/1000), detected?"DETECTED ":"", face_id);
342+
if (debugData) {
343+
Serial.printf("FACE: %uB %ums %s%d\n", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start)/1000), detected?"DETECTED ":"", face_id);
344+
}
342345
return res;
343346
}
344347

@@ -350,16 +353,15 @@ static esp_err_t stream_handler(httpd_req_t *req){
350353
char * part_buf[64];
351354
dl_matrix3du_t *image_matrix = NULL;
352355
int face_id = 0;
353-
#if defined(DEBUG_STREAM_DATA)
354-
bool detected = false;
355-
int64_t fr_start = 0;
356-
int64_t fr_face = 0;
357-
int64_t fr_recognize = 0;
358-
int64_t fr_encode = 0;
359-
int64_t fr_ready = 0;
360-
#endif
356+
bool detected = false;
357+
int64_t fr_start = 0;
358+
int64_t fr_face = 0;
359+
int64_t fr_recognize = 0;
360+
int64_t fr_encode = 0;
361+
int64_t fr_ready = 0;
361362

362-
Serial.println("Stream started");
363+
364+
Serial.println("Stream requested");
363365

364366
flashLED(75); // double flash of status LED
365367
delay(75);
@@ -378,22 +380,18 @@ static esp_err_t stream_handler(httpd_req_t *req){
378380
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
379381

380382
while(true){
381-
#if defined (DEBUG_STREAM_DATA)
382-
detected = false;
383-
#endif
383+
detected = false;
384384
face_id = 0;
385385
fb = esp_camera_fb_get();
386386
if (!fb) {
387387
Serial.println("Camera capture failed");
388388
res = ESP_FAIL;
389389
} else {
390-
#if defined(DEBUG_STREAM_DATA)
391-
fr_start = esp_timer_get_time();
392-
fr_ready = fr_start;
393-
fr_face = fr_start;
394-
fr_encode = fr_start;
395-
fr_recognize = fr_start;
396-
#endif
390+
fr_start = esp_timer_get_time();
391+
fr_ready = fr_start;
392+
fr_face = fr_start;
393+
fr_encode = fr_start;
394+
fr_recognize = fr_start;
397395
if(!detection_enabled || fb->width > 400){
398396
if(fb->format != PIXFORMAT_JPEG){
399397
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
@@ -419,28 +417,20 @@ static esp_err_t stream_handler(httpd_req_t *req){
419417
Serial.println("fmt2rgb888 failed");
420418
res = ESP_FAIL;
421419
} else {
422-
#if defined(DEBUG_STREAM_DATA)
423-
fr_ready = esp_timer_get_time();
424-
#endif
420+
fr_ready = esp_timer_get_time();
425421
box_array_t *net_boxes = NULL;
426422
if(detection_enabled){
427423
net_boxes = face_detect(image_matrix, &mtmn_config);
428424
}
429-
#if defined(DEBUG_STREAM_DATA)
430-
fr_face = esp_timer_get_time();
431-
fr_recognize = fr_face;
432-
#endif
425+
fr_face = esp_timer_get_time();
426+
fr_recognize = fr_face;
433427
if (net_boxes || fb->format != PIXFORMAT_JPEG){
434428
if(net_boxes){
435-
#if defined(DEBUG_STREAM_DATA)
436-
detected = true;
437-
#endif
429+
detected = true;
438430
if(recognition_enabled){
439431
face_id = run_face_recognition(image_matrix, net_boxes);
440432
}
441-
#if defined(DEBUG_STREAM_DATA)
442-
fr_recognize = esp_timer_get_time();
443-
#endif
433+
fr_recognize = esp_timer_get_time();
444434
draw_face_boxes(image_matrix, net_boxes, face_id);
445435
free(net_boxes->score);
446436
free(net_boxes->box);
@@ -457,9 +447,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
457447
_jpg_buf = fb->buf;
458448
_jpg_buf_len = fb->len;
459449
}
460-
#if defined(DEBUG_STREAM_DATA)
461-
fr_encode = esp_timer_get_time();
462-
#endif
450+
fr_encode = esp_timer_get_time();
463451
}
464452
dl_matrix3du_free(image_matrix);
465453
}
@@ -487,25 +475,25 @@ static esp_err_t stream_handler(httpd_req_t *req){
487475
break;
488476
}
489477

490-
#ifdef DEBUG_STREAM_DATA
491-
int64_t fr_end = esp_timer_get_time();
492-
int64_t ready_time = (fr_ready - fr_start)/1000;
493-
int64_t face_time = (fr_face - fr_ready)/1000;
494-
int64_t recognize_time = (fr_recognize - fr_face)/1000;
495-
int64_t encode_time = (fr_encode - fr_recognize)/1000;
496-
int64_t process_time = (fr_encode - fr_start)/1000;
497-
int64_t frame_time = fr_end - last_frame;
498-
last_frame = fr_end;
499-
frame_time /= 1000;
500-
uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
501-
Serial.printf("MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps), %u+%u+%u+%u=%u %s%d\n",
502-
(uint32_t)(_jpg_buf_len),
503-
(uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
504-
avg_frame_time, 1000.0 / avg_frame_time,
505-
(uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time,
506-
(detected)?"DETECTED ":"", face_id
507-
);
508-
#endif
478+
int64_t fr_end = esp_timer_get_time();
479+
int64_t ready_time = (fr_ready - fr_start)/1000;
480+
int64_t face_time = (fr_face - fr_ready)/1000;
481+
int64_t recognize_time = (fr_recognize - fr_face)/1000;
482+
int64_t encode_time = (fr_encode - fr_recognize)/1000;
483+
int64_t process_time = (fr_encode - fr_start)/1000;
484+
int64_t frame_time = fr_end - last_frame;
485+
last_frame = fr_end;
486+
frame_time /= 1000;
487+
uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
488+
if (debugData) {
489+
Serial.printf("MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps), %u+%u+%u+%u=%u %s%d\n",
490+
(uint32_t)(_jpg_buf_len),
491+
(uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
492+
avg_frame_time, 1000.0 / avg_frame_time,
493+
(uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time,
494+
(detected)?"DETECTED ":"", face_id
495+
);
496+
}
509497
}
510498

511499
last_frame = 0;
@@ -794,9 +782,9 @@ static esp_err_t dump_handler(httpd_req_t *req){
794782
d+= sprintf(d,"Spiffs: %i, used: %i<br>\n", SPIFFS.totalBytes(), SPIFFS.usedBytes());
795783
Serial.printf("Spiffs: %i, used: %i\n", SPIFFS.totalBytes(), SPIFFS.usedBytes());
796784
}
797-
// Following is debug while implementing FaceDB dump
798-
// d+= sprintf(d,"mtmn_config size: %u<br>ra_filter size: %u<br>id_list %u<br>\n", sizeof(mtmn_config), sizeof(ra_filter), sizeof(id_list));
799-
// Serial.printf("mtmn_config size: %u<br>ra_filter size: %u<br>id_list %u\n", sizeof(mtmn_config), sizeof(ra_filter), sizeof(id_list));
785+
d+= sprintf(d,"Enrolled faces: %i (max %i)<br>\n", id_list.count, id_list.size);
786+
Serial.printf("Enrolled faces: %i (max %i)\n", id_list.count, id_list.size);
787+
800788
// Footer
801789
d+= sprintf(d,"<br><div class=\"input-group\">\n");
802790
d+= sprintf(d,"<button title=\"Refresh this page\" onclick=\"location.replace(document.URL)\">Refresh</button>\n");
@@ -977,7 +965,10 @@ void startCameraServer(int hPort, int sPort){
977965
.user_ctx = NULL
978966
};
979967

968+
// Filter list; used during face detection
980969
ra_filter_init(&ra_filter, 20);
970+
971+
// Mtmn config values (face detection and recognition parameters)
981972
mtmn_config.type = FAST;
982973
mtmn_config.min_face = 80;
983974
mtmn_config.pyramid = 0.707;
@@ -991,7 +982,14 @@ void startCameraServer(int hPort, int sPort){
991982
mtmn_config.o_threshold.score = 0.7;
992983
mtmn_config.o_threshold.nms = 0.7;
993984
mtmn_config.o_threshold.candidate_number = 1;
985+
986+
// Face ID list (settings + pointer to the data allocation)
994987
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
988+
// The size of the allocated data block; calculated in dl_lib_calloc()
989+
id_list_alloc = FACE_ID_SAVE_NUMBER * sizeof(dl_matrix3d_t *) + sizeof(void *);
990+
Serial.print("FACE DB SIZE: ");
991+
Serial.println(id_list_alloc);
992+
Serial.printf("FACE DB POINTER: %p\n", id_list.id_list);
995993

996994
config.server_port = hPort;
997995
config.ctrl_port = hPort;

esp32-cam-webserver.ino

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ const int pwmMax = pow(2,pwmresolution)-1;
161161
int8_t recognition_enabled = 0;
162162
#endif
163163

164+
// Debug Data for stream and capture
165+
#if defined(DEBUG_DEFAULT_ON)
166+
bool debugData = true;
167+
#else
168+
bool debugData = false;
169+
#endif
170+
164171
// Notification LED
165172
void flashLED(int flashtime) {
166173
#ifdef LED_PIN // If we have it; flash it.
@@ -537,6 +544,9 @@ void setup() {
537544
Serial.printf("Stream viewer available at '%sview'\n", streamURL);
538545
Serial.printf("Raw stream URL is '%s'\n", streamURL);
539546

547+
if (debugData) Serial.println("Camera debug data is enabled (send any char to disable)");
548+
else Serial.println("Camera debug data is disabled (send any char to enable)");
549+
540550
// Used when dumping status; these are slow functions, so just do them once during startup
541551
sketchSize = ESP.getSketchSize();
542552
sketchSpace = ESP.getFreeSketchSpace();
@@ -566,7 +576,22 @@ void loop() {
566576
Serial.println("WiFi reconnected");
567577
warned = false;
568578
}
569-
delay(WIFI_WATCHDOG);
579+
// loop here for WIFI_WATCHDOG, turning debugData true/false depending on serial input..
580+
unsigned long start = millis();
581+
while (millis() - start < WIFI_WATCHDOG ) {
582+
delay(100);
583+
if (Serial.available()) {
584+
// Toggle debug output on serial input
585+
if (debugData) {
586+
debugData = false;
587+
Serial.println("Camera debug data is disabled (send any char to enable)");
588+
} else {
589+
debugData = true;
590+
Serial.println("Camera debug data is enabled (send any char to disable)");
591+
}
592+
}
593+
while (Serial.available()) Serial.read(); // chomp the buffer
594+
}
570595
} else {
571596
// disconnected; attempt to reconnect
572597
if (!warned) {

myconfig.sample.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ struct station {
135135
// #define FACE_DETECTION
136136
// #define FACE_RECOGNITION
137137

138+
// Uncomment to enable camera debug info on serial by default
139+
// DEBUG_DEFAULT_ON
138140

139141
/*
140142
* Camera Hardware Selectiom

0 commit comments

Comments
 (0)