SỬ DỤNG NHẬN DẠNG KHUÔN MẶT ĐỂ MỞ CỬA HOẶC ĐIỀU KHIỂN CÁC THIẾT BỊ TỰ ĐỘNG HÓA GIA ĐÌNH KHÁC
Trong hướng dẫn này sẽ giải thích cách lưu hình ảnh đã đăng ký (eroll face) lên bộ nhớ, và sau đó chúng ta có thể sử dụng các nhận dạng đã lưu này để so sánh với hình ảnh thu được từ ESP32. Có ba bước:
- Tạo sơ đồ phân vùng mới để cho phép lưu trữ liên tục
- Sửa đổi bản phác thảo ví dụ CameraWebServer để lưu dữ liệu khuôn mặt vào phân vùng mới
- Sử dụng các nhận dạng đã lưu này để điều khiển các thiết bị được kết nối với ESP32
Trước khi làm theo hướng dẫn này, hãy đảm bảo bạn đã chạy thành công Example: CameraWebServer
PHÂN VÙNG LẠI VÙNG NHỚ CỦA ESP32
Phải phân vùng lại ESP32 để tạo ra vùng lưu trữ khuôn mặt đã nhận dạng. Tải xuống file phân vùng của tác giả: https://robotzero.one/wp-content/uploads/2019/04/rzo_partitions.csv
Thêm tệp này vào thư mục chứa các lược đồ phân vùng khác. Điều này được tìm thấy ở một trong hai nơi, tùy thuộc vào cách bạn cài đặt Arduino IDE.
Arduino IDE được cài đặt từ Windows Store:
C > Users > your-user-name > Documents > ArduinoData > packages > esp32 > hardware > esp32 > 1.0.4 > tools > partitions
Arduino IDE được cài đặt từ trang web Arduino:
C > Users > your-user-name > AppData > Local > Arduino15 > packages > esp32 > hardware > esp32 > 1.0.4 > tools > partitions
Lược đồ mới phải được thêm vào thiết bị ESP của bạn trong tệp cấu hình trình quản lý bảng - board.txt. Một lần nữa điều này được tìm thấy ở một trong hai nơi.
Arduino IDE được cài đặt từ Windows Store:
C > Users > your-user-name > Documents > ArduinoData > packages > esp32 > hardware > esp32 > 1.0.4
Arduino IDE được cài đặt từ trang web Arduino:
C > Users > your-user-name > AppData > Local > Arduino15 > packages > esp32 > hardware > esp32 > 1.0.4
Thêm ba dòng sau bên dưới các tùy chọn phân vùng hiện có cho bảng Esp32wrover trong tệp board.txt này.
esp32wrover.menu.PartitionScheme.rzo_partition=Face Recognition (2621440 bytes with OTA)
esp32wrover.menu.PartitionScheme.rzo_partition.build.partitions=rzo_partitions
esp32wrover.menu.PartitionScheme.rzo_partition.upload.maximum_size=2621440
THU THẬP DỮ LIỆU KHUÔN MẶT ĐỂ LƯU TRỮ
Ví dụ về CameraWebServer trong IDE không lưu các khuôn mặt đã đăng ký khi mất điện. Để sửa đổi nó để sử dụng phân vùng mới, một vài thay đổi cần được thực hiện.
Trong Arduino IDE, tạo một bản sao CameraWebServer. Ta sẽ sử dụng sketch này để học và lưu lại các khuôn mặt.
Bạn sẽ thấy ba tab trong Arduino IDE tương tự như hình ảnh bên dưới:
Trong tab thứ hai (app_httpd.cpp) thực hiện các thay đổi sau.
Sau #include “fr_forward.h” (khoảng dòng 24) thêm:
#include “fr_flash.h”;
Thay đổi int8_t left_sample_face = enroll_face(&id_list, aligned_face);(&id_list, aligned_face); (khoảng dòng 178) thành:
int8_t left_sample_face = enroll_face_id_to_flash(&id_list, aligned_face);
Sau face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES); (khoảng dòng 636) thêm:
read_face_id_from_flash(&id_list);
Flash và chạy Phác thảo này theo cách tương tự như trước đây. Dữ liệu khuôn mặt đã đăng ký sẽ được lưu vào phân vùng mới trên bộ nhớ flash.
SỰ KIỆN KÍCH HOẠT NHẬN DẠNG KHUÔN MẶT
Khi nhận dạng đúng khuôn mặt đã được học, chân RelayPin sẽ được kéo lên mức HIGH. Sau 5 giây trôi qua, nếu không có mặt nhận dạng, pin được đặt ở mức LOW. Mã trong hàm rzoCheckForFace() có thể được thay đổi thành bất kỳ chức năng nào bạn yêu cầu khi nhận diện khuôn mặt.
(Đoạn code dưới đây không phải nguyên gốc trong bài viết, đã được sửa đổi để phù hợp với board ESP-EYE và chân relay đã được đổi qua chân 21)
#include "esp_camera.h"
#include "fd_forward.h"
#include "fr_forward.h"
#include "fr_flash.h"
#define relayPin 21 // pin 12 can also be used
unsigned long currentMillis = 0;
unsigned long openedMillis = 0;
long interval = 5000; // open lock for ... milliseconds
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#define ENROLL_CONFIRM_TIMES 5
#define FACE_ID_SAVE_NUMBER 7
static inline mtmn_config_t app_mtmn_config()
{
mtmn_config_t mtmn_config = {0};
mtmn_config.type = FAST;
mtmn_config.min_face = 80;
mtmn_config.pyramid = 0.707;
mtmn_config.pyramid_times = 4;
mtmn_config.p_threshold.score = 0.6;
mtmn_config.p_threshold.nms = 0.7;
mtmn_config.p_threshold.candidate_number = 20;
mtmn_config.r_threshold.score = 0.7;
mtmn_config.r_threshold.nms = 0.7;
mtmn_config.r_threshold.candidate_number = 10;
mtmn_config.o_threshold.score = 0.7;
mtmn_config.o_threshold.nms = 0.7;
mtmn_config.o_threshold.candidate_number = 1;
return mtmn_config;
}
mtmn_config_t mtmn_config = app_mtmn_config();
static face_id_list id_list = {0};
dl_matrix3du_t *image_matrix = NULL;
camera_fb_t * fb = NULL;
dl_matrix3du_t *aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3);
void setup() {
Serial.begin(115200);
digitalWrite(relayPin, LOW);
pinMode(relayPin, OUTPUT);
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_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
//drop down frame size for higher initial frame rate
sensor_t * s = esp_camera_sensor_get();
s->set_framesize(s, FRAMESIZE_QVGA);
s->set_vflip(s, 1);
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
read_face_id_from_flash(&id_list);// Read current face data from on-board flash
}
void rzoCheckForFace() {
currentMillis = millis();
if (run_face_recognition()) { // face recognition function has returned true
Serial.println("Face recognised");
digitalWrite(relayPin, HIGH); //close (energise) relay
openedMillis = millis(); //time relay closed
}
if (currentMillis - interval > openedMillis) { // current time - face recognised time > 5 secs
digitalWrite(relayPin, LOW); //open relay
}
}
bool run_face_recognition() {
bool faceRecognised = false; // default
int64_t start_time = esp_timer_get_time();
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return false;
}
int64_t fb_get_time = esp_timer_get_time();
Serial.printf("Get one frame in %u ms.\n", (fb_get_time - start_time) / 1000); // this line can be commented out
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
uint32_t res = fmt2rgb888(fb->buf, fb->len, fb->format, image_matrix->item);
if (!res) {
Serial.println("to rgb888 failed");
dl_matrix3du_free(image_matrix);
}
esp_camera_fb_return(fb);
box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config);
if (net_boxes) {
if (align_face(net_boxes, image_matrix, aligned_face) == ESP_OK) {
int matched_id = recognize_face(&id_list, aligned_face);
if (matched_id >= 0) {
Serial.printf("Match Face ID: %u\n", matched_id);
faceRecognised = true; // function will now return true
} else {
Serial.println("No Match Found");
matched_id = -1;
}
} else {
Serial.println("Face Not Aligned");
}
free(net_boxes->box);
free(net_boxes->landmark);
free(net_boxes);
}
dl_matrix3du_free(image_matrix);
return faceRecognised;
}
void loop() {
rzoCheckForFace();
}
Sau khi flash và chạy sketch mới này thì khi nhận được khuôn mặt đã được lưu ở phần thu thập dữ liệu đèn LED trên board ESP-EYE sẽ sáng lên.
MỞ CỬA
Bây giờ tôi chỉ cần câu chân 21 qua module relay. Tiếp tục sử dụng relay để điều khiển chốt cửa bằng điện là chúng ta đã hòa thành dự án.
XÓA KHUÔN MẶT KHỎI BỘ NHỚ
Nếu bạn cần xóa các mặt được lưu trữ, hãy dán và tải lên sketch bên dưới
#include "esp_camera.h"
#include "fd_forward.h"
#include "fr_forward.h"
#include "fr_flash.h"
#define ENROLL_CONFIRM_TIMES 5
#define FACE_ID_SAVE_NUMBER 7
static face_id_list id_list = {0};
void setup() {
Serial.begin(115200);
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
read_face_id_from_flash(&id_list);// Read current face data from on-board flash
Serial.println("Faces Read");
while ( delete_face_id_in_flash(&id_list) > -1 ){
Serial.println("Deleting Face");
}
Serial.println("All Deleted");
}
void loop() {
}
1 nhận xét