OpenCV to close the window on a specific key? - python

It seems really simple, but I can't get it to work and the couldn't find any questions regarding this particular issue (if there are, please point out in the comments).
I am showing an image and want the window to close on a specific key, but strangely, any key causes it to close.
This is my simple code for testing:
img = cv2.imread("MyImage.png")
cv2.imshow('My Image', img)
k = cv2.waitKey(0) & 0xFF
print(k)
if k == 27: # close on ESC key
cv2.destroyAllWindows()
(based on what is said here)
No matter what key I press, the key code is shown (27 for ESC, 32 for SPACE, ...) and the window closes.
The main problem: the if clause is never reached (I checked by putting the print(k) inside it, and nothing is printed). After the key press, the program simply stops running and it doesn't get to checking the key code.
(I am on macOS Catalina, with Python 3.8)
So, how do I actually make it wait for a specific key?

From my point of view, your program just terminates, and thus all windows are implicitly closed, regardless of which key you press.
One idea might be to put a while True loop around the reading and checking of the pressed key:
import cv2
img = cv2.imread('path/to/your/image.png')
cv2.imshow('My Image', img)
while True:
k = cv2.waitKey(0) & 0xFF
print(k)
if k == 27:
cv2.destroyAllWindows()
break
Running this, pressing some keys, and finally ESC, I get the following output:
103
100
102
27
Also, all windows are closed, and the program is terminated.
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.5
OpenCV: 4.4.0
----------------------------------------

If you want to use specific key, you can use ord():
img = cv2.imread('path/to/your/image.png')
cv2.imshow('My Image', img)
while True:
k = cv2.waitKey(0) & 0xFF
print(k)
if k == ord('c'): # you can put any key here
cv2.destroyAllWindows()
break

Simply do this:
img = cv2.imread("MyImage.png")
cv2.imshow('My Image', img)
k = cv2.waitKey(0)
print(k)
if k == 27: # close on ESC key
cv2.destroyAllWindows()
I have simply removed & 0xFF from it. This works for me but I don't why this would pose a problem as it is simply applying and operation with FF.

Try this, it will wait for key 'q' to be pressed.
import cv2
img = cv2.imread("MyImage.png")
cv2.imshow('My Image', img)
if cv2.waitKey(0) & 0xFF == ord('q'):
cv2.destroyAllWindows()
HIH.

Related

python multiprocessing runs slower at second time without terminating whole program

I have a python program with opencv gui that uses a multiprocessing in threading in class instance.
After running below script, when I type q it will quit the sub loop and it terminates or join all existing thread, process and close queue in modules.
And then if I type r then it will start sub loop again, but this time, the worker in multiprocessing runs twice slower. I have no idea why it is happening.
code is like below.
module_started = False
height = 480
width = 800
img_base = np.zeros((height,width,3), np.uint8)
cv2.namedWindow("VIN", cv2.WINDOW_NORMAL)
while True:
if not module_started:
cam1 = PersonDetector(0)
cam1.start()
outputs = []
module_started = True
while True:
if cam1.new_detection:
outputs = cam1.get_output()
if outputs:
for xys in outputs:
(startX, startY, endX, endY) = xys
cv2.rectangle(cam1.frame, (startX, startY), (endX, endY), (255,5,150),2)
# show the output image
cv2.imshow("VIN", cam1.frame)
key = cv2.waitKey(40) & 0xFF
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
cam1.stop()
del cam1
# show the output frame
cv2.imshow("VIN", img_base)
key = cv2.waitKey(40) & 0xFF
if key == ord("e"):
break
if key == ord("r"): # go back to start sub loop
module_started = False
cv2.destroyAllWindows()
it is on raspberry pi 4. it has cpu 4 core.
first time, htop shows CPU% over 300%
but second time, htop shows CPU% just 99 or 100%...
why it happens?
I have tested by myself for a whole day.
It was not because of multiprocessing nor threading.
It was because of cv2.imshow(), I removed imshow then everything keep the same speed but when repeating imshow like above code, it shows program down, I still dont know why though...

Repeating a video on loop using OpenCV and Python

I am trying to create a simple program that will play a video using OpenCV on repeat until the waitKey is pressed. The video will play once and then give an error message "(-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'". I was getting this message earlier but fixed it by changing the file location. I'm almost positive that the issue comes from the fact that when the video ends the next frame is nonexistent so it cant be read, as breaking the while loop when the frame is None doesn't give an error. Every solution I have tried has failed. Any help?
import cv2
import numpy as np
cap = cv2.VideoCapture('video_file_location')
while True:
_, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) == 27:
break
cap.release()
cv2.destroyAllWindows()
Try putting the cv2.VideoCapture() into the loop and the frame should only show when the return is True and that is your problem in your code
import cv2
import numpy as np
while True:
#This is to check whether to break the first loop
isclosed=0
cap = cv2.VideoCapture('videoplayback.mp4')
while (True):
ret, frame = cap.read()
# It should only show the frame when the ret is true
if ret == True:
cv2.imshow('frame',frame)
if cv2.waitKey(1) == 27:
# When esc is pressed isclosed is 1
isclosed=1
break
else:
break
# To break the loop if it is closed manually
if isclosed:
break
cap.release()
cv2.destroyAllWindows()

terminating a python loop [duplicate]

This question already has answers here:
How to detect ESCape keypress in Python?
(5 answers)
Closed 5 years ago.
I made a program that reads pixels from a camera. I have used a while loop. But I can't close the program from terminal without pressing 'Cltrl + C'. I want to close the program using ESC button ( ASCII 27). I tried the following code, which is not working. Any help would be appreciated
import cv2 as cv
import numpy as np
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read()
redimage = frame[:,:,2]
print(redimage)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
Use:
if k == chr(27):
break
cv.waitKey(1) is working for opencv gui only. You can't capture keyboard events in console with this function.
So, you can change your code to show the frame that you are reading from the camera.
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read()
redimage = frame[:,:,2]
cv2.imshow('frame', frame)
print(redimage)
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
You can find in this answer a way to capture keyboard events in console.

Annotating video frames with a label based on state

I have a bunch of videos and depthmaps showing human poses from the Microsoft Kinect.
I can get a skeleton of the human in the video but what I want to do is recognize a certain pose from this skeleton data.
To do that I need to annotate each frame in the videos with a 0 or 1, corresponding to "bad pose" and "good pose", i.e. the frame has a binary state variable.
I want to be able to playback the avi file in matlab and then press space to switch between these two states and simultaneously add the state variable to an array giving the state for each frame in the video.
Is there a tool in matlab that can do this? Otherwise matlab is not a restriction, python, C++ or any other language is fine.
I have been googling around, and most of the stuff I have found is to annotate individual frames with a polygon. I want to do this at maybe half the regular framerate of the video.
EDIT: I used the solution provided by miindlek and decided to share a few things if someone runs into this. I needed to see in the video what annotation I was assigning to each frame, so I made a small circle in the upper left corner of the video as I displayed it. Hopefully this will be useful for someone else later. I also capture the key pressed with waitKey and then do something based on the output. This allows for multiple keys to be pressed during the annotations.
import numpy as np
import cv2
import os
os.chdir('PathToVideo')
# Blue cicle means that the annotation haven't started
# Green circle is a good pose
# Red is a bad pose
# White circle means we are done, press d for that
# Instructions on how to use!
# Press space to swap between states, you have to press space when the person
# starts doing poses.
# Press d when the person finishes.
# press q to quit early, then the annotations are not saved, you should only
# use this if you made a mistake and need to start over.
cap = cv2.VideoCapture('Video.avi')
# You can INCREASE the value of speed to make the video SLOWER
speed = 33
# Start with the beginning state as 10 to indicate that the procedure has not started
current_state = 10
saveAnnotations = True
annotation_list = []
# We can check wether the video capture has been opened
cap.isOpened()
colCirc = (255,0,0)
# Iterate while the capture is open, i.e. while we still get new frames.
while(cap.isOpened()):
# Read one frame.
ret, frame = cap.read()
# Break the loop if we don't get a new frame.
if not ret:
break
# Add the colored circle on the image to know the state
cv2.circle(frame,(50,50), 50, colCirc, -1)
# Show one frame.
cv2.imshow('frame', frame)
# Wait for a keypress and act on it
k = cv2.waitKey(speed)
if k == ord(' '):
if current_state==0:
current_state = 1
colCirc = (0,0,255)
else:
current_state = 0
colCirc = (0,255,0)
if current_state == 10:
current_state = 0
colCirc = (0,255,0)
if k == ord('d'):
current_state = 11
colCirc = (255,255,255)
# Press q to quit
if k == ord('q'):
print "You quit! Restart the annotations by running this script again!"
saveAnnotations = False
break
annotation_list.append(current_state)
# Release the capture and close window
cap.release()
cv2.destroyAllWindows()
# Only save if you did not quit
if saveAnnotations:
f = open('poseAnnot.txt', 'w')
for item in annotation_list:
print>>f, item
f.close()
One way to solve your task is using the opencv library with python, as described in this tutorial.
import numpy as np
import cv2
cap = cv2.VideoCapture('video.avi')
current_state = False
annotation_list = []
while(True):
# Read one frame.
ret, frame = cap.read()
if not ret:
break
# Show one frame.
cv2.imshow('frame', frame)
# Check, if the space bar is pressed to switch the mode.
if cv2.waitKey(1) & 0xFF == ord(' '):
current_state = not current_state
annotation_list.append(current_state)
# Convert the list of boolean values to a list of int values.
annotation_list = map(int, annotation_list)
print annotation_list
cap.release()
cv2.destroyAllWindows()
The variable annotation_list contains all annotations for each frame. To switch between the two modes, you have to press the space bar.

can't get the keycode now, using python and opencv

okay, i've been using this basic thing for last few months to get key events such as ESC key, or E key etc, to do things when they are pressed in my opencv program.
Now earlier, for detecting ESC key, the code was there already in all the examples in the samples folder and on the web. I understood that. From that i hacked up a way to get the keycodes for other keys, such as E and S etc. Because i wanted to use them to take snapshots of the current frames under processing in my program. And it worked, i found out for E its 101, like for ESC its 27
But that's the ASCII value or something? I'm not sure.
This is what i'm doing now also, but its just not printing the keycode:
import cv
while True:
k = cv.WaitKey(100) % 0x100
if k != 255:
print k
So that when i press some key which doesn't have a value of 255, i should be notified that the that key was pressed. It works in my opencv programs:
while True:
k = cv.WaitKey(10)
if k % 0x100 == 27: # if ESC key is pressed....
#cv.SaveImage(filename,threshed2)
cv.DestroyWindow("threshed") #Destroy the window of detection results
cv.DestroyWindow("gray")
cv.DestroyWindow("edge")
cv.DestroyWindow("pupil")
#cv.DestroyWindow('smooth')
break
elif k == 101: #if E is pressed
eyeSnap = "C:\\Users\\ronnieaka\\Desktop\\PROJ\\openCV\\eyeSnaps\\det_pupil.jpg"
cv.SaveImage(eyeSnap,image)
I know its a basic thing and i just was playing around to get the keys pressed and do something else not related to OpenCV
Why i'm i not getting 101 from the previous code when i press E or the code for other keys when i press them?
This used to be super simple:
k = cv.WaitKey(10)
if k == 27:
# ESC key was pressed
The code above don't work on your system?
I have the same problem as you, but I always could not get keycode (only get 255)
I find it because the cv.WaitKey only receive key from the windows you create not python command line :)

Categories

Resources