How to pause a OpenCV video video stream to get points? - python

I have an OpenCV loop running with a video. I want to pause the video on the second frame and make the user click on two points.
import time
import cv2
points=[]
layer = 0
def onMouse(event, x, y, flags, param):
if len(points) < 2:
if event == cv2.EVENT_LBUTTONDOWN:
points.append((x,y))
cap = cv2.VideoCapture(path)
while cap.isOpened():
layer +=1
ret, im = cap.read()
if ret == True:
cv2.imshow(win, im)
key = cv2.waitKey(100)
if len(points) < 2 and layer==2:
cv2.setMouseCallback(win, onMouse)
if key == ord("q"):
break
else:
break
cap.release()
cv2.destroyAllWindows()
But the previous code doesn't pause for user input.
if I try:
time.sleep(5)
Whole program freezes.
I've also tried the using a while loop inside a while loop but it also freezes
if layer == 2:
while len(points) < 2:
cv2.setMouseCallback(win, onMouse)
if len(points) == 2:
break
What Can I do to pause for the user to input two clicks

The following code seemed to work for me.
if layer == 2:
cv2.setMouseCallback(win, onMouse)
cv2.waitKey(0)
how-should-i-properly-use-cv2-waitkey-when-wanting-to-start-pause-a-video
But any suggestion on how to escape the wait key if there are two points in the list?

Related

Opencv rotate camera mode

I want to rotate the camera view by 90 degree clockwise with an interrupt button. But the button's state goes back to it's default state when I click once and unpress the button. As a result, on clicking the button, the camera rotates for an instance and then goes back to the default mode in the while loop. How to solve this issue?
Here is my snippet:
import cv2
cap = cv2. VideoCapture(0)
while True:
ret, frame = cap.read()
cv2.imshow('null', frame)
if (button):
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow('null', frame)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
Any help would be appreciated.
You should use extra variable - rotate = False - to keep this state
rotate = False
while True:
ret, frame = cap.read()
# without imshow()
if button_a.is_pressed():
rotate = True
if rotate:
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
# outside `if`
cv2.imshow('null', frame)
This way it changes rotate from False to True but never from True to False
EDIT:
If next press should rotate another 90 degrees (to 180) then it would need more complex code. It would check if is_pressed() in previous loop was False and in current loop is True - to run it only once when button is pressed long time.
Something like this.
I used normal space to test it.
import cv2
cap = cv2.VideoCapture(0)
rotate = 0
is_pressed = False
previous = False
current = False
while True:
ret, frame = cap.read()
# without imshow()
current = is_pressed
if (previous is False) and (current is True):
rotate = (rotate + 90) % 360
print(rotate)
previous = current
if rotate == 90:
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
elif rotate == 180:
frame = cv2.rotate(frame, cv2.ROTATE_180)
elif rotate == 270:
frame = cv2.rotate(frame, cv2.ROTATE_90_COUNTERCLOCKWISE)
# outside `if`
cv2.imshow('null', frame)
key = cv2.waitKey(40) & 0xff
if key == 27:
break
is_pressed = (key == 32)
cv2.destroyAllWindows()
cap.release()
import cv2
cap = cv2. VideoCapture(0)
button_is_pressed = false;
while True:
ret, frame = cap.read()
if (button):
button_is_pressed = not button_is_pressed
if(button_is_pressed)
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow('null', frame)
cap.release()
I would try something like this, when you press the button it changes the state of variable button_is_pressed, while still unchanged it keeps rotating image.

Computer Terminating OpenCv Image Grabber Program

I Have Created a Program in Python in which it uses opencv to grab some images and save it.I have runned this program on my mac and it works fine does what i expect but on my computer the webcam feed shows and the first image when i click space works but when i click for the second time to grab images it doesnt works.The following is the error message that it shows
[ WARN:0] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-hfoi92lm\opencv\modules\videoio\src\cap_msmf.cpp (435) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Below is my code
import cv2
import subprocess
from sys import exit
import os
# Code!
import time
cam = cv2.VideoCapture(0)
cv2.namedWindow("test")
cv2.startWindowThread()
img_counter = 0
while True:
ret, frame = cam.read()
if not ret:
print("failed to grab frame")
break
cv2.imshow("test", frame)
k = cv2.waitKey(1)
if k%256 == 27:
# ESC pressed
print("Escape hit, closing...")
break
elif k%256 == 32:
# SPACE pressed
img_name = f'\\Users\\Anush\\PycharmProjects\\PelletInspection\\Sample_Images\\Sample_Image_{img_counter}.jpg'
cv2.imwrite(img_name, frame)
print("{} written!".format(img_name))
img_counter += 1
cam.release()
cv2.destroyAllWindows()
try to comment #cv2.startWindowThread()
try editing cv2.waitKey(33) instead of cv2.waitKey(1)

uninterrupted while loop with python cv2.VideoCapture() and string input

I use this code to capture and display the input from my webcam.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
check, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
I have a barcode scanner and want to check inside the while loop if a specific string gets scanned in.
input() interupts the stream from the webcam. I need something like cv2.waitKey() but for strings
while(True):
check, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitString(barcode) == '123456':
# do something
if cv2.waitString(barcode) == '098765':
# do something else
I tried msvcrt, but to no avail. The stream continues but nothing gets printed.
if msvcrt.kbhit():
if msvcrt.getwche() == '280602017300':
print("Barcode scanned!")
Or is there a way to skip input() until something was entered?
UPDATE
Making some progress with the help of this post.
How to read keyboard-input?
I was able to update my code.
import threading
import queue
import time
import numpy as np
import cv2
def read_kbd_input(inputQueue):
print('Ready for keyboard input:')
while (True):
input_str = input()
inputQueue.put(input_str)
def main():
inputQueue = queue.Queue()
inputThread = threading.Thread(target=read_kbd_input, args=(inputQueue,), daemon=True)
inputThread.start()
cap = cv2.VideoCapture(0)
font = cv2.FONT_HERSHEY_DUPLEX
fontScale = 1
fontColor = (255,255,255)
lineType = 2
input_str = "test"
while (True):
check, frame = cap.read()
if (inputQueue.qsize() > 0):
input_str = inputQueue.get()
if (input_str == '280602017300'):
print("do something")
cv2.putText(frame, input_str, (10,30), font, fontScale, fontColor, lineType)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
time.sleep(0.01)
print("End.")
if (__name__ == '__main__'):
main()
Now the only problem left is that my webcam stream is supposed to run in fullscreen. So the console will allways be in the background and therefore wont get the inputs form the keyboard or my barcode scanner.
need it the other way around

OpenCV Video capture using keyboard to start/stop

I have a running script capable of starting/stopping a video stream using 2 different keys;
Program runs and shows the live stream.
When ESC is hit, the program exits.
When SPACE is hit, the video stream is captured.
However, when a video is captured it stores all the stream from the beginning of script execution.
import cv2
import numpy as np
capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))
while True:
ret, frame_temp = capture.read()
cv2.imshow('FRAME', frame_temp)
key=cv2.waitKey(1)
if key%256 == 27:
break
elif key%256 == 32:
output.write(frame_temp)
capture.release()
output.release()
cv2.destroyAllWindows()
So, instead when the program runs I would like;
Program runs and shows the live stream.
Begin recording the stream when SPACE is hit and stop the recording when SPACE is hit once more.
Any suggestions would be much appreciated.
You need an extra variable to figure out if you are recording. I made a variable called recording_flag
import cv2
import numpy as np
capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
recording_flag = False
while True:
ret, frame_temp = capture.read()
cv2.imshow('FRAME', frame_temp)
key=cv2.waitKey(1)
if key%256 == 27:
break
elif key%256 == 32:
if recording_flag == False:
# we are transitioning from not recording to recording
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))
recording_flag = True
else:
# transitioning from recording to not recording
recording_flag = False
if recording_flag:
output.write(frame_temp)
capture.release()
output.release()
cv2.destroyAllWindows()
This line while True: isn't exactly ideal for what you're trying to do. I would recommend you define a function to do the recording and have it recursively call itself if the user stops recording via the space key. The top of your script would still start the same:
import cv2
import numpy as np
capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))
Next you would define your function, it starts by waiting (forever) for a key to be pressed. Once a key is pressed if it is escape (27) it exits the function and cleans up, if it is space (32) it sets a boolean flag that starts recording (while loop). If neither escape or space is pressed it calls itself and starts the process over. Inside the while loop it checks if a key is pressed if so it checks if it is escape (27) or space (32). If either it hit it either exits the function (escape) or haults recording by calling itself which starts the process all over again (space).
def wait_then_capture():
key = cv2.waitKey(0)
if key%256 == 27:
return
elif key%256 == 32:
record = True
else:
wait_then_capture()
while record == True:
ret, frame_temp = capture.read()
cv2.imshow('FRAME', frame_temp)
key = cv2.waitKey(1)
if key%256 == 27:
return
elif key%256 == 32:
break
output.write(frame)
wait_then_capture()
We then call our new function and end the script with the same cleanup you already have
wait_then_capture()
capture.release()
output.release()
cv2.destroyAllWindows()
Your finished script would look like this
import cv2
import numpy as np
capture = cv2.VideoCapture(1)
codec = cv2.VideoWriter_fourcc(*'XVID')
output = cv2.VideoWriter('CAPTURE.avi', codec, 30, (640, 480))
def wait_then_capture():
key = cv2.waitKey(0)
if key%256 == 27:
return
elif key%256 == 32:
record = True
else:
wait_then_capture()
while record == True:
ret, frame_temp = capture.read()
cv2.imshow('FRAME', frame_temp)
key = cv2.waitKey(1)
if key%256 == 27:
return
elif key%256 == 32:
break
output.write(frame)
wait_then_capture()
wait_then_capture()
capture.release()
output.release()
cv2.destroyAllWindows()

How to capture video and save from webcam on click or pressing any key from keyboard using OpenCV

I want to capture and save a video from my webcam in a way that when I press any key (enter, space etc) from keyboard then code should start save the video from current frame and when I press same key from keyboard then code should stop to save the video. This is my code currently:
import cv2
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))
while(True):
ret, frame = cap.read()
k = cv2.waitKey(1)
if ret == True:
cv2.imshow('frame',frame)
# press space key to start recording
if k%256 == 32:
out.write(frame)
# press q key to close the program
elif k & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
My current code is capturing only one (current frame) when I press space key. I need help to solve this problem.
Here is the same question but it is for images, it can't solve for videos.
Also is there a better way to capture and save video which can solve my problem?
The problem is that the code you wrote only calls the function out.write(frame) when you press the space key.
This should solve the issue:
create some sentinel variable at the beginning of your code. let's say record = False
And then inside your loop, make this change:
if k%256 == 32:
record = True
if record:
out.write(frame)
So this is how your code will look like:
import cv2
record = False
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))
while(True):
ret, frame = cap.read()
k = cv2.waitKey(1)
if ret == True:
cv2.imshow('frame',frame)
# press space key to start recording
if k%256 == 32:
record = True
if record:
out.write(frame)
# press q key to close the program
if k & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()

Categories