how to fix opencv video freeze few second when sound play? - python

i try create application motion detector, when detected will play alarm. the program is running but the problem is when sound play video will freeze few second. so how to fix that?
I was tired of looking for references, but couldn't find anything.
import cv2
import numpy as np
import os
from playsound import playsound
# Video Capture
capture = cv2.VideoCapture(1)
fgbg = cv2.createBackgroundSubtractorMOG2(50, 200, True)
# frame
frameCount = 0
while(1):
# frame value
ret, frame = capture.read()
# cek frame
if not ret:
break
frameCount += 1
# resize frame
resizedFrame = cv2.resize(frame, (0, 0), fx=0.50, fy=0.50)
# foreground
fgmask = fgbg.apply(resizedFrame)
# jumlah Pixel
count = np.count_nonzero(fgmask)
if (frameCount > 1 and count > 5000):
playsound('tune.mp3')
os.system('cls' if os.name == 'nt' else 'clear')
print('Frame: %d, Pixel Count: %d' % (frameCount, count))
cv2.imshow('Frame', resizedFrame)
cv2.imshow('Mask', fgmask)
k = cv2.waitKey(1)
if k == 27:
break
capture.release()
cv2.destroyAllWindows()

Unfortunately, opencv when You play a sound from playsound. Even if You try calling plahsound using threads it will still freeze.
However, You can use Pygame's Mixer, which doesn't interrupt opencv's window. You can play a sound by:
from pygame import mixer
mixer.init()
sound = mixer.Sound('mysound.ogg')
sound.play()
However, I think Pygame's mixer is incompatible with mp3 files. You might wanna use .wav instead, or convert your mp3 file to .ogg format.

Related

Video Screen Capture using python and OpenCv and video not opening

importing the required packages
`import pyautogui
import cv2
import numpy as np`
Specify resolution
`resolution = (1920, 1080)`
Specify video codec
`codec = cv2.VideoWriter_fourcc(*"XVID")`
Specify frames rate. We can choose any
value and experiment with it
`fps = 60.0`
Creating a VideoWriter object
`out = cv2.VideoWriter("Recording.avi", codec, fps, resolution)`
Create an Empty window
`cv2.namedWindow("Live", cv2.WINDOW_NORMAL)`
# Resize this window
`cv2.resizeWindow("Live", 480, 270)`
`while True:
# Take screenshot using PyAutoGUI
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
# Optional: Display the recording screen
cv2.imshow('Live', frame)
# Stop recording when we press 'Esc'
k = cv2.waitKey(10) & 0xFF # press 'Esc' to exit
if k == 27:
break
# Release the Video writer
out.release()
# Destroy all windows
cv2.destroyAllWindows()`
the video was successfully but in the end I could not open the video file "Recording.avi" or to be specific my video player won't play it
any help?

How can I achieve a 30 FPS frame rate using this Python screen recorder code?

I want a screen recorder. I thought of making my own.
I checked the internet and found: https://www.thepythoncode.com/code/make-screen-recorder-python
The Code:
import cv2
import numpy as np
import pyautogui
# Display screen resolution, get it from your OS settings
SCREEN_SIZE = (1366, 768)
# Define the codec
fourcc = cv2.VideoWriter_fourcc(*"XVID")
# Create the video write object
out = cv2.VideoWriter("output.avi", fourcc, 30.0, (SCREEN_SIZE))
while True:
# make a screenshot
img = pyautogui.screenshot()
# img = pyautogui.screenshot(region=(0, 0, 300, 400))
# convert these pixels to a proper numpy array to work with OpenCV
frame = np.array(img)
# convert colors from BGR to RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# write the frame
out.write(frame)
# show the frame
cv2.imshow("screenshot", frame)
# if the user clicks q, it exits
if cv2.waitKey(1) == ord("q"):
break
# Make sure everything is closed when exited
cv2.destroyAllWindows()
out.release()
The Problem:
When I run this, this works good. But it has a random speed after output. The fps is 30 but when I record for 1 minute, the video is 5 seconds or 10 minutes (random).
How do I make this recorder give output in 30 fps with the correct speed?
basically if you want to continue with your same code, you will have to compromise on resolution or frame rate.
My suggestion is to try the cv2.VideoCapture() functionality.
I am attaching the link to the webpage where there is a detailed step-by-step process where the author has achieved an FPS rate of 30.75.
Here's the link:
https://www.pyimagesearch.com/2017/02/06/faster-video-file-fps-with-cv2-videocapture-and-opencv/
The second half of the content present in the link has The faster, threaded method to reading video frames with OpenCV.
# import the necessary packages
from imutils.video import FileVideoStream
from imutils.video import FPS
import numpy as np
import argparse
import imutils
import time
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", required=True,
help="path to input video file")
args = vars(ap.parse_args())
# start the file video stream thread and allow the buffer to
# start to fill
print("[INFO] starting video file thread...")
fvs = FileVideoStream(args["video"]).start()
time.sleep(1.0)
# start the FPS timer
fps = FPS().start()
# loop over frames from the video file stream
while fvs.more():
# grab the frame from the threaded video file stream, resize
# it, and convert it to grayscale (while still retaining 3
# channels)
frame = fvs.read()
frame = imutils.resize(frame, width=450)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = np.dstack([frame, frame, frame])
# display the size of the queue on the frame
cv2.putText(frame, "Queue Size: {}".format(fvs.Q.qsize()),
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# show the frame and update the FPS counter
cv2.imshow("Frame", frame)
cv2.waitKey(1)
fps.update()
# stop the timer and display FPS information
fps.stop()
print("[INFO] elasped time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
# do a bit of cleanup
cv2.destroyAllWindows()
fvs.stop()

uninterrupted while loop with python cv2.VideoCapture() and string input

I use this code to capture and display the input from my webcam.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
check, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
I have a barcode scanner and want to check inside the while loop if a specific string gets scanned in.
input() interupts the stream from the webcam. I need something like cv2.waitKey() but for strings
while(True):
check, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitString(barcode) == '123456':
# do something
if cv2.waitString(barcode) == '098765':
# do something else
I tried msvcrt, but to no avail. The stream continues but nothing gets printed.
if msvcrt.kbhit():
if msvcrt.getwche() == '280602017300':
print("Barcode scanned!")
Or is there a way to skip input() until something was entered?
UPDATE
Making some progress with the help of this post.
How to read keyboard-input?
I was able to update my code.
import threading
import queue
import time
import numpy as np
import cv2
def read_kbd_input(inputQueue):
print('Ready for keyboard input:')
while (True):
input_str = input()
inputQueue.put(input_str)
def main():
inputQueue = queue.Queue()
inputThread = threading.Thread(target=read_kbd_input, args=(inputQueue,), daemon=True)
inputThread.start()
cap = cv2.VideoCapture(0)
font = cv2.FONT_HERSHEY_DUPLEX
fontScale = 1
fontColor = (255,255,255)
lineType = 2
input_str = "test"
while (True):
check, frame = cap.read()
if (inputQueue.qsize() > 0):
input_str = inputQueue.get()
if (input_str == '280602017300'):
print("do something")
cv2.putText(frame, input_str, (10,30), font, fontScale, fontColor, lineType)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
time.sleep(0.01)
print("End.")
if (__name__ == '__main__'):
main()
Now the only problem left is that my webcam stream is supposed to run in fullscreen. So the console will allways be in the background and therefore wont get the inputs form the keyboard or my barcode scanner.
need it the other way around

Save image stream with timestamp using OpenCV Python

I am using open CV, Python to save same camera Images in jpg and png format.
I am using timestamp to save the images in sequence. My code sample is following. But the problem is it only saves one image every time I execute. What will be the best solution to save the image stream with timestamp
import numpy as np
import cv2
import time
camera = cv2.VideoCapture(0)
time = time.time() #timestamp
def saveJpgImage(frame):
#process image
img_name = "opencv_frame_{}.jpg".format(time)
cv2.imwrite(img_name, frame)
def savePngImage():
#process image
img_name = "opencv_frame_{}.png".format(time)
cv2.imwrite(img_name, frame)
def main():
while True:
ret, frame = cam.read()
cv2.imshow("Camera Images", frame)
if not ret:
break
k = cv2.waitKey(1)
if k%256 == 27:
# ESC pressed
print("Escape hit, closing...")
break
elif k%256 == 32:
saveJpgImage(frame)
savePngImage(frame)
if __name__ == '__main__':
main()
You're testing when a key is pressed and calling the save function when it's pressed. If you want to call a video loop when the key is pressed please do so! (don't forget to include the escape method!)

Superimposing image over webcam feed using OpenCV 2.4.7.0 in Python 2.7

I am trying to superimpose an image over a camera feed in python. I can get an image to superimpose over another image, but when I apply the same thing to my camera feed it doesn't work. Here's my code so far:
#!/usr/bin/python
import cv2
import time
cv2.cv.NamedWindow("Hawk Eye", 1)
capture = cv2.cv.CaptureFromCAM(0)
cv2.cv.SetCaptureProperty(capture, cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 800)
cv2.cv.SetCaptureProperty(capture, cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 600)
x_offset=y_offset=50
arrows = cv2.imread("arrows.png")
while True:
webcam=cv2.cv.QueryFrame(capture)
#webcam[y_offset:y_offset+arrows.shape[0], x_offset:x_offset+arrows.shape[1]]=arrows
cv2.cv.ShowImage("Hawk Eye", webcam)
if cv2.cv.WaitKey(10) == 27:
break
cv2.cv.DestroyAllWindows()
If I uncomment:
img[y_offset:y_offset+arrows.shape[0], x_offset:x_offset+arrows.shape[1]]=arrows
the line that imposes the image, it shows just the camera feed, but when I add it in my loop it stops working. Thanks!
This works OK using the cv2 API:
import cv2
import time
cv2.namedWindow("Hawk Eye", 1)
capture = cv2.VideoCapture(0)
capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 800)
capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 600)
x_offset=y_offset=50
arrows = cv2.imread("hawk.png")
while True:
ret, webcam = capture.read()
if ret:
webcam[y_offset:y_offset+arrows.shape[0], x_offset:x_offset+arrows.shape[1]]=arrows
cv2.imshow("Hawk Eye", webcam)
if cv2.waitKey(10) == 27:
break
cv2.destroyAllWindows()

Categories