This access control system based on face recognition displays the open and close status of the access on an OLED screen.
- On Startup: It is in recognition mode.
- Mode Switching: Switch modes using serial port commands.
Send R: Enter registration mode.
In registration mode, send REG = Alice: to register facial information; send DEL = Alice: to delete registered facial information.
Send Y: Save the registered facial information and switch back to recognition mode.
After rebooting the device, it will directly enter recognition mode and load the pre - registered facial information.Code
Open Arduino IDE, create a new project, and add the following code:
/*
Access control system based on face recognition (the system starts in recognition mode)
To use this system:
1.Upload the code and open serial monitor
2.Starts directly in recognition mode
3.Serial input 'R' switches to registration mode
4.Register faces using "REG=Name" commands
5.When done, send "Y" to save and switch back to recognition mode
6.In recognition mode, the OLED will show OPEN/CLOSE status
*/
#include "WiFi.h"#include "StreamIO.h"#include "VideoStream.h"#include "RTSP.h"#include "NNFaceDetectionRecognition.h"#include "VideoStreamOverlay.h"#include "AmebaFatFS.h"#include <U8g2lib.h> // Include U8g2 library for OLED
#define CHANNELVID 0 // Channel for RTSP streaming#define CHANNELJPEG 1 // Channel for taking snapshots#define CHANNELNN 3 // RGB format video for NN only available on channel 3
// Customised resolution for NN#define NNWIDTH 576#define NNHEIGHT 320
// U8g2 OLED setup - adjust according to your OLED modelU8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
VideoSetting configVID(VIDEO_FHD, 30, VIDEO_H264, 0);VideoSetting configJPEG(VIDEO_FHD, CAM_FPS, VIDEO_JPEG, 1);VideoSetting configNN(NNWIDTH, NNHEIGHT, 10, VIDEO_RGB, 0);
NNFaceDetectionRecognition facerecog;
RTSP rtsp;StreamIO videoStreamer(1, 1);StreamIO videoStreamerFDFR(1, 1);StreamIO videoStreamerRGBFD(1, 1);
char ssid[] = "xxx"; // your network SSID (name)char pass[] = "xxx"; // your network passwordint status = WL_IDLE_STATUS;
bool regMode = false; // Start in recognition modebool accessGranted = false; // Track access statusuint32_t img_addr = 0;uint32_t img_len = 0;
String fileName;long counter = 0;
// File Initialization
AmebaFatFS fs;
void updateOLEDStatus() {
u8g2.clearBuffer();
if (regMode) {
u8g2.drawStr(0, 20, "REGISTER MODE");
u8g2.drawStr(0, 40, "REG=<NAME>");
u8g2.drawStr(0, 60, "Enter 'Y' to save");
} else {
u8g2.drawStr(0, 20, "RECOGNITION MODE");
u8g2.drawStr(0, 40, accessGranted ? "Status: OPEN" : "Status: CLOSE");
}
u8g2.sendBuffer();
}
void setup(){
// Initialize OLED display
u8g2.begin();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB10_tr);
u8g2.drawStr(0, 20, "Initializing...");
u8g2.sendBuffer();
Serial.begin(115200);
// Attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
// Update OLED
u8g2.clearBuffer();
u8g2.drawStr(0, 20, "Connecting WiFi");
u8g2.sendBuffer();
delay(2000);
}
// Configure camera video channels with video format information
Camera.configVideoChannel(CHANNELVID, configVID);
Camera.configVideoChannel(CHANNELJPEG, configJPEG);
Camera.configVideoChannel(CHANNELNN, configNN);
Camera.videoInit();
// Configure RTSP with corresponding video format information
rtsp.configVideo(configVID);
rtsp.begin();
// Configure Face Recognition model
facerecog.configVideo(configNN);
facerecog.modelSelect(FACE_RECOGNITION, NA_MODEL, DEFAULT_SCRFD, DEFAULT_MOBILEFACENET);
facerecog.begin();
facerecog.setResultCallback(FRPostProcess);
// Configure StreamIO object to stream data from video channel to RTSP
videoStreamer.registerInput(Camera.getStream(CHANNELVID));
videoStreamer.registerOutput(rtsp);
if (videoStreamer.begin() != 0) {
Serial.println("StreamIO link start failed");
}
// Start data stream from video channel
Camera.channelBegin(CHANNELVID);
Camera.channelBegin(CHANNELJPEG);
// Configure StreamIO object to stream data from RGB video channel to face detection
videoStreamerRGBFD.registerInput(Camera.getStream(CHANNELNN));
videoStreamerRGBFD.setStackSize();
videoStreamerRGBFD.setTaskPriority();
videoStreamerRGBFD.registerOutput(facerecog);
if (videoStreamerRGBFD.begin() != 0) {
Serial.println("StreamIO link start failed");
}
// Start video channel for NN
Camera.channelBegin(CHANNELNN);
// Start OSD drawing on RTSP video channel
OSD.configVideo(CHANNELVID, configVID);
OSD.begin();
// Restore any registered faces saved in flash
facerecog.restoreRegisteredFace();
// Update OLED
updateOLEDStatus();
Serial.println("System started in RECOGNITION mode");
Serial.println("Available commands:");
Serial.println("R - Switch to registration mode");
Serial.println("In registration mode:");
Serial.println("REG={Name} - Register a new face");
Serial.println("DEL={Name} - Delete a registered face");
Serial.println("RESET - Reset all registered faces");
Serial.println("Y - Save faces and switch to recognition mode");
}
void loop(){
// Handle serial input
if (Serial.available() > 0) {
String input = Serial.readString();
input.trim();
if (input.equalsIgnoreCase("R") && !regMode) {
// Switch to registration mode
regMode = true;
Serial.println("Switched to REGISTRATION mode");
updateOLEDStatus();
}
else if (input.equalsIgnoreCase("Y") && regMode) {
// Save configurations and switch to recognition mode
facerecog.backupRegisteredFace();
regMode = false;
Serial.println("Faces saved. Switched to RECOGNITION mode");
updateOLEDStatus();
}
else if (regMode) {
// Registration mode commands
if (input.startsWith(String("REG="))) {
String name = input.substring(4);
facerecog.registerFace(name);
Serial.print("Registered face: ");
Serial.println(name);
// Update OLED temporarily
u8g2.clearBuffer();
u8g2.drawStr(0, 20, "REGISTERED:");
u8g2.drawStr(0, 40, name.c_str());
u8g2.sendBuffer();
delay(2000);
updateOLEDStatus();
}
else if (input.startsWith(String("DEL="))) {
String name = input.substring(4);
facerecog.removeFace(name);
Serial.print("Removed face: ");
Serial.println(name);
}
else if (input.startsWith(String("RESET"))) {
facerecog.resetRegisteredFace();
Serial.println("All registered faces have been reset");
}
}
}
delay(100);
OSD.createBitmap(CHANNELVID);
OSD.update(CHANNELVID);
}
// User callback function for post processing of face recognition resultsvoid FRPostProcess(std::vector<FaceRecognitionResult> results){
uint16_t im_h = configVID.height();
uint16_t im_w = configVID.width();
printf("Total number of faces detected = %d\r\n", facerecog.getResultCount());
OSD.createBitmap(CHANNELVID);
if (facerecog.getResultCount() > 0 && !regMode) {
FaceRecognitionResult face = results[0];
if (String(face.name()) != String("unknown")) {
if (!accessGranted) { // Only trigger once per recognition
Serial.print("Access GRANTED for: ");
Serial.println(face.name());
accessGranted = true;
// Update OLED
updateOLEDStatus();
// Take snapshot
fs.begin();
File file = fs.open(String(fs.getRootPath()) + face.name() + String(++counter) + ".jpg");
delay(1000);
Camera.getImage(CHANNELJPEG, &img_addr, &img_len);
file.write((uint8_t *)img_addr, img_len);
file.close();
fs.end();
// After 10 seconds, return to CLOSE status
delay(5000);
accessGranted = false;
updateOLEDStatus();
}
} else {
if (accessGranted) { // Only update if status changed
Serial.println("Access DENIED - Unknown face");
accessGranted = false;
updateOLEDStatus();
}
}
}
for (int i = 0; i < facerecog.getResultCount(); i++) {
FaceRecognitionResult item = results[i];
int xmin = (int)(item.xMin() * im_w);
int xmax = (int)(item.xMax() * im_w);
int ymin = (int)(item.yMin() * im_h);
int ymax = (int)(item.yMax() * im_h);
uint32_t osd_color = (String(item.name()) == String("unknown")) ? OSD_COLOR_RED : OSD_COLOR_GREEN;
printf("Face %d name %s:\t%d %d %d %d\n\r", i, item.name(), xmin, xmax, ymin, ymax);
OSD.drawRect(CHANNELVID, xmin, ymin, xmax, ymax, 3, osd_color);
char text_str[40];
snprintf(text_str, sizeof(text_str), "Face:%s", item.name());
OSD.drawText(CHANNELVID, xmin, ymin - OSD.getTextHeight(CHANNELVID), text_str, osd_color);
}
OSD.update(CHANNELVID);
}
- Save the project; select the AMB82-MINI development board, the corresponding serial port, and the GC2053 camera.
- Hold the BOOT button and press EN briefly to put the device in download mode.
- Click the Upload button, and after uploading, press EN to reset and run the program.
Operation Effects:
- The system enters Recognition Mode.
- Send "R" via serial to switch to Register Mode.
Testing:
- Open VLC's network stream interface on the same LAN, enter the development board's IP address (e.g., rtsp://192.168.1.104:554) to get real-time facial recognition status and fix the face position.
- Send "REG=LJL" via serial to register the detected face; VLC will display a green box.
- Send "Y" via serial to save the face data and return to Recognition Mode.
Results:
If the camera doesn't detect the registered face, the OLED shows "CLOSE".
If the camera detects the registered face, the OLED shows "OPEN" for 5 seconds.
Portable Access Control System:
Using the expansion board's onboard battery connector, a lithium - battery can power the system, creating a portable handheld version.
To achieve this, register and save facial data to Flash via serial.
Comments