below is the code i used to play multiple videos in parallel using multi threading pool. but only one video is playing for each input. i want each video to open separately. not combined
import concurrent.futures
RTSP_URL = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4"
RTSP_List = [RTSP_URL, RTSP_URL, RTSP_URL, RTSP_URL]
def url_to_video(url):
video = cv2.VideoCapture(url)
while True:
_, frame = video.read()
cv2.imshow("RTSP", frame)
k = cv2.waitKey(1)
if k == ord('q'):
break
video.release()
cv2.destroyAllWindows()
while True:
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.map(url_to_video, RTSP_List)```
how to play each video separately.
you just need each thread to use a different name for the window in cv2.imshow, so that each thread will generate a different window, and you should place them somewhere distinct so that they aren't appearing one over the other, i just added in index to them so that each distinct index will have a position on screen and different title, also you shouldn't destroy all windows when one is done ...
import concurrent.futures
import cv2
RTSP_URL = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4"
RTSP_List = [(RTSP_URL,0), (RTSP_URL,1), (RTSP_URL,2), (RTSP_URL,3)]
def url_to_video(tup):
url,index = tup
video = cv2.VideoCapture(url)
while True:
_, frame = video.read()
cv2.imshow(f"RTSP {index}", frame)
cv2.moveWindow(f"RTSP {index}", index*300, 0)
k = cv2.waitKey(1)
if k == ord('q'):
break
video.release()
while True:
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.map(url_to_video, RTSP_List)
cv2.destroyAllWindows()
Related
This is the process I am trying to achieve :
Live Stream is captured from webcam and the Image frames are stored in a particular folder.
Now, If I give a trigger the frames in that folder at that moment should be converted into a video and get saved with name eg. video1.mp4.
Now again if I press a trigger another video should be saved as video2.mp4.
I have attached the code here . If I press R , it is saving one video as a0.mp4 . But If I press again, nothing seems to happen.
def frametovideo(img_array):
for i in range(len(img_array)):
out.write(img_array[i])
if name == "main":
img_array = []
videono = 0
cap = cv2.VideoCapture(0)
for filename in glob.glob('./output/*.jpg'):
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width,height)
img_array.append(img)
path = 'a' + str(videono) + '.mp4'
out = cv2.VideoWriter(path,cv2.VideoWriter_fourcc(*'mp4v'), 15, size)
while True:
ret, frame = cap.read()
if ret == True:
cv2.imshow("frame",frame)
k = cv2.waitKey(5) & 0xff
if k == ord('r'):
frametovideo(img_array)
videono += 1
You do not understanding how to save filenames Do not used operator. Used string format python 3.8 or later. Try this in below. Actually, you can modified key press.
import cv2
import os
i = 1
wait = 0
video = cv2.VideoCapture(0)
while video.isOpened():
ret, img = video.read()
cv2.imshow('live video', img)
# wait for user to press any key
key = cv2.waitKey(100)
# wait variable is to calculate waiting time
wait = wait+100
if key == ord('q'):
break
# when it reaches to 5000 milliseconds
# we will save that frame in given folder
if wait == 5000:
filename = f'Frame_{str(i)}.jpg'
# Save the images in given path
cv2.imwrite(filename, img)
i += 1
wait = 0
# close the camera
video.release()
# close open windows
cv2.destroyAllWindows()
Btw,look in line #27-34. Correct way to do this if __name__ == "__main__":
The code below shows the face and produces an output using voices. The problem is I'm unable to stop the voices, I want it to say it only once not for each frame taken
P.S I've tried using a timer but it didn't work.
import cv2
import pyttsx3
cap = cv2.VideoCapture(0)
voiceEngine = pyttsx3.init()
while(True):
# Capture frame-by-frame
success, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if success:
voiceEngine.say("hello there")
voiceEngine.runAndWait()
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == 27:
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
This is what flags are for.
said = False
while True:
...
if success and not said:
voiceEngine.say("hello there")
voiceEngine.runAndWait()
said = True
Every 10 seconds, I capture a new image using my igmcap() function and store it in the direction folder Captures. I want my identify() function to run on the latest image captured. Is the best way to do this to wrap all of the functions inside of a single loop?
Python Code:
def imgcap():
cap = cv2.VideoCapture(0)
framerate = cap.get(10)
x=1
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
if ret:
# Our operations on the frame come here
filename = 'Captures\\capture' + str(int(x)) + ".png"
x=x+1
cv2.imshow("frame", frame)
cv2.imwrite(filename, frame)
time.sleep(5)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
print("Ret False")
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
imgcap()
def identify(path):
cmd = f"darknet.exe detector test cfg/obj.data cfg/yolov4_test.cfg custom-yolov4-detector_best.weights -ext_output -out result.json {path}"
# cmd = f"darknet.exe detector test cfg/obj.data cfg/yolov4-tiny-custom.cfg custom-yolov4-tiny-detector_best.weights -ext_output -out result.json {path}"
os.chdir(r'C:\Yolo_v4\darknet\build\darknet\x64')
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = p.stdout.read()
print(out)
identify(r'C:\\Yolo_v4\\darknet\\build\\darknet\\x64\\Captures\\SOMETHING_GOES_HERE')
If you want to keep your functions independent, imgcap() could return the actual path to the capture so it can be used for subsequent analysis:
def imgcap():
# All your code goes here
...
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
return filename
If you are always going to run identify() on every new frame captured, it makes sense to make them part of the same loop, after the frame is saved.
I am trying to capture a frame from the webcam with the help of a thread, and then returning it through a queue. When I run the code, I get the return type as a np.array but when I display it I get a callback warning and not output.
import cv2
cap = cv2.VideoCapture(0)
import queue
import threading
def capture(out_queue):
while(True):
frame = cap.read()[1]
cv2.imshow('window', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
out_queue.put(frame)
break
my_queue_1 = queue.Queue()
t1 = threading.Thread(target=capture, args=(my_queue_1,))
t1.start()
t1.join()
ret1 = my_queue_1.get()
print(type(ret1))
cv2.imshow('returned', ret1)
cv2.destroyAllWindows()
cap.release()
I get the type as class 'numpy.ndarray' &
[ WARN:0] terminating async callback
EDIT: forgot to include cv2.waitkey(). problem solved
My IP camera seems to be a little unstable and disconnects randomly. I'd like my script to be able to determine when its disconnected and attempt to reconnect a few times, probably waiting 5-10 seconds between attempts. I've tried a few things, but nothing is working.
This is my basic script, when ret is false the script ends:
#!/usr/local/bin/python3
import cv2
import time
import datetime
print("start time: " + datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"))
cap = cv2.VideoCapture('rtsp://<ip><port>/live0.264')
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Confirm we have a valid image returned
if not ret:
print("disconnected!")
break
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
# Display the resulting frame
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
print("end time: " + time.strftime("%X"))
# When everything is done, release the capture
cap.release()
cv2.destroyAllWindows()
Edit: I would also like the script to try to reconnect to the camera in the event that my network goes down temporarily or anything like that as well.
I was finally able to solve this myself. Hopefully this is useful for anyone else looking to do the same thing.
This is actually a shell of a more complex script that has logic for motion detection and video recording when motion is detected. Everything is working very well with this basic logic (and my crappy IP camera) although I am still doing testing.
#!/usr/local/bin/python3
import cv2
import datetime
import time
def reset_attempts():
return 50
def process_video(attempts):
while(True):
(grabbed, frame) = camera.read()
if not grabbed:
print("disconnected!")
camera.release()
if attempts > 0:
time.sleep(5)
return True
else:
return False
recall = True
attempts = reset_attempts()
while(recall):
camera = cv2.VideoCapture("rtsp://<ip><port>/live0.264")
if camera.isOpened():
print("[INFO] Camera connected at " +
datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
attempts = reset_attempts()
recall = process_video(attempts)
else:
print("Camera not opened " +
datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
camera.release()
attempts -= 1
print("attempts: " + str(attempts))
# give the camera some time to recover
time.sleep(5)
continue
More detailed description:
https://github.com/Combinacijus/various-code-samples/tree/master/Python/OpenCV/ip_cam_reconnecting
Wrote a class to deal with IP camera disconnecting randomly. Main idea is to check if cap.read() returns a frame and if it doesn't it tries to reconnect to the camera.
import cv2
import requests # NOTE: Only used for forceful reconnection
import time # NOTE: Only used for throttling down printing when connection is lost
class IPVideoCapture:
def __init__(self, cam_address, cam_force_address=None, blocking=False):
"""
:param cam_address: ip address of the camera feed
:param cam_force_address: ip address to disconnect other clients (forcefully take over)
:param blocking: if true read() and reconnect_camera() methods blocks until ip camera is reconnected
"""
self.cam_address = cam_address
self.cam_force_address = cam_force_address
self.blocking = blocking
self.capture = None
self.RECONNECTION_PERIOD = 0.5 # NOTE: Can be changed. Used to throttle down printing
self.reconnect_camera()
def reconnect_camera(self):
while True:
try:
if self.cam_force_address is not None:
requests.get(self.cam_force_address)
self.capture = cv2.VideoCapture(self.cam_address)
if not self.capture.isOpened():
raise Exception("Could not connect to a camera: {0}".format(self.cam_address))
print("Connected to a camera: {}".format(self.cam_address))
break
except Exception as e:
print(e)
if self.blocking is False:
break
time.sleep(self.RECONNECTION_PERIOD)
def read(self):
"""
Reads frame and if frame is not received tries to reconnect the camera
:return: ret - bool witch specifies if frame was read successfully
frame - opencv image from the camera
"""
ret, frame = self.capture.read()
if ret is False:
self.reconnect_camera()
return ret, frame
if __name__ == "__main__":
CAM_ADDRESS = "http://192.168.8.102:4747/video" # NOTE: Change
CAM_FORCE_ADDRESS = "http://192.168.8.102:4747/override" # NOTE: Change or omit
cap = IPVideoCapture(CAM_ADDRESS, CAM_FORCE_ADDRESS, blocking=True)
# cap = IPVideoCapture(CAM_ADDRESS) # Minimal init example
while True:
ret, frame = cap.read()
if ret is True:
cv2.imshow(CAM_ADDRESS, frame)
if cv2.waitKey(1) == ord("q"):
break