How would I get the latest outputted file from Opencv - python

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.

Related

Save a video with different file name each time we give a Trigger in opencv

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__":

How to make pyttsx3 stop talking in real-time video capturing in python

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

Python: Automatically reconnect IP camera

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

OpenCV (Python) not updating frame when read() is called

I am trying to pull individual frames at specified times from an RTSP feed.
This works fine for video streaming:
vcap = cv2.VideoCapture(RTSP_URL)
while(1):
ret, frame = vcap.read()
cv2.imshow('VIDEO', frame)
cv2.waitKey(1)
But if I want to take an image every second and save it by doing something like this:
vcap = cv2.VideoCapture(RTSP_URL)
for t in range(60):
ret, frame = vcap.read()
if ret:
cv2.imwrite("{}.jpg".format(t), frame)
time.sleep(1);
Every image will look exactly the same as the first image. In every instance ret == True.
(Also this was working fine for me a week ago and then ipython did something that required me to do a re-install)
cv2.waitKey(1000) wouldn't do anything if you didn't show image with cv2.imshow(). Try:
vcap = cv2.VideoCapture(RTSP_URL)
for t in range(60):
ret, frame = vcap.read()
cv2.imwrite('{}.jpg'.format(t), frame)
# this will activate the waitKey funciton
cv2.imshow('preview', frame)
cv2.waitKey(1000)
On another note, iPython/jupyter doesn't play well with the cv2's imshow and the whole GUI functionality. If, for example, you can't break the loop by keypress
if (cv2.waitKey(1000) == 27 & 0xff): break;
Alright, after endless messing with it over the last few days, 1 second is not fast enough for the feed for whatever reason.
This will work:
vcap = cv2.VideoCapture(RTSP_URL)
for t in range(60):
ret, frame = vcap.read()
if ret and t % 1000 == 0:
cv2.imwrite("{}.jpg".format(t), frame)
time.sleep(0.001)

cv2.VideoCapture.read() gets old frame after time.sleep()

I tried to capture (stereo) images with Python's opencv and two cameras so therefore every 5 seconds an image should be saved. But the problem here is that an old frame is saved.
The minified code is as follows:
cap = cv2.VideoCapture(0)
for i in range(20):
time.sleep(5)
print "Taking image %d:" % i
ret, frame = cap.read()
cv2.imwrite("image %d" % i, frame)
print " image done." if ret else " Error while taking image..."
cap.release()
cv2.destroyAllWindows()
To check this, I changed the position of the camera after each taken image. But nevertheless an image from an old position is saved (actually not the same, but I assume some frames after the last saved image). After 5 (or more) images finally the captured location in the image does also change.
So, is there any problem with time.sleep? I guess that I'm not getting the actual frame, but a buffered one. If this is the case, how could I fix it and capture the actual frame?
VideoCapture is buffering.
If you always want the actual frame, do this:
while True:
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()
cv2.imshow(" ", frame)
if cv2.waitKey(2000) != -1:
break
you need to count the elapsed time, but not stop read frames. like this:
import cv2
import time
cap = cv2.VideoCapture(0)
preframe_tm = time.time()
i = 0
while True:
ret, frame = cap.read()
elapsed_time = time.time() - preframe_tm
if elapsed_time < 5:
continue
preframe_tm = time.time()
i += 1
print("Taking image %d:" % i)
cv2.imwrite("image_%d.jpg" % i, frame)
if i >= 20:
break
cap.release()
cv2.destroyAllWindows()

Categories