hub8735
Published © LGPL

Demonstration Case-AI electronic cat eyes

Recognizable face appears at the door, the TFT LCD inside the door will automatically turn on and display who is waiting outside.

BeginnerFull instructions provided139
Demonstration Case-AI electronic cat eyes

Things used in this project

Hardware components

Arduino HUB-8735
×1
ILI9341 TFT
×1

Software apps and online services

LINE Notify

Story

Read more

Custom parts and enclosures

demo video

https://www.youtube.com/watch?v=_28hPDlj5WA

Schematics

user guide

user guide

Code

arduino souce code

Arduino
arduino souce code
/*


 Face registration commands
 --------------------------
 Point the camera at a target face and enter the following commands into the serial monitor,
 Register face:           "REG={Name}"            Ensure that there is only one face detected in frame
 Exit registration mode:  "EXIT"                  Stop trying to register a face before it is successfully registered
 Reset registered faces:  "RESET"                 Forget all previously registered faces
 Backup registered faces to flash:    "BACKUP"    Save registered faces to flash
 Restore registered faces from flash: "RESTORE"   Load registered faces from flash



*/

#include "WiFi.h"
#include "StreamIO.h"
#include "VideoStream.h"
#include "RTSP.h"
#include "NNFaceDetectionRecognition.h"
#include "VideoStreamOverlay.h"
#include "SPI.h"
#include "AmebaILI9341.h"
#include "TJpg_Decoder.h"
#include "AmebaFatFS.h"

#define CHANNEL   0
#define CHANNELTFT   1
#define CHANNELNN 3

// Customised resolution for NN
#define NNWIDTH 576
#define NNHEIGHT 320

/*SPI TFT LCD*/
#define TFT_RESET       27//PF_1//5
#define TFT_DC          28//PF_2//4
#define TFT_CS          SPI1_SS
#define ILI9341_SPI_FREQUENCY 25000000
#define FILENAME "StImg_"

AmebaILI9341 tft = AmebaILI9341(TFT_CS, TFT_DC, TFT_RESET);

VideoSetting config(VIDEO_FHD, 30, VIDEO_H264, 0);
VideoSetting configNN(NNWIDTH, NNHEIGHT, 10, VIDEO_RGB, 0);
VideoSetting configTFT(VIDEO_VGA,CAM_FPS,VIDEO_JPEG,1);
uint32_t img_addr = 0;
uint32_t img_len = 0;
uint32_t count = 0;

NNFaceDetectionRecognition facerecog;
RTSP rtsp;
StreamIO videoStreamer(1, 1);
StreamIO videoStreamerFDFR(1, 1);
StreamIO videoStreamerRGBFD(1, 1);

char ssid[] = "your_ssid";    // your network SSID (name)
char pass[] = "your_password";       // your network password
int status = WL_IDLE_STATUS;

//Line notify
char server[] = "notify-api.line.me"; 
String LineToken = "your_token";
String message = "";

WiFiSSLClient client;

IPAddress ip;
int rtsp_portnum; 

/*  delay function
*/
unsigned long CurrentTime,preTime;
const int intervalSwitch = 5000;

unsigned long LineCurrentTime,LinepreTime;
const int LineintervalSwitch = (1000 * 60)* 1;
bool lineFlag = false;
bool SendLineMessageFlag = false;

unsigned long OpenCameraCurrentTime,OpenCamerapreTime;
const int OpenCameraintervalSwitch = 9000;
int LCD_AutoClosePin = 5;

bool FaceDetected = false;
uint16_t faceDetectedCount;
bool faceDetected = false;
uint32_t picturecount = 0;
// File Initialization
AmebaFatFS fs;


bool tft_output(int16_t x,int16_t y, uint16_t w, uint16_t h, uint16_t * bitmap)
{
    tft.drawBitmap(x,y,w,h,bitmap);

    return 1;
}


void setup() {
    Serial.begin(115200);

    SPI.setDefaultFrequency(ILI9341_SPI_FREQUENCY);
    pinMode(LCD_AutoClosePin,OUTPUT);
    
    digitalWrite(LCD_AutoClosePin,LOW);
    tft.begin();
    tft.setRotation(3);

    TJpgDec.setJpgScale(2);
    TJpgDec.setCallback(tft_output);

    // 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);

        // wait 2 seconds for connection:
        delay(2000);
    }

    ip = WiFi.localIP();
    
    // Configure camera video channels with video format information
    // Adjust the bitrate based on your WiFi network quality
    config.setBitrate(2 * 1024 * 1024);     // Recommend to use 2Mbps for RTSP streaming to prevent network congestion
    Camera.configVideoChannel(CHANNEL, config);
    Camera.configVideoChannel(CHANNELNN, configNN);
    Camera.configVideoChannel(CHANNELTFT, configTFT);
    Camera.videoInit();

    Camera.channelBegin(CHANNELTFT);
    // Configure RTSP with corresponding video format information
    rtsp.configVideo(config);
    rtsp.begin();
    rtsp_portnum = rtsp.getPort();


    facerecog.configVideo(configNN);
    facerecog.modelSelect(FACE_RECOGNITION, NA_MODEL, DEFAULT_SCRFD, DEFAULT_MOBILEFACENET);
    facerecog.begin();
    facerecog.setResultCallback(FRPostProcess);

    videoStreamer.registerInput(Camera.getStream(CHANNEL));
    videoStreamer.registerOutput(rtsp);
    if (videoStreamer.begin() != 0) {
        Serial.println("StreamIO link start failed");
    }
    Camera.channelBegin(CHANNEL);

    // 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(CHANNEL, config);
    OSD.begin();
}

void loop() {
    if (Serial.available() > 0) {
        String input = Serial.readString();   //Waiting for input via Serial
        input.trim();

        if (input.startsWith(String("REG="))){        //To register name and remember the face recognition results. When registering faces, please make sure there is only one face in the screen.
            String name = input.substring(4);
            facerecog.registerFace(name);
        } else if (input.startsWith(String("EXIT"))) {  //Enter the command "EXIT" to exit registration mode。
            facerecog.exitRegisterMode();
        } else if (input.startsWith(String("RESET"))) { //Enter the command "RESET" to forget all previously registered faces. All previously assigned faces and names will be deleted.
            facerecog.resetRegisteredFace();
        } else if (input.startsWith(String("BACKUP"))) {  //  Enter the command "BACKUP" to save a copy of the registered face to flash memory. If a backup exists, enter the command "RESTORE" to reload the registered faces from flash memory. 
            facerecog.backupRegisteredFace();
        } else if (input.startsWith(String("RESTORE"))) {
            facerecog.restoreRegisteredFace();
        }
    }


   CurrentTime = millis();
   if(CurrentTime - preTime > intervalSwitch){
		preTime = CurrentTime;
    OSD.createBitmap(CHANNEL);
    OSD.update(CHANNEL);
    
   }


    Camera.getImage(CHANNELTFT,&img_addr,&img_len);

    if(lineFlag) //line
    {
        if(SendLineMessageFlag == false )
        {
            SendLineMessageFlag = true;
            
            if(client.connect(server,443))
            {
                Serial.println("connected to server");
                // use HTTP request:
                message =   "Warning, there is a stranger at the door!!!";
                String query = "message=" + message;
                client.print("POST /api/notify HTTP/1.1\r\n");
                client.print("Host: " + String(server) +"\r\n"); 
                client.print("Authorization: Bearer " + LineToken + "\r\n"); 
                client.print("Content-Type: application/x-www-form-urlencoded\r\n");
                client.print("Content-Length: " + String(query.length()) + "\r\n");
                client.print("\r\n");
              
                client.print(query + "\r\n");      


            }

        }

        LineCurrentTime = millis();
        if(LineCurrentTime - LinepreTime > LineintervalSwitch)
        {
          LinepreTime = LineCurrentTime;
          
          lineFlag = false;
          SendLineMessageFlag = false;
      
         }

    } 

    if(faceDetected)       //If an unregistered face is detected as a stranger, the photo will be automatically taken and save archived.
    {
      Serial.println("save picture !!!!!!!");
      faceDetected = false;
      fs.begin();
      File file = fs.open(String(fs.getRootPath()) + String(FILENAME) + String(picturecount) + String(".jpg"));   
      
      file.write((uint8_t*)img_addr, img_len);
      delay(1);
      file.close();
      fs.end();
      picturecount++; 
    
     
    }
    
    TJpgDec.getJpgSize(0,0,(uint8_t *)img_addr,img_len);
    TJpgDec.drawJpg(0,0,(uint8_t *)img_addr,img_len);    
    
      if(FaceDetected)
      {

        /*open TFT LCD*/ 
        digitalWrite(LCD_AutoClosePin,HIGH); //When a stranger's face is detected, turn on the LCD
        /*end */

        OpenCameraCurrentTime = millis();
        if(OpenCameraCurrentTime - OpenCamerapreTime > OpenCameraintervalSwitch){
          OpenCamerapreTime = OpenCameraCurrentTime;        
          FaceDetected = false;
          Serial.println("close TFT_LCD!!!!!!!");
          /*
            close TFT_LCD
          */          
          digitalWrite(LCD_AutoClosePin,LOW);  // When the time is up, the LCD TFT will be turned off automatically.
        }

      }
}

// User callback function f
void FRPostProcess(std::vector<FaceRecognitionResult> results) {
    uint16_t im_h = config.height();
    uint16_t im_w = config.width();

    Serial.print("Network URL for RTSP Streaming: ");
    Serial.print("rtsp://");
    Serial.print(ip);
    Serial.print(":");
    Serial.println(rtsp_portnum);
    Serial.println(" ");

    printf("Total number of faces detected = %d\r\n", facerecog.getResultCount());
    OSD.createBitmap(CHANNEL);

    if (facerecog.getResultCount() > 0) {
        FaceDetected = true;

        for (uint32_t 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 osdcolor;
            if (String(item.name()) == String("unknown")) {
                osdcolor = OSD_COLOR_RED;
                faceDetectedCount++;
                if(faceDetectedCount < 6)
                {
                  faceDetected = true;
                  faceDetectedCount = 0;
                }

                if(lineFlag == false)
                  lineFlag = true;                  
                  
            } else {
                osdcolor = OSD_COLOR_GREEN;
            }

          
            printf("Face %d name %s:\t%d %d %d %d\n\r", i, item.name(), xmin, xmax, ymin, ymax);
            OSD.drawRect(CHANNEL, xmin, ymin, xmax, ymax, 3, osdcolor);

            char text_str[40];
            snprintf(text_str, sizeof(text_str), "Face:%s", item.name());
            OSD.drawText(CHANNEL, xmin, ymin - OSD.getTextHeight(CHANNEL), text_str, osdcolor);
        }
        //FaceDetected = false;
    }

    OSD.update(CHANNEL);
}

Credits

hub8735
5 projects • 79 followers
Contact

Comments

Please log in or sign up to comment.