pythonopencvcvzone

How to print every x seconds while rest of code runs without being stopped?


I've seen ways of using the time.sleep() function, however that stops the rest of the code from running.

I'm making a hand recognition script and want the video output to be hindered by a certain value being printed every second.

This is my code:

import cv2
from cvzone.HandTrackingModule import HandDetector
import time

cap = cv2.VideoCapture(0)
detector = HandDetector(maxHands=1, detectionCon=0.7)
length = 0
while True:
    success, img = cap.read()
    hands, img = detector.findHands(img)

    if hands:
        hand1 = hands[0]
        lmlist1 = hand1["lmList"]
        bbox = hand1["bbox"]
        cp1 = hand1["center"]
        HandType = hand1["type"]
        #fingers1 = detector.fingersUp(hand1)
        #print(fingers1)
        length, info, img = detector.findDistance(lmlist1[8], lmlist1[5], img)
        
    
    print(length)
    time.sleep(1)
        
    
    cv2.imshow("Image", img)
    cv2.waitKey(1) 
    if cv2.waitKey(1) == ord("q"):
        break
    

cap.release()
cv2.destroyAllWindows()

The problem is that because of:

print(length) 
time.sleep(1) 

the frame rate of the video is reduced to 1fps.

Is there a way to run the printing command so that it doesn't affect the frame rate?

Thanks.

EDIT

This is the new code and fps is still low on my computer.

import cv2
from cvzone.HandTrackingModule import HandDetector
import time
import threading
import math
#Resolution: 720 x 1280

cap = cv2.VideoCapture(0)

detector = HandDetector(maxHands=1, detectionCon=0.7)
length = 0

fingerpos = [1,1,1,1,1]

    
def index(img):
    
    lil, info, img = detector.findDistance(lmlist1[8], lmlist1[5], img)
    
    lib, info, img = detector.findDistance(lmlist1[6], lmlist1[5], img)
    
    lit, info, img = detector.findDistance(lmlist1[8], lmlist1[6], img)
    
    
    index_angle = (lib**2 + lit**2 - lil**2) / (2 * lib * lit)
    
    index_angle = math.degrees(math.acos(index_angle))
    return int(index_angle)

def middle(img):
    lml, info, img = detector.findDistance(lmlist1[12], lmlist1[9], img)
    
    lmb, info, img = detector.findDistance(lmlist1[12], lmlist1[10], img)
    
    lmt, info, img = detector.findDistance(lmlist1[10], lmlist1[9], img)
    
    
    middle_angle = (lmb**2 + lmt**2 - lml**2) / (2 * lmb * lmt)

    middle_angle = math.degrees(math.acos(middle_angle))
    return int(middle_angle)

def ring(img):

    lrl, info, img = detector.findDistance(lmlist1[16], lmlist1[13], img)
    
    lrb, info, img = detector.findDistance(lmlist1[16], lmlist1[14], img)
    
    lrt, info, img = detector.findDistance(lmlist1[14], lmlist1[13], img)
    
    
    ring_angle = (lrb**2 + lrt**2 - lrl**2) / (2 * lrb * lrt)
    
    ring_angle = math.degrees(math.acos(ring_angle))
    return int(ring_angle)

def pinky(img):
    lpl, info, img = detector.findDistance(lmlist1[20], lmlist1[17], img)
    
    lpb, info, img = detector.findDistance(lmlist1[20], lmlist1[18], img)
    
    lpt, info, img = detector.findDistance(lmlist1[18], lmlist1[17], img)
    
    
    pinky_angle = (lpb**2 + lpt**2 - lpl**2) / (2 * lpb * lpt)
    
    pinky_angle = math.degrees(math.acos(pinky_angle))
    return int(pinky_angle)

def thumb(img):
    ltl, info, img = detector.findDistance(lmlist1[4], lmlist1[2], img)
    
    ltb, info, img = detector.findDistance(lmlist1[4], lmlist1[3], img)
    
    ltt, info, img = detector.findDistance(lmlist1[3], lmlist1[2], img)
    
    
    thumb_angle = (ltb**2 + ltt**2 - ltl**2) / (2 * ltb * ltt)
    
    thumb_angle = math.degrees(math.acos(thumb_angle))
    return int(thumb_angle)

def data(img):
        
    print(str(thumb(img)) + ", " + str(index(img)) + ", " + str(middle(img)) + ", " + str(ring(img)) + ", " + str(pinky(img)))
    time.sleep(0.5)                

threading.Thread(target=data).start()    

while True:
    success, img = cap.read()
    #img = cv2.resize(img, (640, 420)) 
    hands, img = detector.findHands(img)
    
    #print('Resolution: ' + str(img.shape[0]) + ' x ' + str(img.shape[1]))
    if hands:
        hand1 = hands[0]
        lmlist1 = hand1["lmList"]
        bbox = hand1["bbox"]
        cp1 = hand1["center"]
        HandType = hand1["type"]
        
        data(img)
        #print(str(thumb(img)) + ", " + str(index(img)) + ", " + str(middle(img)) + ", " + str(ring(img)) + ", " + str(pinky(img)))
            
    cv2.imshow("Image", img)
    cv2.waitKey(1) 
    if cv2.waitKey(1) == ord("q"):
        break
    

cap.release()
cv2.destroyAllWindows()

Solution

  • One way is to use time.time to measure how much time has passed (will print 'hi' every 5 seconds or so, this is less precise because if some part of the loop takes more time, it may print later than expected):

    import time
    
    
    start = time.time()
    while True:
        # run some code
    
        current_time = time.time()
        if current_time - start >= 5:
            print('hi')
            start = current_time
    

    Or use threading module to run a loop concurrently (will print 'hi' every 5 seconds, this is also more precise, because the time measurement is not affected by the speed of the "main" loop (as is the case with the above code)):

    import time
    import threading
    
    
    def loop():
        while True:
            time.sleep(5)
            print('hi')
    
    
    threading.Thread(target=loop).start()
    
    while True:
        # run some code
        pass  # this can be removed after you add the actual code