ESP32CAM 人脸识别追踪
阅读原文时间:2023年07月13日阅读:3

总体实现的流程:ESP32cam作为客户端,pc作为服务端通过mqtt协议建立通信,将采集的图像在电脑端显示人脸识别的方法使用的是opencv,并通过mqtt传输指令给esp32cam控制舵机云台转动。

客户端程序

#include
#include
#include
#include

const char* WIFI_SSID = "wifi的名称";
const char* WIFI_PASS = "wifi的密码";

WebServer server(80);

static auto loRes = esp32cam::Resolution::find(320, 240);
static auto hiRes = esp32cam::Resolution::find(800, 600);

void callback(char* topic, byte* payload, unsigned int length) ;

bool stopEngine = true;

//初始化mqtt类对象
WiFiClient espClient;
PubSubClient mqtt_client(espClient);

const char* mqttServer = "broker.emqx.io";
const int mqttPort = 1883;
const char* mqttUser = "";
const char* mqttPassword = "";

int servo_y = 8;
int servo_z = 9;
int servo_y_pin = 14;
int servo_z_pin = 13;
int pos_z = 90 , pos_y = 90;

void serveJpg()
{
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("CAPTURE FAIL");
server.send(503, "", "");
return;
}
//Serial.printf("CAPTURE OK %dx%d %db\n", frame->getWidth(), frame->getHeight(),
//static_cast(frame->size()));

server.setContentLength(frame->size());
server.send(200, "image/jpeg");
WiFiClient client = server.client();
frame->writeTo(client);
}

void handleJpgHi()
{
if (!esp32cam::Camera.changeResolution(hiRes)) {
Serial.println("SET-HI-RES FAIL");
}
serveJpg();
}

int calculatePWM( int degree)
{
const float deadZone = 6.4;
const float max = 32;
if (degree < 0) degree = 0; if (degree > 180)
degree = 180;
return ( int)(((max - deadZone) / 180) * degree + deadZone);
}

void mqtt_connet(){
mqtt_client.setServer(mqttServer,mqttPort);
mqtt_client.setCallback(callback);
while (!mqtt_client.connected()) {
Serial.println("Connecting to MQTT…");

if (mqtt\_client.connect(mqttServer, mqttUser, mqttPassword )) {

  Serial.println("connected");

} else {

  Serial.print("failed with state ");  
  Serial.print(mqtt\_client.state());  
  delay(2000);  
}  

}
mqtt_client.subscribe("POSITION");
}
void callback(char* topic, byte* payload, unsigned int length) {
String payloadStr = "";
for (int i=0; i<length; i++) {
payloadStr += (char)payload[i];
}
Serial.println(payloadStr);

if(payloadStr.equals("RIGHT")){
pos_z --;

}else if(payloadStr.equals("LEFT")){
pos_z ++;
}

if(payloadStr.equals("UP")){
pos_y --;

}else if(payloadStr.equals("DOWN")){
pos_y ++;
}

if(pos_z >= 180) pos_z = 180;
if(pos_z <= 0) pos_z = 0; if(pos_y >= 180) pos_y = 180;
if(pos_y <= 0) pos_y = 0;
Serial.printf("pos_z: %d pos_y: %d \n",pos_z,pos_y);
ledcWrite(servo_z,calculatePWM(pos_z));
ledcWrite(servo_y,calculatePWM(pos_y));
}

void setup()
{
Serial.begin(115200);
ledcSetup(servo_y, 50, 8);
ledcSetup(servo_z, 50, 8);
ledcAttachPin(servo_y_pin, servo_y);
ledcAttachPin(servo_z_pin, servo_z);

{
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(hiRes);
cfg.setBufferCount(2);
cfg.setJpeg(80);

bool ok = Camera.begin(cfg);  
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");  

}

WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

Serial.print("http://");
Serial.println(WiFi.localIP());
Serial.println(" /cam-hi.jpg");
server.on("/cam-hi.jpg", handleJpgHi);
mqtt_connet();
server.begin();
}

void loop()
{
server.handleClient();
mqtt_client.loop();

}

服务端程序

import cv2
import time
import urllib.request
import numpy as np
import paho.mqtt.client as mqtt

url='http://192.168.0.106/cam-hi.jpg'
cv2.namedWindow("Berhasil", cv2.WINDOW_AUTOSIZE)
face=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

mqttBroker = "broker.emqx.io"
client = mqtt.Client("Cleaning-Robot",clean_session=True,userdata=None)
client.connect(mqttBroker,1883)

while True:
imgresponse=urllib.request.urlopen(url)
start = time.time()
imgnp=np.array(bytearray(imgresponse.read()),dtype=np.uint8)
img=cv2.imdecode(imgnp,-1)
rows , cols , _ = img.shape
conter_x = (int)(rows / 2)
conter_y = (int)(cols / 2)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = face.detectMultiScale(gray,1.3,5)

for (x,y,w,h) in faces:  
    faces\_conter\_x = (int)(x + (w / 2))  
    faces\_conter\_y = (int)(y + (h / 2))  
    cv2.rectangle(img,(x,y), (x+w,y+h), (0,255,120),2)  
    cv2.putText(img,"face",(w+x,y+h),cv2.FONT\_HERSHEY\_PLAIN,2,(0,255,255),2)

    if(faces\_conter\_x > conter\_x):  
        client.publish("POSITION","RIGHT")  
        str\_x = str(conter\_x - faces\_conter\_x)  
        print("RIGHT" + str\_x)

    elif(faces\_conter\_x < conter\_x):  
        client.publish("POSITION","LEFT")  
        str\_x = str(faces\_conter\_y - conter\_y)  
        print("LEFT:" + str\_x)

    if(faces\_conter\_y > conter\_y):  
        client.publish("POSITION","DOWN")  
        str\_y = str(conter\_y - faces\_conter\_y)  
        print("DOWN:" + str\_y)

    elif(faces\_conter\_y < conter\_y):  
        client.publish("POSITION","UP")  
        str\_y = str(faces\_conter\_y - conter\_y)  
        print("UP:" + str\_y)

end = time.time()  
seconds = end - start  # 处理一帧所用的时间  
fps = 1 / seconds  # 一秒钟可以处理多少帧  
fps = "%.2f fps"%fps  
cv2.putText(img, fps, (5,50 ), cv2.FONT\_HERSHEY\_SIMPLEX, 0.75, (0, 0, 255), 1)

cv2.imshow("Berhasil",img)  
key=cv2.waitKey(30) & 0xff  
if key==27:  
    break

cv2.destroyAllWindows

总结:舵机控制不稳定,可采用好的控制算法解决。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章