Auto-capture an image from a video in OpenCV using python - python

I am trying developing a code which functions as the self-timer camera. The video would be seen in the window and the person's face and eyes would be continuously detected and once the user selects a specific time, the frame at that point of time is captured. I am able to capture the frame after a certain time using sleep function in time module but the video frame seems to freeze. Is there any solution such that I can continue to see the video and the video capture takes place after some delay automatically.
I am using the code-
import numpy as np
import cv2
import time
import cv2.cv as cv
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',frame)
#time.sleep(01)
Capture = cv.CaptureFromCAM(0)
time.sleep(5)
ret, frame = cap.read()
image = cv.QueryFrame(Capture) #here you have an IplImage
imgarray = np.asarray(image[:,:]) #this is the way I use to convert it to numpy array
cv2.imshow('capImage', imgarray)
cv2.waitKey(0)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
Can someone suggest me? Any kind of help would be appreciated.

In order to continuously view the video, you need to repeat the same part of the code which displays the video first and put it in a while loop. Make sure that the handle to the window is not lost.You can make the capture as a mouse click event and use a tickcount, one before the start of the while loop and one inside the loop. Once the difference between the two tick counts is equal to some pre-defined seconds,capture that frame, use break and come out of the while loop.

You need to add another 'cap.read()' line when the delay ends, as this is the code that actually captures the image.

use threading and define the cv.imshow() separately from your function
import threading
import cv2
def getFrame():
global frame
while True:
frame = video_capture.read()[1]
def face_analyse():
while True:
#do some of the opeartion you want
def realtime():
while True:
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
video_capture.release()
cv2.destroyAllWindows()
break
if __name__ == "__main__":
video_capture = cv2.VideoCapture(cam)
frame = video_capture.read()[1]
gfthread = threading.Thread(target=getFrame, args='')
gfthread.daemon = True
gfthread.start()
rtthread = threading.Thread(target=realtime, args='')
rtthread.daemon = True
rtthread.start()
fathread = threading.Thread(target=face_analyse, args='')
fathread.daemon = True
fathread.start()
while True: #keep main thread running while the other two threads are non-daemon
pass

Related

Video playback using Tkinter and OpenCV too slow

If I use OpenCV to play video into its own window using this sort of logic:
cap = cv2.VideoCapture('video.mp4',cv2.CAP_FFMPEG)
while True:
ret, frame = cap.read()
if(ret):
cv2.imshow('', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
then it works well and smoothly. But if I use what appears to be the recommended way of playing into my own tkinter window, using the window.after() technique like this snippet:
def update(self):
# Get a frame from the video source
ret, frame = cap.read()
self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
self.canvas.create_image(0, 0, image = self.photo, anchor = tk.NW)
self.update_id = self.window.after(self.VIDEO_READ_DELAY, self.update)
it is slow and stutters badly. I've played with the update delay without any real success, so I'm guessing that the processing overhead of the image conversion is what's causing the problem.
Can imshow() be made to play into my tkinter canvas directly?

Is there a way to check if camera is connected without cap = cv2.videocapture

I am making a program that checks if the camera is connected, and if so, Show the webcam footage, The problem is: The way i structured my program i cannot have cap = cv2.videocapture() for the time it takes the command to execute. This makes sabotages for the showframe function and makes it only show a frame every ~1 second. Is there a different way to check if the camera is connected rather than cap = cv2.videocapture() and cap.isOpened()?
I also cannot have a while loop in my program because of the root.mainloop command for tkinter, However, if there is no way to check my camera status rather than cap.isOpened(), can i move the root.mainloop command somewhere where i can have a while True loop in my program?
I've tried both Multiprocessesing and Threading with no further success.
Heres some code:
from tkinter import * # Import the tkinter module (For the Graphical User Interface)
import cv2 # Import the cv2 module for web camera footage
import PIL # Import the pillow library for image configuration.
from PIL import Image, ImageTk # Import the specifics for Image configuration.
print("[INFO] Imports done")
width, height = 800, 600 # Define The width and height widget for cap adjustment
RootGeometry = str(width) + "x" + str(height) # Make a variable to adjust tkinter frame
print("[INFO] Geometries made")
ImageSource = 0
cap = cv2.VideoCapture(ImageSource) # First VideoCapture
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
print("[INFO] Cap set")
root = Tk()
print("[INFO] Window made")
root.title("Main Window")
root.configure(background="white")
root.geometry(RootGeometry)
root.bind('<Escape>', lambda e: root.quit())
lmain = Label(root)
lmain.pack()
print("[INFO] Configuration of cap done.")
def ShowFrame():
ok, frame = cap.read()
if ok:
print("[INFO] Show frame Initialized.")
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = PIL.Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
lmain.imgtk = imgtk
lmain.configure(image=imgtk)
print("[INFO] After 10 initializing")
lmain.after(10, ShowFrame)
print("[INFO] Showed image")
else:
lmain.after(10, CheckSource)
def CheckSource():
print("[INFO] CheckSource Triggered.")
cap = cv2.VideoCapture(ImageSource)
if cap.isOpened():
print("[INFO] [DEBUG] if Ok initialized")
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.destroyAllWindows()
cv2.waitKey(0)
print("[WARNING] Exiting app after command")
ShowFrame()
else:
print("[WARNING] No source found. Looking for source.")
lmain.after(10, CheckSource)
CheckSource()
root.mainloop()
print("[INFO] [DEBUG] Root.Mainoop triggered")
Any and all help would be very appreciated!
When there is no webcam/image source, cap.read() will be (False, none). Therefore you can check if a webcam is connected if you do something like:
import cv2
cap=cv2.VideoCapture(ImageSource)
while True:
if cap.read()[0]==False:
print("Not connected")
cap=cv2.VideoCapture(imageSource)
else:
ret, frame=cap.read()
cv2.imshow("webcam footage",frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Hope this helps :)
You should not do a VideoCapture each frame, you only need to check if it exists. isOpened() is the proper function for that. If it does not yet exist, then retry the cam.
I modified your code:
def CheckSource():
print("[INFO] CheckSource Triggered.")
# check if cam is open, if so, do showFrame
if cap.isOpened():
print("[INFO] [DEBUG] if Ok initialized")
if cv2.waitKey(1) & 0xFF == ord('q'):
cv2.destroyAllWindows()
cv2.waitKey(0)
print("[WARNING] Exiting app after command")
ShowFrame()
else:
# cam is not open, try VideoCapture
print("[WARNING] No source found. Looking for source.")
cap = cv2.VideoCapture(ImageSource)
lmain.after(10, CheckSource)

Open cv and Tkinter

I am trying to load a video frame to tkinter label. I tried running following method. my web cam turns on but feed does not loads on the label. Is there a time interval limit I should use of ?
self.cap = cv2.VideoCapture(0)
self.updateCamera()
def updateCamera(self):
# Get a frame from the video source
ret, frame = self.cap.read()
frame = cv2.resize(frame, (800,600))
frame = PIL.Image.fromarray(frame)
frame = PIL.ImageTk.PhotoImage(frame)
self.camraLabel.configure(image=frame)
print("Here")
self.camraLabel.after(1000,self.updateCamera)
if I comment out self.camraLabel.after(1000,self.updateCamera) a still image appears on the label. Can't think of what I have done wrong.
You created a recursive function that will never end. This is bad, can you see how the function will never exit? It also prevents the label from updating, so you never see an image. Instead you should use a time based loop, like for example the following:
import time
import cv2
# store current time
curr_time = time.time()
# get camera
self.cap = cv2.VideoCapture(0)
def updateCamera(self):
# Get a frame from the video source
ret, frame = self.cap.read()
frame = cv2.resize(frame, (800,600))
frame = PIL.Image.fromarray(frame)
frame = PIL.ImageTk.PhotoImage(frame)
self.camraLabel.configure(image=frame)
print("Here")
# loop forever
while True:
# check if the frame needs to be updated
if time.time()-curr_time > 1:
# if more then a second has passed,
# get a new frame and update curr_time
self.updateCamera()
curr_time = time.time()
# do other stuf
Disclaimer: untested code

Use VideoCapture() in two different function within same class OpenCV Python

I'm making a GUI in which one button will display the video and another button will start capturing frames from that video at certain intervals.
Here, are the functions that are called by the buttons:-
def capture(self):
global img_location
global camera
camera = cv2.VideoCapture(1)
return_value, image = camera.read()
time.sleep(2) #set the delay you want in frame
now_time = strftime("%Y-%m-%d %H:%M:%S", gmtime())
img_location = './timelapse_focus/'+FolderName+'/'+ now_time +'.jpg'
cv2.imwrite(img_location, image)
del(camera)
def display(self):
# Create a VideoCapture object and read from input file
# If the input is the camera, pass 0 instead of the video file name
# Check if camera opened successfully
camera = cv2.VideoCapture(1)
if (camera.isOpened()== False):
print("Error opening video stream or file")
# Read until video is completed
while(camera.isOpened()):
# Capture frame-by-frame
ret, frame = camera.read()
if ret == True:
# Display the resulting frame
cv2.imshow('Frame',frame)
# Press <q> on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release the video capture object
camera.release()
# Closes all the frames
cv2.destroyAllWindows()
for i in range (1,5):
cv2.waitKey(1)
It's showing the following error:-
HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV
VIDIOC_STREAMON: Bad file descriptor
Unable to stop the stream.: Bad file descriptor
To do the same I tried to declare the camera variable globally.
But it's not working. Even I used self. camera, it is also not working.
Please suggest something.
The problem here is that you try to open cv2.VideoCapture(1) both in the display(self) and in the capture(self). Set frame as self.frame in display(self) and use it in capture(self). Like this:
def capture(self):
time.sleep(2) #set the delay you want in frame
now_time = strftime("%Y-%m-%d %H:%M:%S", gmtime())
img_location = './timelapse_focus/'+FolderName+'/'+ now_time +'.jpg'
cv2.imwrite(img_location, self.frame)
def display(self):
# Create a VideoCapture object and read from input file
# If the input is the camera, pass 0 instead of the video file name
# Check if camera opened successfully
camera = cv2.VideoCapture(1)
if (camera.isOpened()== False):
print("Error opening video stream or file")
# Read until video is completed
while(camera.isOpened()):
# Capture frame-by-frame
ret, self.frame = self.camera.read()
if ret == True:
# Display the resulting frame
cv2.imshow('Frame',self.frame)
# Press <q> on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release the video capture object
camera.release()
# Closes all the frames
cv2.destroyAllWindows()
for i in range (1,5):
cv2.waitKey(1)
This is only for capturing one frame each time you call capture(self). Otherwise you need to add a while loop and the method in a Thread in order not to crash your GUI.

Display Web cam Python

I have this code for web cam and should be displayed in the window (designed in Qt designer) this code works well but now i have two cam windows, one in my Main window (form designed in Qt Designer) and one out of the Main window.
def b1_clicked(self):
mycam = cv2.VideoCapture(0)
if mycam.isOpened():
_, frame = mycam.read()
else:
_, frame = False
while (True):
cv2.imshow("preview", frame)
_, frame = mycam.read()
frame = cv2.cvtColor(frame, cv2.cv.CV_BGR2RGB)
image = QtGui.QImage(frame, frame.shape[1], frame.shape[0],frame.strides[0], QtGui.QImage.Format_RGB888)
self.label.setPixmap(QtGui.QPixmap.fromImage(image))
key = cv2.waitKey(20)
if key == 27: # escape ESC
break
Please any suggestion how to kill and make it not visible the form which is out of the Main window.
Thanks
Comment out cv2.imshow which opens its own window.

Categories

Resources