Распознавание лица
Файлы проекта
sketch.ino
#include <Arduino.h> #include <WebSocketsServer.h> #include <WiFi.h> #include "camera.h" #include "img_converters.h" #include "FaceFinder.h" // логин-пароль WiFi #define AP_SSID "" #define AP_PASS "" WebSocketsServer ws(82, "", "hub"); FaceFinder face; void setup() { Serial.begin(115200); delay(200); cam_init(FRAMESIZE_VGA, PIXFORMAT_JPEG, 10); WiFi.mode(WIFI_STA); WiFi.begin(AP_SSID, AP_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println(WiFi.localIP()); ws.begin(); } void loop() { ws.loop(); //if (!ws.connectedClients()) return; camera_fb_t *fbj = nullptr; fbj = esp_camera_fb_get(); esp_camera_fb_return(fbj); fbj = nullptr; fbj = esp_camera_fb_get(); if (fbj) { uint32_t len = fbj->width * fbj->height * 2; uint8_t *buf = (uint8_t *)ps_malloc(len); if (buf) { bool ok = jpg2rgb565(fbj->buf, fbj->len, buf, JPG_SCALE_NONE); if (ok) { // swap low->high byte for (uint32_t i = 0; i < len; i += 2) { uint8_t b = buf[i]; buf[i] = buf[i + 1]; buf[i + 1] = b; } face.find(buf, fbj->width, fbj->height, true, 0); if (face.found) Serial.printf("%d,%d,%d,%d\n", face.x, face.y, face.w, face.h); if (ws.connectedClients()) { size_t jpg_buf_len = 0; uint8_t *jpg_buf = nullptr; ok = fmt2jpg(buf, len, fbj->width, fbj->height, PIXFORMAT_RGB565, 80, &jpg_buf, &jpg_buf_len); if (ok) ws.broadcastBIN(jpg_buf, jpg_buf_len); if (jpg_buf) free(jpg_buf); } } free(buf); } } esp_camera_fb_return(fbj); delay(30); }
camera.h
#pragma once #define CAMERA_MODEL_AI_THINKER //#define CAMERA_MODEL_WROVER_KIT //#define CAMERA_MODEL_M5STACK_PSRAM //#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM #include "esp_camera.h" #if defined(CAMERA_MODEL_WROVER_KIT) #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 21 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 19 #define Y4_GPIO_NUM 18 #define Y3_GPIO_NUM 5 #define Y2_GPIO_NUM 4 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 #elif defined(CAMERA_MODEL_M5STACK_PSRAM) #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM 15 #define XCLK_GPIO_NUM 27 #define SIOD_GPIO_NUM 25 #define SIOC_GPIO_NUM 23 #define Y9_GPIO_NUM 19 #define Y8_GPIO_NUM 36 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 39 #define Y5_GPIO_NUM 5 #define Y4_GPIO_NUM 34 #define Y3_GPIO_NUM 35 #define Y2_GPIO_NUM 32 #define VSYNC_GPIO_NUM 22 #define HREF_GPIO_NUM 26 #define PCLK_GPIO_NUM 21 #elif defined(CAMERA_MODEL_M5STACK_WITHOUT_PSRAM) #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM 15 #define XCLK_GPIO_NUM 27 #define SIOD_GPIO_NUM 25 #define SIOC_GPIO_NUM 23 #define Y9_GPIO_NUM 19 #define Y8_GPIO_NUM 36 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 39 #define Y5_GPIO_NUM 5 #define Y4_GPIO_NUM 34 #define Y3_GPIO_NUM 35 #define Y2_GPIO_NUM 17 #define VSYNC_GPIO_NUM 22 #define HREF_GPIO_NUM 26 #define PCLK_GPIO_NUM 21 #elif defined(CAMERA_MODEL_AI_THINKER) #define PWDN_GPIO_NUM 32 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 0 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 5 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 #else #error "Camera model not selected" #endif bool cam_init(framesize_t frame_size = FRAMESIZE_VGA, pixformat_t pixel_format = PIXFORMAT_JPEG, int jpeg_quality = 12) { camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sccb_sda = SIOD_GPIO_NUM; config.pin_sccb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.pixel_format = pixel_format; config.frame_size = frame_size; config.jpeg_quality = jpeg_quality; config.fb_count = 1; esp_err_t result = esp_camera_init(&config); return (result == ESP_OK); }
FaceFinder.h
#pragma once #include <Arduino.h> #include <vector> #include "fb_gfx.h" // HUMAN #include "human_face_detect_mnp01.hpp" #include "human_face_detect_msr01.hpp" // CAT // #include "cat_face_detect_mn03.hpp" class FaceFinder { public: bool find(uint8_t *buf565, uint16_t width, uint16_t height, bool draw = true, bool fill = false) { found = 0; frame_w = width; frame_h = height; { // HUMAN HumanFaceDetectMSR01 s1(0.1F, 0.5F, 2, 0.3F); HumanFaceDetectMNP01 s2(0.4F, 0.3F, 1); std::list<dl::detect::result_t> &candidates = s1.infer((uint16_t *)buf565, {height, width, 3}); std::list<dl::detect::result_t> &results = s2.infer((uint16_t *)buf565, {height, width, 3}, candidates); // CAT // CatFaceDetectMN03 cat(0.4F, 0.3F, 10, 0.3F); // std::list<dl::detect::result_t> &results = cat.infer((uint16_t *)buf565, {height, width, 3}); if (!results.size()) return 0; std::list<dl::detect::result_t>::iterator prediction = results.begin(); x = (int)prediction->box[0]; y = (int)prediction->box[1]; w = (int)prediction->box[2] - x + 1; h = (int)prediction->box[3] - y + 1; if ((x + w) > width) w = width - x; if ((y + h) > height) h = height - y; results.end(); } if (draw) { fb_data_t fbd; fbd.width = width; fbd.height = height; fbd.data = buf565; fbd.bytes_per_pixel = 2; fbd.format = FB_RGB565; uint32_t color = 0b1111100000000000; if (fill) { fb_gfx_fillRect(&fbd, x, y, w, h, color); } else { fb_gfx_drawFastHLine(&fbd, x, y, w, color); fb_gfx_drawFastHLine(&fbd, x, y + h - 1, w, color); fb_gfx_drawFastVLine(&fbd, x, y, h, color); fb_gfx_drawFastVLine(&fbd, x + w - 1, y, h, color); } } found = 1; return 1; } int16_t x, y, w, h; uint16_t frame_w, frame_h; bool found = 0; };
Для просмотра результата нужно создать html файл со следующим содержимым, открыть его в браузере и ввести IP адрес платы
stream.html
<!DOCTYPE html> <body> <input id="ip" type="text" value="192.168.1.6"><br> <button onclick="connect()">START</button> <button onclick="wsclose()">STOP</button> <div id="log_inner"></div> <br> <img id="img"> <script> let ws = null; let flag = false; function connect() { flag = true; ws = new WebSocket(`ws://${ip.value}:82/`, ['hub']); console.log('open...'); ws.onopen = function () { console.log('opened'); }; ws.onclose = function () { console.log('close'); ws = null; if (flag) { setTimeout(connect, 1000); console.log('reconnect'); } }; ws.onmessage = function (e) { document.getElementById('img').src = URL.createObjectURL(e.data); }; } function send(text) { if (ws && ws.readyState == 1) ws.send(text); } function wsclose() { flag = false; if (ws) ws.close(); } </script> </body> </html>