Advertisement
safwan092

FaceDoorEntryESP32Cam

Feb 2nd, 2023
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.27 KB | None | 0 0
  1. #include <ArduinoWebsockets.h>
  2. #include "esp_http_server.h"
  3. #include "esp_timer.h"
  4. #include "esp_camera.h"
  5. #include "camera_index.h"
  6. #include "Arduino.h"
  7. #include "fd_forward.h"
  8. #include "fr_forward.h"
  9. #include "fr_flash.h"
  10.  
  11. const char* ssid = "network";
  12. const char* password = "123456789";
  13.  
  14. #define ENROLL_CONFIRM_TIMES 5
  15. #define FACE_ID_SAVE_NUMBER 7
  16.  
  17. // Select camera model
  18. //#define CAMERA_MODEL_WROVER_KIT
  19. //#define CAMERA_MODEL_ESP_EYE
  20. //#define CAMERA_MODEL_M5STACK_PSRAM
  21. //#define CAMERA_MODEL_M5STACK_WIDE
  22. #define CAMERA_MODEL_AI_THINKER
  23. #include "camera_pins.h"
  24.  
  25. using namespace websockets;
  26. WebsocketsServer socket_server;
  27.  
  28. camera_fb_t * fb = NULL;
  29.  
  30. long current_millis;
  31. long last_detected_millis = 0;
  32.  
  33. #define relay_pin 2 // pin 12 can also be used
  34. unsigned long door_opened_millis = 0;
  35. long interval = 5000; // open lock for ... milliseconds
  36. bool face_recognised = false;
  37.  
  38. void app_facenet_main();
  39. void app_httpserver_init();
  40.  
  41. typedef struct
  42. {
  43. uint8_t *image;
  44. box_array_t *net_boxes;
  45. dl_matrix3d_t *face_id;
  46. } http_img_process_result;
  47.  
  48.  
  49. static inline mtmn_config_t app_mtmn_config()
  50. {
  51. mtmn_config_t mtmn_config = {0};
  52. mtmn_config.type = FAST;
  53. mtmn_config.min_face = 80;
  54. mtmn_config.pyramid = 0.707;
  55. mtmn_config.pyramid_times = 4;
  56. mtmn_config.p_threshold.score = 0.6;
  57. mtmn_config.p_threshold.nms = 0.7;
  58. mtmn_config.p_threshold.candidate_number = 20;
  59. mtmn_config.r_threshold.score = 0.7;
  60. mtmn_config.r_threshold.nms = 0.7;
  61. mtmn_config.r_threshold.candidate_number = 10;
  62. mtmn_config.o_threshold.score = 0.7;
  63. mtmn_config.o_threshold.nms = 0.7;
  64. mtmn_config.o_threshold.candidate_number = 1;
  65. return mtmn_config;
  66. }
  67. mtmn_config_t mtmn_config = app_mtmn_config();
  68.  
  69. face_id_name_list st_face_list;
  70. static dl_matrix3du_t *aligned_face = NULL;
  71.  
  72. httpd_handle_t camera_httpd = NULL;
  73.  
  74. typedef enum
  75. {
  76. START_STREAM,
  77. START_DETECT,
  78. SHOW_FACES,
  79. START_RECOGNITION,
  80. START_ENROLL,
  81. ENROLL_COMPLETE,
  82. DELETE_ALL,
  83. } en_fsm_state;
  84. en_fsm_state g_state;
  85.  
  86. typedef struct
  87. {
  88. char enroll_name[ENROLL_NAME_LEN];
  89. } httpd_resp_value;
  90.  
  91. httpd_resp_value st_name;
  92.  
  93. void setup() {
  94. Serial.begin(115200);
  95. Serial.setDebugOutput(true);
  96. Serial.println();
  97.  
  98. digitalWrite(relay_pin, LOW);
  99. pinMode(relay_pin, OUTPUT);
  100.  
  101. camera_config_t config;
  102. config.ledc_channel = LEDC_CHANNEL_0;
  103. config.ledc_timer = LEDC_TIMER_0;
  104. config.pin_d0 = Y2_GPIO_NUM;
  105. config.pin_d1 = Y3_GPIO_NUM;
  106. config.pin_d2 = Y4_GPIO_NUM;
  107. config.pin_d3 = Y5_GPIO_NUM;
  108. config.pin_d4 = Y6_GPIO_NUM;
  109. config.pin_d5 = Y7_GPIO_NUM;
  110. config.pin_d6 = Y8_GPIO_NUM;
  111. config.pin_d7 = Y9_GPIO_NUM;
  112. config.pin_xclk = XCLK_GPIO_NUM;
  113. config.pin_pclk = PCLK_GPIO_NUM;
  114. config.pin_vsync = VSYNC_GPIO_NUM;
  115. config.pin_href = HREF_GPIO_NUM;
  116. config.pin_sscb_sda = SIOD_GPIO_NUM;
  117. config.pin_sscb_scl = SIOC_GPIO_NUM;
  118. config.pin_pwdn = PWDN_GPIO_NUM;
  119. config.pin_reset = RESET_GPIO_NUM;
  120. config.xclk_freq_hz = 20000000;
  121. config.pixel_format = PIXFORMAT_JPEG;
  122. //init with high specs to pre-allocate larger buffers
  123. if (psramFound()) {
  124. config.frame_size = FRAMESIZE_UXGA;
  125. config.jpeg_quality = 10;
  126. config.fb_count = 2;
  127. } else {
  128. config.frame_size = FRAMESIZE_SVGA;
  129. config.jpeg_quality = 12;
  130. config.fb_count = 1;
  131. }
  132.  
  133. #if defined(CAMERA_MODEL_ESP_EYE)
  134. pinMode(13, INPUT_PULLUP);
  135. pinMode(14, INPUT_PULLUP);
  136. #endif
  137.  
  138. // camera init
  139. esp_err_t err = esp_camera_init(&config);
  140. if (err != ESP_OK) {
  141. Serial.printf("Camera init failed with error 0x%x", err);
  142. return;
  143. }
  144.  
  145. sensor_t * s = esp_camera_sensor_get();
  146. s->set_framesize(s, FRAMESIZE_QVGA);
  147.  
  148. #if defined(CAMERA_MODEL_M5STACK_WIDE)
  149. s->set_vflip(s, 1);
  150. s->set_hmirror(s, 1);
  151. #endif
  152.  
  153. WiFi.begin(ssid, password);
  154. while (WiFi.status() != WL_CONNECTED) {
  155. delay(500);
  156. Serial.print(".");
  157. }
  158. Serial.println("");
  159. Serial.println("WiFi connected");
  160.  
  161. app_httpserver_init();
  162. app_facenet_main();
  163. socket_server.listen(82);
  164.  
  165. Serial.print("Camera Ready! Use 'http://");
  166. Serial.print(WiFi.localIP());
  167. Serial.println("' to connect");
  168. }
  169.  
  170. static esp_err_t index_handler(httpd_req_t *req) {
  171. httpd_resp_set_type(req, "text/html");
  172. httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
  173. return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len);
  174. }
  175.  
  176. httpd_uri_t index_uri = {
  177. .uri = "/",
  178. .method = HTTP_GET,
  179. .handler = index_handler,
  180. .user_ctx = NULL
  181. };
  182.  
  183. void app_httpserver_init ()
  184. {
  185. httpd_config_t config = HTTPD_DEFAULT_CONFIG();
  186. if (httpd_start(&camera_httpd, &config) == ESP_OK)
  187. Serial.println("httpd_start");
  188. {
  189. httpd_register_uri_handler(camera_httpd, &index_uri);
  190. }
  191. }
  192.  
  193. void app_facenet_main()
  194. {
  195. face_id_name_init(&st_face_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
  196. aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3);
  197. read_face_id_from_flash_with_name(&st_face_list);
  198. }
  199.  
  200. static inline int do_enrollment(face_id_name_list *face_list, dl_matrix3d_t *new_id)
  201. {
  202. ESP_LOGD(TAG, "START ENROLLING");
  203. int left_sample_face = enroll_face_id_to_flash_with_name(face_list, new_id, st_name.enroll_name);
  204. ESP_LOGD(TAG, "Face ID %s Enrollment: Sample %d",
  205. st_name.enroll_name,
  206. ENROLL_CONFIRM_TIMES - left_sample_face);
  207. return left_sample_face;
  208. }
  209.  
  210. static esp_err_t send_face_list(WebsocketsClient &client)
  211. {
  212. client.send("delete_faces"); // tell browser to delete all faces
  213. face_id_node *head = st_face_list.head;
  214. char add_face[64];
  215. for (int i = 0; i < st_face_list.count; i++) // loop current faces
  216. {
  217. sprintf(add_face, "listface:%s", head->id_name);
  218. client.send(add_face); //send face to browser
  219. head = head->next;
  220. }
  221. }
  222.  
  223. static esp_err_t delete_all_faces(WebsocketsClient &client)
  224. {
  225. delete_face_all_in_flash_with_name(&st_face_list);
  226. client.send("delete_faces");
  227. }
  228.  
  229. void handle_message(WebsocketsClient &client, WebsocketsMessage msg)
  230. {
  231. if (msg.data() == "stream") {
  232. g_state = START_STREAM;
  233. client.send("STREAMING");
  234. }
  235. if (msg.data() == "detect") {
  236. g_state = START_DETECT;
  237. client.send("DETECTING");
  238. }
  239. if (msg.data().substring(0, 8) == "capture:") {
  240. g_state = START_ENROLL;
  241. char person[FACE_ID_SAVE_NUMBER * ENROLL_NAME_LEN] = {0,};
  242. msg.data().substring(8).toCharArray(person, sizeof(person));
  243. memcpy(st_name.enroll_name, person, strlen(person) + 1);
  244. client.send("CAPTURING");
  245. }
  246. if (msg.data() == "recognise") {
  247. g_state = START_RECOGNITION;
  248. client.send("RECOGNISING");
  249. }
  250. if (msg.data() == "openDoor") {
  251. client.send("Openning Door");
  252. open_door(client);
  253. }
  254.  
  255. if (msg.data().substring(0, 7) == "remove:") {
  256. char person[ENROLL_NAME_LEN * FACE_ID_SAVE_NUMBER];
  257. msg.data().substring(7).toCharArray(person, sizeof(person));
  258. delete_face_id_in_flash_with_name(&st_face_list, person);
  259. send_face_list(client); // reset faces in the browser
  260. }
  261. if (msg.data() == "delete_all") {
  262. delete_all_faces(client);
  263. }
  264. }
  265.  
  266. void open_door(WebsocketsClient &client) {
  267. if (digitalRead(relay_pin) == LOW) {
  268. digitalWrite(relay_pin, HIGH); //close (energise) relay so door unlocks
  269. Serial.println("Door Unlocked");
  270. client.send("door_open");
  271. door_opened_millis = millis(); // time relay closed and door opened
  272. }
  273. }
  274.  
  275. void loop() {
  276. auto client = socket_server.accept();
  277. client.onMessage(handle_message);
  278. dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, 320, 240, 3);
  279. http_img_process_result out_res = {0};
  280. out_res.image = image_matrix->item;
  281.  
  282. send_face_list(client);
  283. client.send("STREAMING");
  284.  
  285. while (client.available()) {
  286. client.poll();
  287.  
  288. if (millis() - interval > door_opened_millis) { // current time - face recognised time > 5 secs
  289. digitalWrite(relay_pin, LOW); //open relay
  290. }
  291.  
  292. fb = esp_camera_fb_get();
  293.  
  294. if (g_state == START_DETECT || g_state == START_ENROLL || g_state == START_RECOGNITION)
  295. {
  296. out_res.net_boxes = NULL;
  297. out_res.face_id = NULL;
  298.  
  299. fmt2rgb888(fb->buf, fb->len, fb->format, out_res.image);
  300.  
  301. out_res.net_boxes = face_detect(image_matrix, &mtmn_config);
  302.  
  303. if (out_res.net_boxes)
  304. {
  305. if (align_face(out_res.net_boxes, image_matrix, aligned_face) == ESP_OK)
  306. {
  307.  
  308. out_res.face_id = get_face_id(aligned_face);
  309. last_detected_millis = millis();
  310. if (g_state == START_DETECT) {
  311. client.send("FACE DETECTED");
  312. }
  313.  
  314. if (g_state == START_ENROLL)
  315. {
  316. int left_sample_face = do_enrollment(&st_face_list, out_res.face_id);
  317. char enrolling_message[64];
  318. sprintf(enrolling_message, "SAMPLE NUMBER %d FOR %s", ENROLL_CONFIRM_TIMES - left_sample_face, st_name.enroll_name);
  319. client.send(enrolling_message);
  320. if (left_sample_face == 0)
  321. {
  322. ESP_LOGI(TAG, "Enrolled Face ID: %s", st_face_list.tail->id_name);
  323. g_state = START_STREAM;
  324. char captured_message[64];
  325. sprintf(captured_message, "FACE CAPTURED FOR %s", st_face_list.tail->id_name);
  326. client.send(captured_message);
  327. send_face_list(client);
  328.  
  329. }
  330. }
  331.  
  332. if (g_state == START_RECOGNITION && (st_face_list.count > 0))
  333. {
  334. face_id_node *f = recognize_face_with_name(&st_face_list, out_res.face_id);
  335. if (f)
  336. {
  337. char recognised_message[64];
  338. sprintf(recognised_message, "DOOR OPEN FOR %s", f->id_name);
  339. open_door(client);
  340. client.send(recognised_message);
  341. }
  342. else
  343. {
  344. client.send("FACE NOT RECOGNISED");
  345. }
  346. }
  347. dl_matrix3d_free(out_res.face_id);
  348. }
  349.  
  350. }
  351. else
  352. {
  353. if (g_state != START_DETECT) {
  354. client.send("NO FACE DETECTED");
  355. }
  356. }
  357.  
  358. if (g_state == START_DETECT && millis() - last_detected_millis > 500) { // Detecting but no face detected
  359. client.send("DETECTING");
  360. }
  361.  
  362. }
  363.  
  364. client.sendBinary((const char *)fb->buf, fb->len);
  365.  
  366. esp_camera_fb_return(fb);
  367. fb = NULL;
  368. }
  369. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement