結合Mqtt&opencv人臉辨識讓伺服馬達動作
結合Mqtt&opencv人臉辨識讓伺服馬達動作
這個主題的意義主要是運用在人臉辨別門禁上,當然要真正用在門機的門禁要複雜一些,因為還要評估效能和穩定性,但原理上大致是如此。
按照步驟如下:
1.如何訓練出一張認識的臉
2.ESP32端
上傳至esp32
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <Servo.h>
WiFiClient espClient;
PubSubClient client(espClient);
const char* ssid="---";
const char* password="------";
const char* mqtt_server="192.168.--.--";
Servo myservo;
int pos = 20;
//如果連線至MQTT成功,即會開始接收訂閱的主題
void reconnect(){
while (! client.connected()){
Serial.print("Attempting MQTT connection...");
if (client.connect("esp32Client")){
Serial.println("connected");
client.subscribe("door/close"); //伺服馬達
}else {
Serial.print("failed connected is : ");
Serial.println(client.state());
delay(2000);
}
}
}
//當訂閱成功後,callback開始監聽broker的發送主題的訊息
void callback(char *topic, byte *message, unsigned int length){
String msgList;
Serial.print("topic:");
Serial.println(topic);
for (int i=0; i<length; i++){
Serial.print(char(message[i]));
msgList+=char(message[i]);
}
Serial.println();
//依收到的訊息來做相應的收受端動作
if (String(topic)=="door/close"){
if (msgList=="1"){
Serial.println("open_door");
myservo.write(170);
delay(200);
myservo.write(pos);
}
}
}
void setup() {
Serial.begin(115200);
myservo.attach(9); //初始化伺服馬達
myservo.write(pos);
//wifi連線
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED){
delay(50);
Serial.print(".");
}
Serial.println("connected successful");
Serial.println(WiFi.localIP());
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (! client.connected()){
reconnect();
}
client.loop();
}
2.python發布Mqtt
import cv2
import numpy
from PIL import Image, ImageDraw, ImageFont
# 發布者(publisher)指令稿 publisher1.py
import paho.mqtt.client as mqtt
# 建立 MQTT Client 物件
client = mqtt.Client()
# 連線至 MQTT 伺服器(伺服器位址,連接埠)
client.connect("192.168.76.155", 1883)
# 解决cv2.putText绘制中文乱码
def cv2ImgAddText(img2, text, left, top, textColor=(0, 0, 255), textSize=20):
if isinstance(img2, numpy.ndarray): # 判断是否OpenCV图片类型
img2 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
# 创建一个可以在给定图像上绘图的对象
draw = ImageDraw.Draw(img2)
# 字体的格式
fontStyle = ImageFont.truetype(r"C:\WINDOWS\FONTS\MSYH.TTC", textSize, encoding="utf-8")
# 绘制文本
draw.text((left, top), text, textColor, font=fontStyle)
# 转换回OpenCV格式
return cv2.cvtColor(numpy.asarray(img2), cv2.COLOR_RGB2BGR)
def face_detection(cv2ImgAddText):
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('AIot/train/train.yml')
cascadePath = "AIot/haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath)
font = cv2.FONT_HERSHEY_SIMPLEX
num = 0
names = ['邱定凱']
cam = cv2.VideoCapture(0)
minW = 0.1*cam.get(3)
minH = 0.1*cam.get(4)
while True:
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5,
minSize=(int(minW), int(minH))
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
num, confidence = recognizer.predict(gray[y:y + h, x:x + w])
name = names[num]
if confidence < 100:
if name=="邱定凱":
client.publish("door/opening","1")
print(name)
# confidence = "{0}%".format(round(100 - confidence))
# confidence = format(round(100 - confidence))
else:
name == "不認識的臉孔"
client.publish("door/opening","0")
print(name)
# confidence = "{0}%".format(round(100 - confidence))
# confidence = format(round(100 - confidence))
# 解决cv2.putText绘制中文乱码
img = cv2ImgAddText(img, name, x + 5, y - 30)
# cv2.putText(img, name, (x + 5, y - 5), font, 1, (0, 0, 255), 1) 无法显示中文
# cv2.putText(img, str(confidence.encode('utf-8')), (x+5, y+h-5), font, 1, (0, 0, 0), 1)
cv2.imshow('camera', img)
k = cv2.waitKey(5)
if k == ord('q'):
break
cam.release()
cv2.destroyAllWindows()
if __name__=='__main__':
face_detection(cv2ImgAddText)



留言
張貼留言