【问题标题】:Mqtt publishing message when face is detected检测到人脸时 Mqtt 发布消息
【发布时间】:2018-09-19 16:20:56
【问题描述】:

我正在使用树莓派进行一个结合 MQTT 和人脸识别的大学项目。 首先,我想说的是,人脸识别在单独运行时可以正常工作,但是在将它与 MQTT 一起应用时,我遇到了一些问题。

在 Try 部分,当一个人被识别或未知时,它每 3 秒发布一次非常好。 奇怪的是,如果我把手放在摄像头前或超出范围,它会继续发送它识别到的最后一个人的 ID。

我希望它要么什么都不做,要么什么都不发布。

有解决此问题的想法或建议吗? 提前致谢

编辑 1:基本上,正如我所知道的,它必须在人脸识别部分做更多的事情。当使用 opencv 仅使用人脸识别代码时,它运行顺利。但是当我把手放在相机前或离开时,事情就变得复杂了,因为捕捉会在它看到的最后一件事上冻结,所以它会继续打印/发布相同的内容。还没有想出避免这种情况的方法。任何帮助将不胜感激

import cv2
import json
import time
import datetime as dt
import paho.mqtt.client as mqtt


detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
recognizer = cv2.face.LBPHFaceRecognizer_create()

broker = "*****"
port = *****
username = '*****'
password = '*****'


def on_connect(client, userdata, flags, rc):
    print("Connected with code: ", rc)
    client.subscribe('test/#')


def on_message(client, userdata, msg):
    print(str(msg.payload))


client = mqtt.Client("Python1")
client.on_connect = on_connect
client.on_message = on_message

client.username_pw_set(username, password)
client.connect(broker, port, 60)

client.loop_start()
time.sleep(1)


def facerecognizer():

    recognizer.read("trainerdir/training.yml")

    font = cv2.FONT_HERSHEY_SIMPLEX

    # Loading data

    with open('data.json', 'r') as f:
        names = json.load(f)

    # reverse the data
    # NOTE: for k, v !!
    # else it raises error !
    names = {v: k for k, v in names.items()}
    # print(names)
    print("[INFO] Face recognition is starting..")

    cap = cv2.VideoCapture(0)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 360)

    try:

        while True:

            ret, img = cap.read()

            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

            faces = detector.detectMultiScale(gray,
                                              scaleFactor=1.3,
                                              minNeighbors=5
                                              # minSize = (20,20)
                                              )

            for (x, y, w, h) in faces:
                cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)

                roi_gray = gray[y:y + h, x:x + w]
                roi_color = img[y:y + h, x:x + w]

                ID, confidence = recognizer.predict(roi_gray)

                if (confidence < 100):

                    ID = names[ID]

                    confidence = "{}%".format(round(100 - confidence))

                    while True:
                        client.publish("Tutorial/", ID + " " + str(dt.datetime.now()))
                        print('ID sent')
                        time.sleep(3)

                    else:
                        client.publish("Tutorial/", 'None')
                        print('ID sent')
                        time.sleep(3)

                    client.loop_forever()

                else:
                    ID = "Unkown"
                    confidence = "{}%".format(round(100 - confidence))
                    print(ID, dt.datetime.now())
                    while True:
                        client.publish("Tutorial/", ID + " " + str(dt.datetime.now()))
                        print('ID sent')
                        time.sleep(3)
                    else:
                        client.publish("Tutorial/", 'None')
                        print('ID sent')
                        time.sleep(3)

                    client.loop_forever()

    # except UnboundLocalError:
    #     print("Error occured. Exitting..")

    except KeyboardInterrupt:
        pass
    except KeyError as K:
        print(K)
        print('[INFO] Name Value is a string and not an integer')

    print("[INFO] Exiting program..")
    cap.release()

【问题讨论】:

    标签: python opencv raspberry-pi mqtt paho


    【解决方案1】:

    从 mqtt 客户端的文档中,您似乎误用了 client.loop_forever() 方法。

    http://www.steves-internet-guide.com/loop-python-mqtt-client/

    TLDR

    • 在循环中使用client.loop(timeout) 来控制更新处理。
    • 使用client.loop_start() 启动一个新线程,为您处理更新。
    • 使用client.loop_forever() 阻止和处理更新。

    由于您已经拨打了client.loop_start(),您无需拨打loop_forever()。从您的代码中删除这些调用应该可以解决问题。

    旁注:您的 time.sleep(3) 调用可以移动到循环的末尾,因为无论它采用哪种条件路径,它都应该发生。

    【讨论】:

    • 试过这个人,但它似乎不起作用。在对此进行故障排除时,我发现它与视频捕获有关。一旦没有显示人脸,例如,如果我离开相机的范围,捕获就会冻结,因此客户端会收到相同的内容,直到再次出现人脸。它导致始终发送相同的消息
    • 在这种情况下,我认为您应该尝试将time.sleeploop_forever 移动到与for (x, y, w, h) in faces: 相同的级别,并确保这是您真正想要做的.由于该错误仅在有 0 个面时发生,因此在该循环中发生的处理中一定存在不匹配,并且每次迭代都需要在 while True: 循环中发生什么。
    • 我已将解决方案发布给我的问题人,谢谢您的建议
    【解决方案2】:

    通过使用 if True: 而不是 while True: 我修复了它。我还删除了 subclient.loop_forever() 并且它工作正常。 这是与我发布到我的问题的代码不同的示例代码

       for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
    
            roi_gray = gray[y:y + h, x:x + w]
            # roi_color = img[y:y + h, x:x + w]
    
            ID, confidence = recognizer.predict(roi_gray)
    
            # 0 is 100% accuracy , and 100 is 0% accuracy
            if (confidence < 100):
    
                ID = names[ID]
                if True:
    
                    subclient.publish("project/IDReceiver", ID + " " + str(dt.datetime.now()))
    
                    print('ID sent')
                    time.sleep(3)
    
                # subclient.loop_forever()
    
            else:
                ID = "Unknown"
                if True:
    
                    subclient.publish("project/IDReceiver", "Unknown " + str(dt.datetime.now()))
    
                    print('ID sent')
                    time.sleep(3)
    

    【讨论】:

    • 干得好!仅供参考,if True: 语句是不必要的,将始终评估以下语句。
    猜你喜欢
    • 1970-01-01
    • 2013-09-24
    • 2022-06-14
    • 2017-07-30
    • 2021-08-27
    • 1970-01-01
    • 2019-11-18
    • 2019-02-27
    • 2015-02-10
    相关资源
    最近更新 更多