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

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)

Related

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

How would I get the latest outputted file from Opencv

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.

How to rewind a video in OpenCV Python in 2019?

I know there are many similar questions asked in 2012 or something.
It is 2019, and in 2012, the only solution was to store the frames in memory or write them and then read them in reverse order.
But I was wondering, if there is a new function to read OpenCV frames in reverse order.
I am looking for a solution something like this:
if rewind == False:
ret,frame = cap.read()
else:
ret,frame = cap.read(rewind=True)
Any solution similar to this one?
or something like this:
if rewind == False:
ret,frame = cap.read()
else:
cap.goBackOneFrame()
ret,frame = cap.read()
Edit:
I tried
if rewind == False:
ret, frame = cap.read() #Read frame
counter += 1
else:
cap.set(cv2.CAP_PROP_POS_FRAMES, counter-1)
counter -= 1
ret, frame = cap.read()
and it works, but the rewind speed is slow. I think my PC is taking more time in processing it?
import cv2
# Grab the current frame.
my_check , vid = cap.read()
# use counter variable for
# Counting frames
counter = 0
check = True
frame_list = []
while(check == True):
cv2.imwrite("frame%d.jpg" %counter , vid)
check , vid = cap.read()
frame_list.append(vid)
# increment the counter by 1
counter += 1
frame_list.pop()
# looping in the List of frames.
for frame in frame_list:
# show the frame.
cv2.imshow("Frame" , frame)
if cv2.waitKey(25) and 0xFF == ord("q"):
break
cap.release()
# close any open windows
cv2.destroyAllWindows()
frame_list.reverse()
for frame in frame_list:
cv2.imshow("Frame" , frame)
if cv2.waitKey(25) and 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()

Taking snapshot with a webcam (either external or internal) with python using opencv

am new here and also new to opencv.
I have this project at hand - designing an application that is able to interface with my computer webcam and take snapshot and also record videos.
So far so good this as far as I can go
import cv2 as cv
import numpy
cv.namedWindow ("camera", 1)
capture = cv.VideoCapture (0)
while True:
ret, frame = capture.read ()
img = cv.cvtColor (frame, cv.COLOR_BGR2BGRA)
cv.imshow ("camera", img)
if cv.waitKey(10) & 0XFF == ord ("q")
break
capture.release ()
cv.destroyAllWindows ()
Now I think am suppose to use cv.VideoCapture.grab ()
And cv.VideoCapture.retrieve ()
But honestly I don't know how am gonna use.
Please I need your HELP
There's a great example of how to do that here:
http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_video_display/py_video_display.html
The example below will take a snapshot every 30 seconds and save it to a file with a unique timestamp:
import cv2 as cv
import time
import datetime
cv.namedWindow("camera", 1)
capture = cv.VideoCapture(0)
while True:
ret, frame = capture.read ()
frame = cv.cvtColor (frame, cv.COLOR_BGR2BGRA)
file = "C:\Python34\CpV\%s.png" % datetime.datetime.now().strftime("%d-%m-%y--%H-%M-%S")
cv.imwrite (file, frame)
#cv.imshow("camera", frame)
time.sleep(30)
capture.release()
cv.destroyAllWindows ()
Use code below to record webcam capture to file :
import cv2
import cv
cap = cv2.VideoCapture(0)
ret,img=cap.read()
height , width , layers = img.shape
fps=20
video = cv2.VideoWriter("rec_out.avi", cv.CV_FOURCC(*'DIVX'), fps, (img.shape[1], img.shape[0]))
while True:
ret,img=cap.read()
height , width , layers = img.shape
video.write(img)
cv2.imshow('Video', img)
#video.write(img)
if(cv2.waitKey(10) & 0xFF == ord('b')):
break
Okay I got to edit my code and it worked
Check it out
import cv2 as cv
import time
cv.namedWindow("camera", 1)
capture = cv.VideoCapture(0)
while True:
ret, frame = capture.read ()
frame = cv.cvtColor (frame, cv.COLOR_BGR2BGRA)
file = "C:\Python34\CpV\test.png"
cv.imwrite (file, frame)
cv.imshow("camera", frame)
#it takes a snapshot when "q" is pressed and closes
the window
if cv.waitKey(10) & 0xFF == ord ('q'):
break
capture.release()
cv.destroyAllWindows ()
This is as far as I have gotten, I need to edit a little to make it short and concise.

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