結合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)

Node-RED設定









留言

這個網誌中的熱門文章

讀取/儲存xlsx檔案-Node-RED

即時串流+拍照-node-red(作品-2)