I tried using schedule. It works fine but the viewfinder of the webcam is stuck at the initial state so it produces only one image multiple times.
Any help?
import cv2
import time
import schedule
cam = cv2.VideoCapture(0)
cv2.namedWindow("Webcam")
img_counter = 0
def capture():
global img_counter
img_name = "opencv_frame_{}.png".format(img_counter)
cv2.imwrite(img_name, frame)
print("screenshot taken")
img_counter += 1
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:
print("closing the app")
break
else:
schedule.every(5).seconds.do(capture)
while 1:
schedule.run_pending()
time.sleep(1)
cam.release()
cam.destroyAllWindows()
You are suffering from buffering. OpenCV VideoCapture() reads a few frames into a buffer - I think it is 5 but have not checked for a while and it may differ between platforms or versions.
There are a few possible work-arounds depending on your situation:
call read() 4-5 times when you want a frame - it will only take a couple of hundred milliseconds
call grab() either repeatedly in another thread or just before you want a frame
reduce the size of the buffer so it can only hold a single frame.
Sorry for the somewhat woolly answer as I am not set up to test more at the moment.
I think your code could be simplified to something like this while still retaining a near-realtime preview of the periodically saved images.
import cv2
import schedule
cam = cv2.VideoCapture(0)
cv2.namedWindow("Webcam")
img_counter = 0
def capture():
global img_counter
img_name = "opencv_frame_{}.png".format(img_counter)
cv2.imwrite(img_name, frame)
print("screenshot taken")
img_counter += 1
# Set up schedule before loop
schedule.every(5).seconds.do(capture)
while True:
ret, frame = cam.read()
if not ret:
print("failed to grab frame")
break
cv2.imshow("test", frame)
schedule.run_pending()
k = cv2.waitKey(100) # 1/10 sec delay; no need for separate sleep
if k % 256 == 27:
print("closing the app")
break
cam.release()
cam.destroyAllWindows()
I am using LBPH algorithm for face detection. The part of collecting the data and training is working fine but in the testing part, there is an error
This is code for testing
import cv2
import numpy as np
import webbrowser
face_classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
def face_detector(img, size=0.5):
faces = ()
# Convert image to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('Printe1r', gray )
if np.count_nonzero(gray) >= 0:
print("in face detector")
faces = face_classifier.detectMultiScale(gray, 1.3, 5)
if faces is ():
return img, []
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,255),2)
roi = img[y:y+h, x:x+w]
roi = cv2.resize(roi, (200, 200))
return img, roi
# Open Webcam
cap = cv2.VideoCapture(0)
print("WebCam opened")
while True:
ret, frame = cap.read()
cv2.imshow('Printe1rwer', frame )
image, face = face_detector(frame)
cv2.imshow('Printe1aas r', image )
print(face)
try:
print("hell1o")
face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
print("hello")
# Pass face to prediction model
# "results" comprises of a tuple containing the label and the confidence value
results = model.predict(face)
print("Helo",results)
if results[1] < 500:
print("in results < 500")
confidence = int( 100 * (1 - (results[1])/400) )
display_string = str(confidence) + '% Confident it is User'
cv2.putText(face, display_string, (100, 120), cv2.FONT_HERSHEY_COMPLEX, 1, (255,120,150), 2)
if confidence > 75:
print("in confidence < 75")
cv2.putText(face, "Hey Vimal", (250, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (0,255,0), 2)
cv2.imshow('Face Recognition', face )
webbrowser.open('')
break
else:
print("in else")
cv2.putText(face, "Locked", (250, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (0,0,255), 2)
cv2.imshow('Face Recognition', face )
except Exception as e:
print(e)
cv2.putText(frame, "No Face Found", (220, 120) , cv2.FONT_HERSHEY_COMPLEX, 1, (0,0,255), 2)
cv2.putText(frame, "Locked", (250, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (0,0,255), 2)
cv2.imshow('Face Recognition', frame )
pass
if cv2.waitKey(1) == 13: #13 is the Enter Key
break
cap.release()
cv2.destroyAllWindows()
The error I am getting is:
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-1-3a076399e5b1> in <module>
34 ret, frame = cap.read()
35 cv2.imshow('Printe1rwer', frame )
---> 36 image, face = face_detector(frame)
37 cv2.imshow('Printe1aas r', image )
38 print(face)
<ipython-input-1-3a076399e5b1> in face_detector(img, size)
14 if np.count_nonzero(gray) >= 0:
15 print("in face detector")
---> 16 faces = face_classifier.detectMultiScale(gray, 1.3, 5)
17
18 if faces is ():
error: OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp:1689:
error: (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'`
Could somebody help me out??
I am using the OpenCV version 4.2.0
One thing is the value of the variable gray in the face detector function is always a numpy array with all values as zero. I have checked that but it is always zero.
I've tested the first part of your code. It seems to be working, printing gray I get:
TEMP.py:20: SyntaxWarning: "is" with a literal. Did you mean "=="?
if faces is ():
WebCam opened
[[162 162 162 ... 97 97 97]
[161 161 160 ... 95 95 95]
[159 159 161 ... 95 95 95]
...
[252 252 252 ... 164 164 164]
[236 233 229 ... 165 164 164]
[164 158 153 ... 164 164 164]]
Apart from correcting () with == as suggested by the interpreter, I would check:
That the img that comes in face detector is nonzero (just print it, mine is ok).
That you're actually loading the right input source in cap = cv2.VideoCapture(0) (do you have multiple webcams attached?)
Try inserting a if frame: block just after ret, frame = cap.read(). Probably only the first frame is None and it is giving you all the problems.
If the above are ok, the only suspect remains gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)...
A side note: ret, frame = cap.read() reads all the input continuously from the camera, but the pc may be slower than your algorithm in processing every frame. I usually avoid the creation of a long buffer using a trick. After you solve the above, have a look at this.
I tried changing the file path for "haarcascade_frontalface_default.xml" and it worked for me. I mean I provided the exact path for the location.
I am able to process the video frames by saing the frame as an image and then processing it. But was unable to pass frame directly to the object detection.
Saving image with imwrite is making program slow...
Here is my main method:
cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=2), cv2.CAP_GSTREAMER)
if cap.isOpened():
window_handle = cv2.namedWindow("CSI Camera", cv2.WINDOW_AUTOSIZE)
# Window
while cv2.getWindowProperty("CSI Camera", 0) >= 0:
ret_val, frame = cap.read()
if not ret_val:
break
frame = imutils.resize(frame, width=600)
#cv2.imwrite('box.jpg', frame)
#image = Image.open(path)
#Error in here!!!
predictions = od_model.predict_image(frame)
for x in range(len(predictions)):
probab = (predictions[x]['probability'])*100
if(probab > 45):
print(predictions[x]['tagName'], end=' ')
print(probab)
#cv2.imshow("CSI Camera", frame)
# This also acts as
keyCode = cv2.waitKey(30) & 0xFF
# Stop the program on the ESC key
if keyCode == 27:
break
cap.release()
cv2.destroyAllWindows()
else:
print("Unable to open camera")
Error Message:
predictions = od_model.predict_image(frame)
File "/home/bharat/New_IT3/object_detection.py", line 125, in
predict_image
inputs = self.preprocess(image)
File "/home/bharat/New_IT3/object_detection.py", line 130, in
preprocess
image = image.convert("RGB") if image.mode != "RGB" else image
AttributeError: 'numpy.ndarray' object has no attribute 'mode'
open cv reads image in bgr colour spectrum conver it to rgb and send the image for detection, api for the same is -
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
For my project I have multiple cameras and I need to save the video feed to multiple output files at the same time. Here's my code:
import cv2
def one_cam_is_open(list_of_cams):
for cam in list_of_cams:
if cam.isOpened():
return True
return False
cam_list = []
# Capture video from camera
for i in range(0, 2):
cap = cv2.VideoCapture(i)
if cap!=-1:
cam_list.append(cv2.VideoCapture(i))
# the width and height of all cameras will be 1900x1080
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) + 0.5)
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) + 0.5)
dim = (1900, 1080)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Be sure to use the lower case
video_writers = {}
for i, cam in enumerate(cam_list):
video_writers[cam] = cv2.VideoWriter("output_" + str(i) + ".mp4", fourcc, 20.0, dim)
while one_cam_is_open(cam_list):
for (cam, out) in video_writers:#TypeError: cannot unpack non-iterable cv2.VideoCapture object
ret, frame = cam.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'): # Hit `q` to exit
break
else:
break
# Release everything if job is finished
for (cam, out) in video_writers:
out.release()
cam.release()
cv2.destroyAllWindows()
As noted in the code, I get the error TypeError: cannot unpack non-iterable cv2.VideoCapture object when I try to unpack the references to the VideoWriter obejects for each camera.
Is there a way to write to multiple video files using VideoWriter?
I use opencv to open a video, process frame by frame and write it back to a video. For some videos, this works fine, but for others, I got this wired error when I try to write the frames back to a video:
cv2.error: /home/xxx/Documents/opencv_videos/opencv/modules/videoio/src/cap_mjpeg_encoder.cpp:829: error: (-215) img.cols == width && img.rows == height && channels == 3 in function write
Here is what my code looks like:
cap = cv2.VideoCapture('cut.avi')
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output.avi',fourcc, 25.0, (1280,720))
count = 0
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
processed_frame = PROCESS(frame)
cv2.imwrite('temp.jpg',processed_frame)
out.write(processed_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
I can, however, use cv2.imwrite to write the process frame to a jpeg image on disk. Does anyone know where this error comes from? Thanks!