pythonopencvwinsound

Behaviour of createBackgroundSubtractorMOG2 function in opencv


I am trying to create a motion detecting alarm by using the cv2.createBackgroundSubtractorMOG2() function to check for moving objects and sound an alarm. This is my code:

import cv2
import numpy as np
import winsound


kernel=np.ones((5,5),np.uint8)
cap=cv2.VideoCapture(0)
fgbg=cv2.createBackgroundSubtractorMOG2()
while True:
    ret,frame=cap.read()
    fgmask=fgbg.apply(frame)  #creates binary image of moving objects
    fgmask=cv2.erode(fgmask,kernel,iterations=1)  #erosion to remove noise
    counter=np.sum(fgmask==255)  # counts the number of white pixels in the mask
    cv2.imshow('img',fgmask)
    cv2.imshow('frame',frame)
    print(counter)
    if counter>50:  #sounds an alarm if the number of white pixels is greater than a certain limit
        winsound.Beep(1000,2000)
        print("beep")

    if (cv2.waitKey(1) & 0xFF)==ord('q'):
        break
cap.release()

The problem is caused as the program is paused for 2 seconds when the winsound.Beep function is called and after it resumes the program glitches and repeatedly starts beeping.

If I remove the winsound.Beep function the program works as expected. Why does this happen?


Solution

  • The reason you're experiencing such problem is because winsound.Beep(1000,2000) is a blocking operation and should be runned on a separate thread.

    In order for you to accomplish what you're trying to do, here the working code:

    import cv2
    import numpy as np
    import winsound
    import threading 
    
    kernel=np.ones((5,5),np.uint8)
    cap=cv2.VideoCapture(0)
    fgbg=cv2.createBackgroundSubtractorMOG2()
    
    def playSound():
        winsound.Beep(1000,2000)
    
    while True:
    
        ret,frame=cap.read()
        fgmask=fgbg.apply(frame)  
        fgmask=cv2.erode(fgmask,kernel,iterations=1)  
        counter=np.sum(fgmask==255)  
    
        cv2.imshow('img',fgmask)
        cv2.imshow('frame',frame)
    
        if counter>50:  
            # Run the playSound function on a separate thread 
            t = threading.Thread(target=playSound)
            t.start()            
    
        if (cv2.waitKey(1) & 0xFF)==ord('q'):
            break
    
    cap.release()
    

    Hope this helps