OpenCV works with threads but not with processes - python

Hi everyone and thanks for the help.
I've got this function to save a video from frames taken by my webcam.
import cv2
import multiprocessing
import threading
def rec():
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
If i use it with threads, and so with this code, it works well:
s1 = threading.Thread(target=rec)
s1.start()
But if i want to start another process, using the following code, when i open the video it contains only black frames with some noise.
s1 = multiprocessing.Process(target=rec)
s1.start()
I searched all around but couldn't find any solution.
Also, i'm using Python 3.6

where is cap defined ? Try defining that in the function that you give to multiprocessing. If it is defined in the parent and is passed from the parent to the child, it is being pickled and that probably makes it unusable.

I solved the problem.
I was calling cap = cv2.VideoCapture(0) in my main and also in one of my imported modules, and that conflicted. I solved by calling it once.

Related

OpenCV buffer problem when using external trigger

I'm using OpenCV with USB camera on a Raspberry Pi4. I have activated an external trigger by RPI's GPIO pin. I wrote a short Python code to test the trigger and made sure it worked. Then I wrote another Python program to save a single image captured by the camera. Here is the code:
import time
import cv2
import smbus
from gpiozero import LED
TRIG_ADDR = 17
def setup_trigger_control_gpio(pin):
trigger = LED(pin)
return trigger
def setup_camera(frame_width, frame_height, fps):
cap = cv2.VideoCapture(0, cv2.CAP_ANY)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, frame_width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height)
cap.set(cv2.CAP_PROP_FPS, fps)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
if cap.isOpened() is not True:
print ("Cannot open camera. Exiting.")
quit()
else:
return cap
trigger = setup_trigger_control_gpio(TRIG_ADDR)
cap = setup_camera(640, 480, 120)
trigger.on()
ret, frame = cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imwrite("images/frame.pgm", frame)
trigger.off()
cap.release()
I set the buffersize to 1, since I'm using a trigger to capture the frame exactly when I need to. The program however gets stuck on the cap.read() line as if it did not receive the trigger. When I ran the program after that I ran the short program for the trigger only, it has finished successfully. Sometimes I had to run the trigger program more than once for the main program to finish, which I find a bit scary, because of the inconsistency.
I tried to set the buffersize to 10, which seemingly worked, however the saved image was empty(all black). I have also tried to "flush" the buffer by reading the first 10 empty frames, which worked and I have finally saved a proper image. The real problems occur when I try to process real time video this way, as even after flushing the buffer, the images do not correspond to the point in time when they should've been taken. Therefor I would love to use the feature of setting the buffersize to one, so that I would know exactly which frame is being processed. I will be thankful for any ideas.

How to access 1 webcam with 2 threads

I am using python 3.5 with opencv.
I want to use 2 threads:
Thread 1: Save the video to a file
Thread 2: Display the video to the user
To view/capture the video from webcam i am using snippets of code from the following website: opencv video docs
I can capture and save the video using the following code:
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(True):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
# write the flipped frame
out.write(frame)
else:
break
out.release()
cv2.destroyAllWindows()
I can view the video using the following code:
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Each of these pieces of code are in their own functions called capture and display. I then call them in separate threads with pythons threading library as follows:
cap = cv2.VideoCapture(0)
Thread(target=capture).start()
Thread(target=display).start()
cap.release()
I get an error I assume is related to both threads wanting to access the video buffer at the same time.
I understand this can be done without threads but there are other things I would like to do further than can only be done in separate threads.
How can I access the cap video capture from both threads?
My flask/django experience is increadibly limited, so I am not sure how to do it for that exactly, but I will answer the question posted directly.
First you need to create a thread-safe object to avoid calling at the same time the read function in different threads.
import cv2
import threading
class VideoCamera(object):
# filename can be 0 to access the webcam
def __init__(self, filename):
self.lock = threading.Lock()
self.openVideo(filename)
def openVideo(self, filename):
self.lock.acquire()
self.videoCap = cv2.VideoCapture(filename)
self.lock.release()
With this, you should be able to create an object with a lock and to open safely a video (in case that you want to open another video with the same object).
Now you have 2 options, either you create a thread that updates the frame and stores the current one internally or update do in a thread safe manner the get next frame function. I will do the second one here to show you:
def getNextFrame(self):
self.lock.acquire()
img = None
# if no video opened return None
if self.videoCap.isOpened():
ret, img = self.videoCap.read()
self.lock.release()
return img
This way you should be able to access the video cap with 2 frames... however, the frames will be different every time the function is called.
I hope this helps you.

Cron job Issue in raspberry-pi

from time import sleep
import datetime
import os
import shutil
import cv2
from filename import opvideo
## Adding New Directory
path= '/home/pi/Desktop/teasr/input-video'+opvideo
os.makedirs(path)
path1= '/home/pi/Desktop/teasr/input-image'+opvideo
os.makedirs(path1)
os.makedirs('/home/pi/Desktop/teasr/output-video'+opvideo)
#######capturing
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.cv.CV_FOURCC(*'XVID')
out = cv2.VideoWriter('/home/pi/Desktop/teasr/input-video'+opvideo+ '/video.h264',fourcc, 15.0, (640,480))
i=0
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
# write the flipped frame
out.write(frame)
cv2.imshow('frame',frame)
i=i+1
if cv2.waitKey(1) & i>160:
cap.release()
out.release()
cv2.destroyAllWindows()
break
else:
break
`
I am looking to run my code after every 10 minutes using cron job. But whenever i my code running it is not capturing video but it is making directory.I am using USB camera for making video. If i am running my code in terminal every thing looks fine and camera is also working. But at cron job it is not working properly.Please help me out to run my full code using cron job.My main purpose is to make video after every 10 mintues when raspberry pi gets switched on. Hoping that someone may help.

Error while writing video in OpenCV3 with Python

I was running a simple program on reading a video file (.mp4 format) and writing it back after inverting every frame. I get an error and a bug warning.
BUG: The current event queue and the main event queue are not the same. Events will not be handled correctly. This is probably because _TSGetMainThread was called for the first time off the main thread.
Error in CoreDragRemoveTrackingHandler: -1856
I am using El Captain OSX , I have installed python virtual environment to use Python 3.5 with OpenCV 3.2.0-rc. Can somebody help me with this.?
Thanks
import numpy as np
import cv2
cap = cv2.VideoCapture('Root.mp4')
# Define the codec and create VideoWriter object
#fourcc = cv2.VideoWriter_fourcc(*'AVRN')
#out = cv2.VideoWriter('Root1.mp4',fourcc, 20.0, (640,360))
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('Root1.avi',fourcc, 20.0, (640,360))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
# write the flipped frame
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
Seems to be fixed by reinstalling opencv3 with --with-ffmpeg flag.
https://github.com/opencv/opencv/issues/7474
One thing i can tell you, there is no problem in the script you mentioned above :p, it is running fine on my system. Reinstall opencv and python in new virtual environment.
Try this:
cap = cv2.VideoCapture(0)
fps = 15
capSize = (1280, 720)
#print cap.get(3)
#print cap.get(4)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
out = cv2.VideoWriter('output.mov',fourcc, fps, capSize, True)
It works for me, so I hope it helps you!

Video Capture with Python

I'm trying to write some code for automatically capturing video from a webcam when activated through a batch script on Windows. I've managed to piece together a working script, but it does not appear to be saving the file. I know the code is (at least on a basic level) working because there are no errors and the activation light on the webcam lights up when the code is run. I've reproduced the code below if anyone has any suggestions on how to get it writing to a file, that would be great!
import numpy as np
import cv2
import msvcrt
cap = cv2.VideoCapture(0)
w=int(cap.get(cv2.CAP_PROP_FRAME_WIDTH ))
h=int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT ))
sub=raw_input("Subject#: ")
#Define the codec and create VideoWriter object
#fourcc = cv2.VideoWriter_fourcc(*'DIVX')
fourcc = cv2.VideoWriter_fourcc(*'FMP4')
out = cv2.VideoWriter('C:\path\to\output_' + sub + '.mp4', fourcc, 30, (w,h))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
if msvcrt.kbhit():
if ord(msvcrt.getch()) != None:
break
else:
break
#Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
The codec FMP4 is just not being supported by your camera I think. Neither in mine. If I change in your code the encoding to 'MJPG' and write to an '.avi' extension, it works very well.
P.S. Wanted to make a comment but I'm still underage (< 50).

Categories

Resources