This is my first time coding in image processing using python and OpenCV. My first project is using webcam to creates a Human Motion detection and display their walking speed in real-time monitoring feed and now the first step I have created a program to detect human motion but the feed is super slow and the results of the output video are very fast. For example, I have running the program for about 1 minutes but the output video duration is only 7-10 seconds. I don't know how to fix this because I have try some adjustments like changing the waitKey() and the fps. I'm using HOG methods to detect human motion.
note : I'm using Logitech C270 with 30fps
this is my program:
import cv2
import numpy as np
import imutils
import time
#initialize the HOG descriptor/person detector
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
cv2.startWindowThread()
#open webcam video stream
cap = cv2.VideoCapture(1)
#output will be written to output.avi
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output_4.avi', fourcc, 18.0, (640,480))
frameCount = 0
start_time = time.time()
while(True):
#capture frame-by-frame
ret, frame = cap.read()
cv2.waitKey(30)
#resizing for faster detection
frame = cv2.resize(frame, (640,480))
#using a greyscale picture, also for faster detection
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
#detect people in the image
boxes, weights = hog.detectMultiScale(frame, winStride=(8,8))
#returns the bounding boxes for the detected objects
boxes = np.array([[x, y, x+w, y+h] for (x,y,w,h) in boxes])
#final bounding boxes
for (xA, yA, xB, yB) in boxes:
cv2.rectangle(frame, (xA, yA), (xB, yB),
(0,255,0),2)
#write the output video
out.write(frame)
#display the resulting frame
cv2.imshow('Human Detection',frame)
if cv2.waitKey(30) & 0xFF == ord('q'):
break
#release the capture
cap.release()
#release the output
out.release()
#close the window
cv2.destroyAllWindows()
cv2.waitKey(30)
Thank You.I hope you can help me.
Related
I am trying to build a dataset of face images, I have searched and find a code that is working fine with my laptop's webcam but when I am trying to capture with IP Camera which is usually used for surveillance than code is not working.
import cv2
import numpy as np
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
cap = cv2.VideoCapture(0)
count = 0
while True:
ret,frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.imwrite("frame%d.jpg" % count, frame)
count = count + 1
if cv2.waitKey(2) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Another thing I want to mention my laptop Camera resolution is 640.0 480.0 and IP Cameras have 2560.0 1440.0. Please help me to capture all frames when face is present.
To capture images from specific camera you need to change arguments in cv2.VideoCapture(argument). For example:
cv2.VideoCapture(0): it's used to select the default camera, generally laptop inbuilt camera.
cv2.VideoCapture(n) where n>=1: it's used to select the other external camera connect to laptop through usb/other ports
cv2.VideoCapture('protocol://IP:port/1'): it's used to take input from network cameras(like in your case)
Here protocol means: HTTP/RTSP etc.
IP means hosting address: Example: 192.168.18.37
port where the IP address is accessed
In this case it should be:
cv2.VideoCapture('rtsp://admin:admin#192.1.1.24/H264?ch=2&subtype=0/1')
The issue has been resolved after adjusting the resolution, I have added the line of code for frame adjustment frame = cv2.resize(frame, (1360, 768)) than code has started working properly.
This code might be helpful for anyone.
import cv2
import numpy as np
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
cap = cv2.VideoCapture('rtsp://admin:admin#192.1.1.24/H264?ch=2&subtype=0/1')
count = 0
while True:
ret,frame = cap.read()
frame = cv2.resize(frame, (1360, 768))
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.imwrite("frame%d.jpg" % count, frame)
count = count + 1
if cv2.waitKey(2) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Changing the resolution before image capture is more optimal. There would be no need to resize every subsequent frame.
Before the while loop set the width and height as follows:
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 768)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1380)
Different flags used for video streaming
I'm trying to build a face detector with webcam using opencv in Python.
When human face is detected, the system need to be able to capture only one photo of face per person and save it automatically (without pressing a key), until the person leaves the frame and another person enters and again his face detected and saved in an image file.
I'm using a while loop for the live video stream and the continous face detection. I tried to create an inner while loop for saving the face photo, but it takes multiple frames.
The code:
import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap=cv2.VideoCapture(0)
while True:
ret, img=cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5, minSize=(150, 150), maxSize=(300, 300))
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
face_img_gray = gray[y:y+h, x:x+w]
face_img_color = img[y:y+h, x:x+w]
laplacian_var = cv2.Laplacian(face_img_gray, cv2.CV_64F).var()
#print(laplacian_var)
if laplacian_var > 140: # avoid blur frame capture
cv2.imwrite('Frame.jpg', face_img_color)
cv2.imshow('img', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
This code works corectly , But it's a very slow .
I changed the cv2.waitKey(1) number. But it still didn't change much
import cv2
import numpy as np
facexml = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eyexml = cv2.CascadeClassifier("haarcascade_eye.xml")
cap = cv2.VideoCapture("my_video.avi")
while True:
_,frame = cap.read()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
faces = facexml.detectMultiScale(gray)
for (x,y,w,h) in faces:
cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = frame[y:y+h, x:x+w]
eyes = eyexml.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,0,255),1)
cv2.imshow("window",frame)
if cv2.waitKey(1) & 0XFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
Simply a Harris cascade classifier is an old and slow algorithm for fast online face recognition in video. Try to read an OpenCV manual on Cascade Classifier and reduce the number of scales by setting equal maxSize and minSize or set larger scaleFactor to decrease total amount of images computed from original image by resizing.
This question already has answers here:
OpenCV Error: (-215)size.width>0 && size.height>0 in function imshow
(17 answers)
Closed 2 years ago.
I've seen the other stack exchange posts about this exact same error, but instead of reading from an image or a list of images, my script reads from a webcam. BTW, this script is copied, and i'm trying to get it working as an example for me to learn how it all works.
import numpy as np
import cv2
# set up HOG person detector and create hog object
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
cv2.startWindowThread()
# set up video capture, make cap video stream object
cap = cv2.VideoCapture(0)
# write file output to output.avi in 640x480 size
out = cv2.VideoWriter(
'output.avi',
cv2.VideoWriter_fourcc(*'MJPG'),
15.,
(640,480))
if cap is not None:
while(True):
# read the webcam
ret, frame = cap.read()
# resizing for faster detection
frame = cv2.resize(frame, (640, 480))
# using a greyscale picture, also for faster detection
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
# detect people in the image
# returns the bounding boxes for the detected objects
boxes, weights = hog.detectMultiScale(frame, winStride=(8,8) )
boxes = np.array([[x, y, x + w, y + h] for (x, y, w, h) in boxes])
for (xA, yA, xB, yB) in boxes:
# display the detected boxes in the colour picture
cv2.rectangle(frame, (xA, yA), (xB, yB),
(0, 255, 0), 2)
# Write the output video
out.write(frame.astype('uint8'))
# Display the resulting frame
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
# and release the output
out.release()
# finally, close the window
cv2.destroyAllWindows()
cv2.waitKey(1)
I understand that the error is caused because there is no image for the resize function to resize, so I added the if cap is not None: statement, but I still get the same error. How can I fix this in this script?
From what I've gathered from your post above, you don't want to use a webcame in any sort of capacity. If so, You might be experiencing some errors with this portion of the script
# set up video capture, make cap video stream object
cap = cv2.VideoCapture(0)
# write file output to output.avi in 640x480 size
out = cv2.VideoWriter(
'output.avi',
cv2.VideoWriter_fourcc(*'MJPG'),
15.,
(640,480))
Here you are setting up a video stream, then loading in an avi. If you just want to read in an image you can use the below code.
import numpy as np
import cv2
# Load an color image in grayscale
img = cv2.imread('inputImage.jpg',0)
#Display the input image
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
You can find more about images and Opencv below.
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_image_display/py_image_display.html
I am making a program that uses a webcam to track objects in real time. The resulting display is always a few frames behind. For an example, when I move the camera to point at a new spot, it still shows the first position for a few frames.
Here is my program, it should find the circles in the frame and return an image with them circled:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles() # parameters removed
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
#draw circle
cv2.circle() # parameters removed
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0XFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
As you can see it takes some time to process each frame. I expected the it to be choppy, but the result shows images from several seconds ago.