I am using Jupyter Notebook for practicing coding (if it's relevant) and trying to use cv2 in order to take pictures using my webcam. However, whenever I take a picture and have that picture saved, the previous picture gets overwritten because of having the same file name. How do I keep this from not happening?
import cv2
key = cv2.waitKey(1)
webcam = cv2.VideoCapture(0)
while True:
try:
check, frame = webcam.read()
print(check)
print(frame)
cv2.imshow("Capturing", frame)
key = cv2.waitKey(1)
if key == ord('s'):
cv2.imwrite(filename='saved_img.jpg', img=frame)
webcam.release()
cv2.waitKey(1650)
cv2.destroyAllWindows()
break
elif key == ord('q'):
print("Turning off camera.")
webcam.release()
print("Camera off.")
print("Program ended.")
cv2.destroyAllWindows()
break
except(KeyboardInterrupt):
print("Turning off camera.")
webcam.release()
print("Camera off.")
print("Program ended.")
cv2.destroyAllWindows()
break
'saved_img' image file always gets overwritten whenever I capture...
You can use the isfile function from the os module:
import os
if os.isfile("saved_img.jpg"):
if input("do you want to overwrite saved_img.jpg? ") == "yes":
cv2.imwrite(filename='saved_img.jpg', img=frame)
else:
cv2.imwrite(filename='saved_img.jpg', img=frame)
If you need to restart-proof, you can check how many files have been saved before, so that code allows (as you said in comment) one image per run of th program
nb_files = len(list(Path(".").glob("saved_img_*.jpg")))
filename = f"saved_img_{nb_files}.jpg"
import cv2
key = cv2.waitKey(1)
webcam = cv2.VideoCapture(0)
while True:
try:
check, frame = webcam.read()
print(check)
print(frame)
cv2.imshow("Capturing", frame)
key = cv2.waitKey(1)
if key == ord('s'):
cv2.imwrite(filename=filename, img=frame)
webcam.release()
cv2.waitKey(1650)
cv2.destroyAllWindows()
break
...
Here's a variation if one run of the program may create multiple images
nb_files = len(list(Path(".").glob("saved_img_*.jpg")))
i = 0
import cv2
key = cv2.waitKey(1)
webcam = cv2.VideoCapture(0)
while True:
try:
check, frame = webcam.read()
print(check)
print(frame)
cv2.imshow("Capturing", frame)
key = cv2.waitKey(1)
if key == ord('s'):
cv2.imwrite(filename=f"saved_img_{nb_files + i}.jpg", img=frame)
i += 1
Related
my code is:
cap = cv2.VideoCapture(2)
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
while True:
ret, frame = cap.read()
if ret == True:
cv2.imshow('frame',frame)
time.sleep(0.001)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
print("you suck")
break
cap.release()
cv2.destroyAllWindows()
The problem is it doesn't do the second iteration, it just performs the first one and then gets stuck. interesting is that when I delete import:
from model.return_model import return_model, process_frames which basically imports pytorch model, it works perfectly. I am trying to debug it, but can't find any solution
Guys I resolved the issue. I used sudo to run the script, and it worked
I made a simple code to take snapshots from my webcam when prompted by pressing 's', and quit if I pressed 'q'. Code runs fine but the elif statement for the quitting part alone is ignored.
import cv2
cap = cv2.VideoCapture(0)
counter = 0
while(True):
ret, frame = cap.read()
cv2.imshow('Webcam', frame)
if (cv2.waitKey(1) & 0xFF) == ord('s'):
print("s working")
counter = counter + 1
cv2.imwrite("Snapshot_" + str(counter) + ".png", frame)
elif (cv2.waitKey(1) & 0xFF) == ord('q'):
print("q working")
break
cap.release()
cv2.destroyAllWindows()
I also tried swapping their order, the if statement being the 'q' condition and the elif being 's', the second statement is always the one skipped.
Update: it only works if I hold q for a while
Why isn't it working normally?
As I learned from the comments, the problem was caused by the waitKey delay. So to fix it I put the pressed button in a variable and compared the condition statements to that variable instead.
import cv2
cap = cv2.VideoCapture(0)
counter = 0
while(True):
ret, frame = cap.read()
cv2.imshow('Webcam', frame)
k = cv2.waitKey(1) & 0xFF
if k == ord('s'):
print("s working")
counter = counter + 1
cv2.imwrite("Screenshot_" + str(counter) + ".png", frame)
elif k == ord('q'):
print("q working")
break
cap.release()
cv2.destroyAllWindows()
The issue is not caused by any delays, nor by any blocking.
After cap.read() returns a new frame, there may be key events waiting because you pressed some keys.
Each waitKey() consumes one key press event and returns it, if there was a key event.
If you pressed a key, the first waitKey() receives that event, and if it was the wrong key, the if doesn't run its consequent code.
Then, the second waitKey() has no key event to handle, so it returns -1.
If you held the key down, you might have had a chance to create enough key press events to get one of them into the second waitKey().
The proper solution is to call waitKey() once per loop, and store its returned value in a variable.
Then you test that variable against as many key codes as you like.
while True:
...
keycode = cv.waitKey()
if keycode == ord('s'):
...
elif keycode == ord('q'):
...
That &0xFF stuff is superfluous and outdated since 2016. waitKey() does that already. It is superfluous.
I'm trying to write a code so that a webcam will take a picture every hour for an undetermined amount of time (2 weeks for now). Here's what I have so far (which works) :
t0=time.perf_counter()
time_max=3600*24*14
time_step= 3600
while(True):
tc=time.perf_counter()
crit = tc-t0
if (crit>time_max) :
cap.release()
break
cap.open(num_cam,api)
cap.set(cv2.CAP_PROP_FOCUS,70)
ret=cap.grab() #takes a picture
tst,frm=cap.retrieve()
cv2.imwrite('test1h_'+str(np.round(crit,2))+'_f70.png',frm)
cap.release()
time.sleep(time_step)
pass
I would like for this loop to stop if I press 'q' for example, and for the webcam to take a picture if I press 'p', how could I implement that ? I read you can you can use cv2.waitKey but I don't know where to put that in the code. I also read that you can use the nodule "keyboard" but that it requires a root in linux and I work on windows.
You can just use this:
if cv.waitKey(20) % 0xFF == ord("d"):
break
So for example if you want to display a video while not pressing the "d" key, this should work:
while True:
isTrue, frame = capture.read()
cv.imshow("Video", frame)
if cv.waitKey(20) % 0xFF == ord("d"):
break
capture.realease()
cv.destroyAllWindows()
Edit: Had mixed up 'char' and 'key', fixed it now.
If you're okay with not using cv2, I would suggest this using pynput:
from pynput import keyboard
def on_press(key):
print(key)
listener = keyboard.Listener(on_press=on_press)
listener.start()
In your case, you could implement it like this:
import time
from pynput import keyboard
t0=time.perf_counter()
time_max=3600*24*14
time_step= 3600
def on_press(key):
if key.char=='p':
#Take picture
cap.open(num_cam,api)
cap.set(cv2.CAP_PROP_FOCUS,70)
ret=cap.grab()
tst,frm=cap.retrieve()
cv2.imwrite('test1h_'+str(np.round(crit,2))+'_f70.png',frm)
cap.release()
elif key.char=='q':
#Interrupt
exit()
listener = keyboard.Listener(on_press=on_press)
listener.start()
while(True):
tc=time.perf_counter()
crit = tc-t0
if (crit>time_max) :
cap.release()
break
cap.open(num_cam,api)
cap.set(cv2.CAP_PROP_FOCUS,70)
ret=cap.grab() #takes a picture
tst,frm=cap.retrieve()
cv2.imwrite('test1h_'+str(np.round(crit,2))+'_f70.png',frm)
cap.release()
time.sleep(time_step)
pass
I tried work with
if cv2.waitKey(0) & 0xFF == ord('q'):
break
But I kept on getting TypeError. However, when I use either one my camera does not respond to the code.
import cv2
import numpy as np
capture = cv2.VideoCapture(0)
while True:
ret, frame = capture.read()
cv2.imshow("frame", frame)
if cv2.waitKey(0) & 0xFF == ord('q'):
break
capture.release()
cv2.destroyAllWindows()
if cv2.waitKey(0) & 0xFF == ord('q'):
TypeError: unsupported operand type(s) for &: 'NoneType' and 'int'
Process finished with exit code 1
Although the docs state the waitkey function returns the code of the pressed key, you could pull out the value and perform a none check
c = cv2.waitKey(0)
if c is not None and c & 0xFF == ord('q'):
I have the following code:
total_frames = 50
cv2.cv.NamedWindow("Dragonfly Simulation")
cv2.cv.StartWindowThread()
for i in range(total_frames):
# do stuff
img_name = # something
img = cv2.cv.LoadImage(img_name)
cv2.cv.ShowImage("Dragonfly Simulation", img)
cv2.cv.WaitKey(2)
cv2.cv.DestroyWindow("Dragonfly Simulation")
cv2.cv.WaitKey(1)
# rest of code
So what does it do:
Opens a window
In a loop, shows an image on the window
Once finished, closes the window
Runs the rest of the code
However in this case I have the total_frame given before. I don't want that.
Instead, I want a code that does the following:
Opens a window
In a loop, shows an image on the window
Waits for the user to close that window
When the user closes that window, exit loop, goes on with the rest of the code.
However, I cannot find a function in OpenCV that can detect when user closes a window. Can anyone suggest a workaround please?
I was just looking for a way to detect when the window has been closed using the X button of the window in addition to waiting for a key press, but I couldn't find an answer anywhere (IsWindowVisible and cvGetWindowHandle are not available in the Python cv2 module).
So I played around and this is how it works:
while cv2.getWindowProperty('window-name', 0) >= 0:
keyCode = cv2.waitKey(50)
# ...
cv2.getWindowProperty() returns -1 as soon as the window is closed.
For explanation, see the documentation for the enumeration of cv::WindowPropertyFlags: getting the flag with index 0 is the fullscreen property, but actually it doesn't matter which flag to use, they all become -1 as soon as the window is closed.
Note: This might only work for certain GUI backends. Notably, it will not work with the GTK backend used in Debian/Ubuntu packages. To use the Qt backend instead, you have to install opencv-python via pip.
As of version 2.2 there is a simple solution (this is modified from the loop in hist.py):
cv2.imshow('image',im)
while True:
k = cv2.waitKey(100) # change the value from the original 0 (wait forever) to something appropriate
...
elif k == 27:
print('ESC')
cv2.destroyAllWindows()
break
if cv2.getWindowProperty('image',cv2.WND_PROP_VISIBLE) < 1:
break
cv2.destroyAllWindows()
I tested on C++ using the getWindowProperty('image', WND_PROP_VISIBLE), but it does not work. So I used the WND_PROP_AUTOSIZE and it works.
I did like this:
cv::namedWindow("myTitle", WINDOW_AUTOSIZE);
while(1)
{
cv::imshow("myTitle", myImage);
if (cv::getWindowProperty("myTitle", WND_PROP_AUTOSIZE) == -1)
break;
}
if cv2.getWindowProperty('windowname',1) == -1 :
break
cv2.imshow('windowname', image)
import cv2
import numpy as np
# total_frames = 50
cv2.namedWindow("Dragonfly Simulation")
cv2.startWindowThread()
# for i in range(total_frames):
while True:
# do stuff
img = np.random.randint(0,255,(200,300)).astype(np.uint8)
cv2.imshow("Dragonfly Simulation", img)
key = cv2.waitKey(200)
print key
if key in [ord('a'), 1048673]:
print 'a pressed!'
elif key in [27, 1048603]: # ESC key to abort, close window
cv2.destroyAllWindows()
break
# do the rest of processing after break
print 'results:'
Sure, you can check user inputs using waitKey and here is a small example based on your code. I changed old cv interface to cv2. I think cv is obsolete.
(Edit) I moved cv2.destroyAllWindows() to inside the while loop to make it clear that the window closes when the user pressed ESC key (which you can assign a key of your choice). I do not think opencv has a proper event handler to catch the window close event like in other GUI toolkit (wxPython etc). So you will need to define how your users should close the window and watch out for that.
I used the following code t check if a key is pressed or the window is closed at the same time.
while cv2.getWindowProperty(camera.get_name(), cv2.WND_PROP_VISIBLE) > 0:
if cv2.waitKey(100) > 0:
break
cv2.destroyAllWindows()
I made a simple function based on this post. It works in opencv 4.5.2
def wait_with_check_closing(win_name):
"""
https://stackoverflow.com/questions/35003476/"
"opencv-python-how-to-detect-if-a-window-is-closed/37881722
"""
while True:
keyCode = cv2.waitKey(50)
if keyCode != -1:
break
win_prop = cv2.getWindowProperty(win_name, cv2.WND_PROP_VISIBLE)
if win_prop <= 0:
break
It can be used instead of cv2.waitKey(0) like following example.
# Usage
cv2.imshow(title, img_resized)
# cv2.waitKey(0)
wait_with_check_closing(title)
cv2.destroyAllWindows()
https://www.programcreek.com/python/example/110676/cv2.WND_PROP_VISIBLE
For my scenario, it had to be the following. I had to call k = cv2.waitKey(1) & 0xFF before checking status of the window for it to work
def show_webcam(mirror=False):
cam = cv2.VideoCapture(0)
# cv2.startWindowThread()
window_name="A_star webcam"
while True:
ret_val, img = cam.read()
if mirror:
img = cv2.flip(img, 1)
cv2.imshow(window_name, img)
k = cv2.waitKey(1) & 0xFF
if not (cv2.getWindowProperty(window_name,cv2.WND_PROP_VISIBLE)):
break
if cv2.waitKey(1) == 27:
break # esc to quit
cv2.destroyAllWindows()
The libraries installed are
autopep8==1.6.0
numpy==1.22.1
opencv-python==4.5.5.62
pycodestyle==2.8.0
toml==0.10.2
#David Kohen's answer is working great for me. But if you have many images to show its better to convert it to a function
def waitUntilX(window):
while True:
k = cv2.waitKey(100) # change the value from the original 0 (wait forever) to something appropriate
if k == 27:
print('ESC')
cv2.destroyAllWindows()
break
if cv2.getWindowProperty(window,cv2.WND_PROP_VISIBLE) < 1:
break
cv2.destroyAllWindows()
Usage
invertedmask = cv2.bitwise_not(mask)
cv2.imshow('inverted mask', invertedmask)
waitUntilX('inverted mask')