本帖最后由 LV36 于 2025-3-25 23:21 编辑
目标:使用安信可小安派BW21-CBV-Kit进行人脸识别,在识别到人脸后开启ESP-01S继电器,继电器模块可自行接用电器。
物料:安信可小安派BW21-CBV-Kit、ESP-01S模块、ESP-01S专用继电器模块、ESP-01S专用烧录器
代码:AmebaNN—>RTSPFaceRecognition、AmebaHttp—>HTTP_Post_MP4_Whisper_Server、AmebaOTA—>OTA
参考链接:【教程】小安派BW21-CBV-Kit——人脸识别、ESP8266 系列——ESP-01S 控制继电器模块
一、ESP-01S模块配置
使用64 位 Windows 10 22H2 平台搭配 Arduino IDE
(1)打开 Arduino IDE "文件"->"首选项","设置"页面 "附加板管理器 URL"处换行添加“https://arduino.esp8266.com/stable/package_esp8266com_index.json
”(不含“)
(2)"工具"->"开发板"->"开发板管理器" 搜索"ESP8266",点击 "Install(安装)"
坑1:因无法访问外网提示下载失败
解决方案,手动下载离线安装
下载链接:https://pan.baidu.com/s/1_dy7ssId6l6nBfFwBnVsuw?pwd=kxi9 提取码:kxi9
或者https://sourceforge.net/projects/esp8266-arduino-core.mirror/files/3.1.2/esp8266-3.1.2.zip/download
下载后解压至%LOCALAPPDATA%/Arduino15/packages/,并重命名"esp8266-3.1.2"为"esp8266"
文件结构如下:
然后再搜索"ESP8266",点击 "Install(安装)"
(3)使用ESP-01S专用烧录器将ESP-01S与PC连接,在设备管理器确定端口,在开发板列表中找到“Generic ESP8266 Module”,选择对应端口连接并烧录。
示例代码:
#include <ESP8266WiFi.h>
#define RELAY 0 //connected to GPIO0
const char *ssid = "01"; // Enter your router or WiFi SSID here
const char *password = "12345678"; // Enter your router or WiFi password here
WiFiServer server(80);
void setup()
{
Serial.begin(115200);
pinMode(RELAY, OUTPUT); //Set GPIO0 to output mode.
digitalWrite(RELAY, HIGH); //Set the GPIO0 output level to high.
/* Connect to the WiFi network. */
Serial.println("");
Serial.print("Conneting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { // If the connection to WiFi fails, retry every 500 milliseconds.
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
/* Start the Server. */
server.begin();
Serial.println("Server started.");
/* Output of the IP address. */
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop()
{
/* Check whether a user has established a connection. */
WiFiClient client = server.available();
if (!client)
return;
/* Wait until the user sends data. */
Serial.println("new client.");
while (!client.available())
delay(1);
/* Reading the first line of the request. */
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();
/* Assignment of the request. */
int value = HIGH;
if (request.indexOf("/RELAY=ON") != -1) {
Serial.println("RELAY=ON");
digitalWrite(RELAY, LOW);
value = LOW;
}
if (request.indexOf("/RELAY=OFF") != -1) {
Serial.println("RELAY=OFF");
digitalWrite(RELAY, HIGH);
value = HIGH;
}
/* Return the answer. */
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("");
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<meta name='viewport' content='width=device-width, inital-scale=1'>");
client.println("<head><title>ESP8266 RELAY Control</title></head>");
client.println("<style>");
client.println("* {text-align: center; font-family: Conso-las;}");
client.println("");
client.println(".container {position: absolute; top: 45%;");
client.println("left: 50%; transform: translateX(-50%) translateY(-50%);}");
client.println("");
client.println(".inner {font-size: 40px;}");
client.println("");
client.println("a {display: inline-block; width: 300px; height: 100px;");
client.println("color: #FFFF00; background-color: #275C6B;");
client.println("margin-top: 20px; padding: 10px 20px;");
client.println("text-decoration: none; border-radius: 5px;");
client.println("font-weight: 800; font-size: 70px;}");
client.println("</style>");
client.println("<div class='container'>");
client.println("<div class='inner'>");
client.print("RELAY if now: ");
if (value == HIGH)
client.print("OFF");
else
client.print("ON");
client.println("<br>");
client.println("<a href=\"/RELAY=OFF\">OFF</a>");
client.println("<a href=\"/RELAY=ON\">ON</a>");
client.println("<style>");
client.println(".footer-text { font-size: 25px; }");
client.println(".bold-text { font-weight: bold; }");
client.println("</style>");
client.println("<div class='footer'>");
client.println("<p class='footer-text'>This software was written by <span class='bold-text'>ESP-01S</span>.</p>");
client.println("</div>");
client.println("</div>");
client.println("</html>");
client.println("");
}
坑2:烧录时提示A fatal esptool.py error occurred: Cannot configure port, something went wrong. Original message: PermissionError(13, '����ϵͳ�ϵ��豸û�з������á�', None, 31)
解决方法:降级自动安装的CH430驱动,下载并打开程序,先卸载再安装。
下载地址:https://sparks.gogo.co.nz/assets/_site_/downloads/CH34x_Install_Windows_v3_4.zip
成功后可通过获取的IP(如192.168.3.250)进行开关控制。
二、安信可小安派BW21-CBV-Kit配置
打开文件—>示例—>AmebaNN—>RTSPFaceRecognition
以此为基础进行修改
示例代码:
/*
Example guide:
https://www.amebaiot.com/en/ameb ... k-face-recognition/
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
Remove face: "DEL={Name}" Remove a registered face
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
NN Model Selection
-------------------
Select Neural Network(NN) task and models using modelSelect(nntask, objdetmodel, facedetmodel, facerecogmodel).
Replace with NA_MODEL if they are not necessary for your selected NN Task.
NN task
=======
OBJECT_DETECTION/ FACE_DETECTION/ FACE_RECOGNITION
Models
=======
YOLOv3 model DEFAULT_YOLOV3TINY / CUSTOMIZED_YOLOV3TINY
YOLOv4 model DEFAULT_YOLOV4TINY / CUSTOMIZED_YOLOV4TINY
YOLOv7 model DEFAULT_YOLOV7TINY / CUSTOMIZED_YOLOV7TINY
SCRFD model DEFAULT_SCRFD / CUSTOMIZED_SCRFD
MobileFaceNet model DEFAULT_MOBILEFACENET/ CUSTOMIZED_MOBILEFACENET
No model NA_MODEL
*/
#include <OTA.h>
#include <HttpClient.h>
#include "WiFi.h"
#include "StreamIO.h"
#include "VideoStream.h"
#include "RTSP.h"
#include "NNFaceDetectionRecognition.h"
#include "VideoStreamOverlay.h"
#define CHANNEL 0
#define CHANNELNN 3
// Customised resolution for NN
#define NNWIDTH 576
#define NNHEIGHT 320
VideoSetting config(VIDEO_FHD, 30, VIDEO_H264, 0);
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[] = "01"; // your network SSID (name)
char pass[] = "12345678"; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
OTA ota;
WiFiClient wifiClient;
int port = 3000;
char* server = "192.168.3.248";
char* kHostname = "192.168.3.250";
char* kPath = "/RELAY=ON/";
// Number of milliseconds to wait without receiving any data before we give up
const int kNetworkTimeout = 30 * 1000;
// Number of milliseconds to wait if no data is available before trying again
const int kNetworkDelay = 1000;
IPAddress ip;
int rtsp_portnum;
void setup()
{
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);
// 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.videoInit();
// Configure RTSP with corresponding video format information
rtsp.configVideo(config);
rtsp.begin();
rtsp_portnum = rtsp.getPort();
// Configure Face Recognition model
// Select Neural Network(NN) task and models
facerecog.configVideo(configNN);
facerecog.modelSelect(FACE_RECOGNITION, CUSTOMIZED_MOBILEFACENET, CUSTOMIZED_SCRFD, CUSTOMIZED_MOBILEFACENET);
facerecog.begin();
facerecog.setResultCallback(FRPostProcess);
// Configure StreamIO object to stream data from video channel to RTSP
videoStreamer.registerInput(Camera.getStream(CHANNEL));
videoStreamer.registerOutput(rtsp);
if (videoStreamer.begin() != 0) {
Serial.println("StreamIO link start failed");
}
// Start data stream from video channel
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();
Serial.println("Connected to wifi");
printWifiStatus();
ota.start_OTA_threads(port, server);
}
void loop()
{
if (Serial.available() > 0) {
String input = Serial.readString();
input.trim();
if (input.startsWith(String("REG="))) {
String name = input.substring(4);
facerecog.registerFace(name);
} else if (input.startsWith(String("DEL="))) {
String name = input.substring(4);
facerecog.removeFace(name);
} else if (input.startsWith(String("RESET"))) {
facerecog.resetRegisteredFace();
} else if (input.startsWith(String("BACKUP"))) {
facerecog.backupRegisteredFace();
} else if (input.startsWith(String("RESTORE"))) {
facerecog.restoreRegisteredFace();
}
}
delay(2000);
OSD.createBitmap(CHANNEL);
OSD.update(CHANNEL);
}
// User callback function for post processing of face recognition results
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) {
for (int i = 0; i < facerecog.getResultCount(); i++) {
FaceRecognitionResult item = results;
// Result coordinates are floats ranging from 0.00 to 1.00
// Multiply with RTSP resolution to get coordinates in pixels
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;
if (String(item.name()) == String("unknown")) {
osd_color = OSD_COLOR_RED;
} else {
osd_color = OSD_COLOR_GREEN;
}
// Draw boundary box
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, osd_color);
// Print identification text above boundary box
char text_str[40];
snprintf(text_str, sizeof(text_str), "Face:%s", item.name());
webpost();
OSD.drawText(CHANNEL, xmin, ymin - OSD.getTextHeight(CHANNEL), text_str, osd_color);
}
}
OSD.update(CHANNEL);
}
void webpost() {
if (wifiClient.connect(kHostname,80)) {
wifiClient.println("POST " + String(kPath) + " HTTP/1.1");
wifiClient.println("Host: " + String(kHostname));
wifiClient.println(); // 空行表示HTTP头部结束
Serial.println("Data sent to ESP");
} else {
Serial.println("Failed to connect to ESP");
}
wifiClient.stop(); // 关闭连接
}
void printWifiStatus()
{
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
实现在识别到人脸时向ESP-01S模块发送RELAY=ON,打开继电器。
由于设置了OTA,需要搭配TF卡运行。TF卡文件如下:
文件夹及文件名固定,可使用默认文件,可在类似C:\Users\Administrator\AppData\Local\Arduino15\packages\realtek\tools\ameba_pro2_tools\1.4.1文件夹找到。
实现效果:
|