简体   繁体   中英

How to call a function only once and wait for 5 seconds before calling again inside while loop- Python

I'm trying capture image and play a song when smile is detected on live camera feed. I have created a separate thread to play complete song and save image using multi-threading as frames were getting stuck when song was playing. The issue I am facing is that inside the infinite while loop, the multi-thread function is being called multiple times in a second resulting in overlapping of the song and many images being saved. Is there a better way to call that function once and wait for few seconds (5 seconds exactly) till song is finished without breaking/pausing the while loop? Here is the code I have worked on:

import cv2
import datetime
import threading
from playsound import playsound

def play_save(save_img):
    print("Saving Image")
    time_stamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    file_name = f'selfie-{time_stamp}.png'
    cv2.imwrite(file_name, save_img)
    print("Playing Song")
    playsound("Happy_birthday.mp3")

def main():
    face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    smile_cascade = cv2.CascadeClassifier('haarcascade_smile.xml')
    cap = cv2.VideoCapture(0)
    while True:
        ret, img = cap.read()
        frame = img.copy()
        if not ret:
            break
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
            roi_gray = gray[y:y + h, x:x + w]
            roi_color = img[y:y + h, x:x + w]
            smile = smile_cascade.detectMultiScale(roi_gray, 1.3, 25)
            for x1, y1, w1, h1 in smile:
                cv2.rectangle(img, (x1, y1), (x1 + w1, y1 + h1), (0, 0, 255), 2)
                multithread = threading.Thread(target=play_save, args=(frame,))
                multithread.start()

        cv2.imshow('Smile Birthday', img)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

An Idea is to use the UTC-Time to check it. You could make a check like this:

import time
time_function_done = None

while True:
    #Do some shit
    if (time_function_done + 5) < time.time():
        time_function_done = time.time()
        #Do your function
    #Do some other shit

If you can't find a direct solution, make a workaround. Hope this helps:))

import time

time.sleep(5) # Sleep for 5 seconds

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM