简体   繁体   中英

How can I run a function every specific time within a while cycle on python?

I'm working in a project with OCR using a webcam. I would like to know how can I run a function every 3 seconds (for example) while the principal code still running. The code is very long. So I use the following to exemplify:

import cv2

cap = cv2.VideoCapture(0)

def capture():
    cv2.imwrite("frame.jpg", frame)

while(1):
    ret, frame = cap.read()
    cv2.imshow('Webcam', frame)
    (_, cnt, _) = cv2.findContours(frame, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    if len(cnt) > 10:
        # here I want to call capture() function every 3 seconds

    if cv2.waitKey(1) & 0xFF == ord('x'):
        break

cap.release()
cv2.destroyAllWindows()

I used time.sleep(3) after the statments of capture() function but it pause the continuous capture of the frame. I don't want it. I need something like a software interruption. When the flag shoots, the code of function run but the while cycle continues working.

I'm using python 2.7 on Windows 7.

I hope you understand my purpose. I rode about daemon and threads but I can't interpret so much.

Probably best to do this with threads ( see multiprocessing ), but easy solution below

Note: Does not fire exactly every 3 seconds as opencv functions take time and probably wait for your webcam to give frames.

Note 2: If not using any kind of multi threading your OCR code WILL block your webcam captures, so make your OCR fast or look into above link.

from time import time

t = time() # starting time

while(1):
    # do stuff

    t_current = time() # current time

    # if more than 3 seconds passed:
    if t_current - t > 3:
        t = t_current
        # do other stuff

Here is a rather simple solution using threads. You mentioned about not able to exit the app using ctrl-C. This is because the thread is a separate task and you will have to hit ctrl-C again to kill that thread. To fix it, I've catched KeyboardInterrupt and stopped the task accordingly. Try this out. The code is pretty self-explanatory, but let me know in case you have any doubts.

import threading
import cv2

exitTask = False
def threadTask():
    global frame
    if not exitTask:
        threading.Timer(1.0, threadTask).start()
        cv2.imwrite("Threads.jpg", frame)
        print "Wrote to file"

cap = cv2.VideoCapture(0)

try:
    ret, frame = cap.read()
except Exception as err:
    print err
    exit(0)

threadTask()

while(True):
    try:
        ret, frame = cap.read()
        cv2.imshow("Cam", frame)
        cv2.waitKey(1)
    except KeyboardInterrupt:
        exitTask = True
        cv2.destroyAllWindows()
        exit(0)

You can use it like this

import cv2
import threading
import time

cap=cv2.VideoCapture(0)

main_loop_running = True
def capture():
    global main_loop_running, frame
    while (main_loop_running):
        cv2.imwrite("frame.jpg", frame)
        time.sleep(3)

ret, frame = cap.read()
cv2.imshow('Webcam', frame)
child_t = threading.Thread(target=capture)
child_t.setDaemon(True)
child_t.start()

while(1):
    ret, frame = cap.read()
    cv2.imshow('Webcam', frame)

    # here I want to call capture() function every 3 seconds

    if cv2.waitKey(1) & 0xFF == ord('x'):
        break

main_loop_running = False
child_t.join()

cap.release()
cv2.destroyAllWindows()

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