Home > Back-end >  How to run a command once when a face was detected in OpenCV
How to run a command once when a face was detected in OpenCV

Time:06-20

I am trying to make it so when a face was detected, it would run a python command once instead of spamming it, for example print()

try:
    import cv2

    cap = cv2.VideoCapture(0)
    pTime = 0
    cascPath=os.path.dirname(cv2.__file__) "/data/haarcascade_frontalface_default.xml"
    faceCascade = cv2.CascadeClassifier(cascPath)

    face_detected = True

    while True:
        success, img = cap.read()
        img = cv2.flip(img, 1)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        cTime = time.time() 
        fps = 1 / (cTime - pTime)
        pTime = cTime
        face_count = 0

        cv2.putText(img, f'FPS:{int(fps)}', (20, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.1,
            minNeighbors=5,
            minSize=(30, 30),
            flags=cv2.CASCADE_SCALE_IMAGE
        )
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x w, y h), (0, 255, 0), 2)
            face_count = face_count 1
                
            cv2.putText(img, 'Face num ' str(face_count), (x-10, y-10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(img, f'Faces Detected: {face_count}', (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

      
        if face_count > 0: # If one or more faces were detected
            print("a face was detected")
        elif face_count == 0: # If no faces were detected
            print("the face magically disappeared")

        cv2.imshow("Face Recognition", img)
        if cv2.waitKey(1) & 0xFF == ord(' '):
            cv2.destroyAllWindows()
            break

except KeyboardInterrupt:
    print("[KeyboardInterrupt] Exiting...")
    time.sleep(2)
    exit()

how can i make while the face is detected, it prints only once instead of spamming (without using something like \r)

CodePudding user response:

You need to introduce state and react only when it changes.

Without copy-pasting your entire code, I'll just show you the idea.

# the state variable
seeing_faces = False

while True:
    frame = get_frame()
    faces = detect_faces(frame)
    there_are_faces_now = (len(faces) > 0)

    # compare state to current detection, different? state CHANGES
    if there_are_faces_now and not seeing_faces:
        print("NOW I see faces")
    elif seeing_faces and not there_are_faces_now:
        print("no longer seeing faces")
    else:
        # no change

    # update state
    seeing_faces = there_are_faces_now

CodePudding user response:

You can track the number of detected faces every frame and execute the command you want when the number of faces increases:

try:
    import cv2

    cap = cv2.VideoCapture(0)
    pTime = 0
    cascPath=os.path.dirname(cv2.__file__) "/data/haarcascade_frontalface_default.xml"
    faceCascade = cv2.CascadeClassifier(cascPath)

    face_detected = True
    currentFaces = 0

    while True:
        success, img = cap.read()
        img = cv2.flip(img, 1)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        cTime = time.time() 
        fps = 1 / (cTime - pTime)
        pTime = cTime
        face_count = 0

        cv2.putText(img, f'FPS:{int(fps)}', (20, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.1,
            minNeighbors=5,
            minSize=(30, 30),
            flags=cv2.CASCADE_SCALE_IMAGE
        )
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x w, y h), (0, 255, 0), 2)
            face_count = face_count 1
                
            cv2.putText(img, 'Face num ' str(face_count), (x-10, y-10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(img, f'Faces Detected: {face_count}', (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

        print(f"Faces Detected: {face_count}", end="\r")
      
        #if face_count > 0: # If one or more faces were detected
        #    print("a face was detected")
        #elif face_count == 0: # If no faces were detected
        #    print("the face magically disappeared")
        if face_count > currentFaces:
            print("Command to execute, face detected")
        currentFaces = face_count

        cv2.imshow("Face Recognition", img)
        if cv2.waitKey(1) & 0xFF == ord(' '):
            cv2.destroyAllWindows()
            break

except KeyboardInterrupt:
    print("[KeyboardInterrupt] Exiting...")
    time.sleep(2)
    exit()
  • Related