Python Video Processing - python

I have written a code which plays a video in two different frames using two threads.The code looks fine but the cv2.imshow method does not display the videos playing. The video player opens and closes immediately.
Help required in resolving the issue.
import threading
import cv2
def print_cube(num):
"""
function to print cube of given num
"""
print("start")
print(num)
cv2.imshow("video1",num)
print("end")
cv2.destroyAllWindows()
def print_square(num):
"""
function to print square of given num
"""
print("start1")
print(num)
cv2.imshow("video2",num)
print("end2")
if __name__ == "__main__":
# creating thread
cap = cv2.VideoCapture("C:\\Users\shakarna\Desktop\video.mp4")
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
t1 = threading.Thread(target=print_square, args=(frame,))
t2 = threading.Thread(target=print_cube, args=(gray,))
# starting thread 1
t1.start()
# starting thread 2
t2.start()
# wait until thread 1 is completely executed
t1.join()
# wait until thread 2 is completely executed
t2.join()
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

the problem could be that your code cannot find the video. To look whether this is the problem or not place your mp4 file into the same folder as your code, than
cap = cv2.VideoCapture("C:\Users\shakarna\Desktop\video.mp4")
should be
cap = cv2.VideoCapture("video.mp4")

Related

While loop doesn't perfom second iteration

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

How to keep cv2.imwrite() from overwriting the image files?

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

multiprocessing script using Pipes

When I try to run the following script, process 1 displays just 1 sec of video and get stuck. is there any problem with the code? My goal is to run two processes, one which display's the frames continuously and other process perform face detection and print the results whenever the process1 sets the event. Process 1 sets the event at regular intervals i.e, after every 20 or 30 frames.
def read(e,parent):
fps,st,frames_to_count,cnt = (0,0,30,0)
vid = cv2.VideoCapture('sample.mp4')
wid = 640
while(vid.isOpened()):
res,frame = vid.read()
if not res:
break
frame = imutils.resize(frame,width = wid)
cv2.imshow('VIDEO',frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
if cnt == frames_to_count:
try:
fps = round(frames_to_count/(time.time()-st))
parent.send(frame)
e.set()
st=time.time()
cnt=0
except:
pass
cnt+=1
cv2.destroyAllWindows()
def fd(e,child):
face_cascade=cv2.CascadeClassifier("path to xml")
while True:
e.wait()
faces=face_cascade.detectMultiScale(child.recv(),1.1,4)
print(faces)
e.clear()
def main():
e = Event()
(child,parent) = Pipe()
p1 = Process(target=read, args=(e,parent))
p2 = Process(target=fd, args=(e,child))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == "__main__":
main()
See all my comments to your posted question. In the code below I have retained the Pipe that you are using but have specified duplex=False since you are not using the returned connections for two-way communication and have correspondingly renamed these connections from child and parent to the now more meaningful read_conn and send_conn. I have, of course, removed the Event instance.
Since fd appears to be in a loop that never terminates, main will never be able to join that process. Therefore, p2 should be created as a daemon process that will automatically terminate when all non-daemon processes and threads terminate.
def read(send_conn):
fps,st,frames_to_count,cnt = (0,0,30,0)
vid = cv2.VideoCapture('sample.mp4')
wid = 640
while(vid.isOpened()):
res,frame = vid.read()
if not res:
break
frame = imutils.resize(frame,width = wid)
cv2.imshow('VIDEO',frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
if cnt == frames_to_count:
try:
fps = round(frames_to_count/(time.time()-st))
send_conn.send(frame)
st=time.time()
cnt=0
except:
pass
cnt+=1
cv2.destroyAllWindows()
def fd(recv_conn):
face_cascade=cv2.CascadeClassifier("path to xml")
while True:
faces=face_cascade.detectMultiScale(recv_conn.recv(),1.1,4)
print(faces)
def main():
(recv_conn,send_conn) = Pipe(duplex=False)
p1 = Process(target=read, args=(send_conn,))
p2 = Process(target=fd, args=(recv_conn,), daemon=True)
p1.start()
p2.start()
p1.join()
if __name__ == "__main__":
main()

Python Threading for Camera

I am trying to put the camera footage into a different thread as the cv2.wait() does not work correctly anymore for access keys even when using an '& and hexadecimal'.
Does anyone know what I have done wrong with the daemon thread I have created for displaying camera footage in the main as when placed in the main while loop it fails while loop?
How do I use a thread to continuously display camera footage in my while loop in the main program?
quote My thread for the ViewCamera function isn't working right - can anyone help?
from djitellopy import Tello
# Access the telopy libray.
import cv2, math, time
from time import sleep, perf_counter
from threading import Thread
stop = True
def ViewCamera():
global stop
while stop == True:
try:
#camera window
img = frame_read.frame
cv2.imshow("drone", img)
print ('thread test')
except Exception as e:
print ("Cerror is : ,", e)
drone = Tello()
'''
create an instance of the Tellopy libray
drone.connect() #connect to drone using wifi
drone.streamon()
#make use of a data stream to drone to pass on keyboard commands
#frame_read = drone.get_frame_read() #read cammera data using frame per frame rate
'''
key = 0
# drone.takeoff()
if __name__ == "__main__":
print ('main program')
# Create a camera thread - runs in background.
t1 = Thread(target=ViewCamera, args=())
t1.daemon = True
print('starting thread')
t1.start()
while True:
key = ord(input('please enter letter'))
if key == ord('j'):
drone.land()
print('stopping thread')
stop = False
break
elif key == ord('w'): # Forward
drone.move_forward(30)
print('moving forwards')
elif key == ord('s'): # Move backwards
drone.move_back(30)
elif key == ord('a'): # Move left
drone.move_left(30)
elif key == ord('d'): # Move right
drone.move_right(30)
elif key == ord('e'): # Rotate right
drone.rotate_clockwise(30)
elif key == ord('q'): # Rotate left
drone.rotate_counter_clockwise(30)
elif key == ord('r'): # Move up
drone.move_up(30)
elif key == ord('f'): # Move down
drone.move_down(30)
print('stopping thread')
t1.join()
drone.land()
The threading daemon isn't seeming to work it should be running in background and continually allowing the camera images in a window to be viewed - any ideas why it is not?

how to end a while loop by pressing a key

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

Categories