Want to capture all frames when a face is present in frame - python

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

Related

Controlling Contrast and Brightness of Video Stream in OpenCV and Python

I’m using OpenCV3 and Python 3.7 to capture a live video stream from my webcam and I want to control the brightness and contrast. I cannot control the camera settings using OpenCV's cap.set(cv2.CAP_PROP_BRIGHTNESS, float) and cap.set(cv2.CAP_PROP_BRIGHTNESS, int) commands so I want to apply the contrast and brightness after each frame is read. The Numpy array of each captured image is (480, 640, 3). The following code properly displays the video stream without any attempt to change the brightness or contrast.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
I get a washed-out video stream when I use Numpy’s clip() method to control the contrast and brightness, even when I set contrast = 1.0 (no change to contrast) and brightness = 0 (no change to brightness). Here is my attempt to control contrast and brightness.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
contrast = 1.0
brightness = 0
frame = np.clip(contrast * frame + brightness, 0, 255)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
How can I control the contrast and brightness of a video stream using OpenCV?
I found the solution using the numpy.clip() method and #fmw42 provided a solution using the cv2.normalize() method. I like the cv2.normalize() solution slightly better because it normalizes the pixel values to 0-255 rather than clip them at 0 or 255. Both solutions are provided here.
The cv2.normalize() solution:
Brightness - shift the alpha and beta values the same amount. Alpha
can be negative and beta can be higher than 255. (If alpha >= 255,
then the picture is white and if beta <= 0, then the picure is black.
Contrast - Widen or shorten the gap between alpha and beta.
Here is the code:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.normalize(frame, frame, 0, 255, cv2.NORM_MINMAX)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
The numpy.clip() solution:
This helped me solve the problem: How to fast change image brightness with python + OpenCV?. I need to:
Convert Red-Green Blue (RGB) to Hue-Saturation-Value (HSV) first
(“Value” is the same as “Brightness”)
“Slice” the Numpy array to the Value portion of the Numpy array and adjust brightness and contrast on that slice
Convert back from HSV to RGB.
Here is the working solution. Vary the contrast and brightness values. numpy.clip() ensures that all the pixel values remain between 0 and 255 in each on the channels (R, G, and B).
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
contrast = 1.25
brightness = 50
frame[:,:,2] = np.clip(contrast * frame[:,:,2] + brightness, 0, 255)
frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
import cv2 as cv
cap = cv.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# normalize the frame
frame = cv.normalize(
frame, None, alpha=0, beta=255, norm_type=cv.NORM_MINMAX, dtype=cv.CV_8UC1
)
# Display the resulting frame
cv.imshow("frame", frame)
# press q to quit
if cv.waitKey(1) & 0xFF == ord("q"):
break

Webcam openCV error: (-215) ssize.width > 0 && ssize.height > 0 in function resize [duplicate]

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

Human Detection output is faster and the feeds is Slow

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.

Can't set frame width and height with [OpenCV] cv2.VideoCapture.set()

I am trying to reduce the frame/window size of my video capture to 320x180 but I can't seem to do it. I am using a Windows Kinect for Xbox One and its connected to my pc using an adapter.
I have tried setting the cv2.CAP_PROP_FRAME_WIDTH to 320 and cv2.CAP_PROP_FRAME_HEIGHT to 180 but once I try and get the values it returns 1920 and 1080. I have also tried installing and reinstalling the Kinect SDK and drivers.
import cv2
import numpy as np
vid = cv2.VideoCapture(0)
vid.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
vid.set(cv2.CAP_PROP_FRAME_HEIGHT, 180)
vid.set(cv2.CAP_PROP_FPS, 25)
print(vid.get(cv2.CAP_PROP_FPS))
print(vid.get(cv2.CAP_PROP_FRAME_WIDTH))
while True:
ret, frame = vid.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
vid.release()
cv2.destroyAllWindows()
print output
I would like help in knowing where the problem stems from and hopefully get a fix.
The idea is to resize the frame without having to worry about setting the default frame size. Instead of using cv2.VideoCapture().set(), you can use cv2.resize() to resize the original 1920x1080 frame into 320x180. But this method does not maintain aspect ratio. If you wanted to maintain aspect ratio, you can use the imutils library. The imutils.resize() function resizes the frame and maintains aspect ratio. Change the width parameter to your desired resolution
import cv2
import imutils
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
ret, frame = cap.read()
frame = imutils.resize(frame, width=320)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Finally I have found that solved this problem
When you try to set random resolution, opencv sets nearest resolution if that resolution is not available.
You can run below command to find out all the available resolutions of your webcam.
uvcdynctrl -f
And set those resolutions only. (my webcam resolutions: 1280x720, 640x480, 640x360)
vid.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
vid.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
Reference: https://techoverflow.net/2018/12/18/how-to-set-cv2-videocapture-image-size/

get frame from video with CV_CAP_PROP_POS_FRAMES in opencv python

I am trying to detect a (photography) flash in a video using OpenCV.
I detected the frame in which the flash occurs (average brightness above a threshold) and now I'd like to get the frame number.
I tried using CV_CAP_PROP_POS_FRAMES from the OpenCV docs without any success.
import numpy as np
import cv2
cap = cv2.VideoCapture('file.MOV')
while(cap.isOpened()):
ret, frame = cap.read()
BW = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)
average = np.average(v) #computes the average brightness
if average > 200: #flash is detected
cv2.imshow('frame',BW)
frameid = cap.get(CV_CAP_PROP_POS_FRAMES) # <--- this line does not work
print(frameid)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Any tips ?
You can either:
Use cap.get(cv2.CAP_PROP_POS_FRAMES) (see here, also), or
increment a variable at each iteration: its current value is the current frame number
From opencv-doc:
When querying a property that is not supported by the backend used by the VideoCapture class, value 0 is returned
Probably it is not supported. In that case you have to count the frame number yourself.

Categories

Resources