总体实现的流程: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
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
总结:舵机控制不稳定,可采用好的控制算法解决。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章