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

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/

Related

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

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

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

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.

How do I display multiple webcam feeds side by side using OpenCV Beta 3.0.0 and Python?

I am working on a project that requires that I display 3 (and possibly more) webcam feeds side by side. To tackle this project, I am using OpenCV Beta 3.0.0 and Python 2.7.5 because I am slightly familiar with the language. Also, how do I display the video in color?
Here is my current code:
import cv2
import numpy as np
capture = cv2.VideoCapture(0)
capture1 = cv2.VideoCapture(1)
while True:
ret, frame = capture.read()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow("frame",gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
capture.release()
cv2.destroyAllWindows()
import cv2
import numpy as np
capture = cv2.VideoCapture(0)
capture1 = cv2.VideoCapture(1)
while True:
_, frame1 = capture.read()
_, frame2 = capture1.read()
frame1 = cv2.cvtColor(frame1,cv2.COLOR_BGR2RGB)
frame2 = cv2.cvtColor(frame2,cv2.COLOR_BGR2RGB)
cv2.imshow("frame1",frame1)
cv2.imshow("frame2",frame2)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
capture1.release()
capture2.release()
cv2.destroyAllWindows()
To display color you simply don't convert to grayscale. To show two frames simultaneously just call imshow() twice. As for side by side, you can play with the frame positions if you really want. Also notice that the I converted the frames from BGR to RGB.

OpenCV Python Video playback - How to set the right delay for cv2.waitKey()

I used the following code to capture a video file, flip it and save it.
#To save a Video File
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.cv.CV_FOURCC(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
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()
This program saves the output as output.avi
Now, to playback the video file I used the following program
#Playing Video from File
import numpy as np
import cv2
cap = cv2.VideoCapture('output.avi')
print cap.get(5) #to display frame rate of video
#print cap.get(cv2.cv.CV_CAP_PROP_FPS)
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #convert to grayscale
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
This program plays the video file output.avi saved from the first program. The thing is, this video appears fast forward. So, I tried changing the delay value for cv2.waitKey(). The video looked fine when I put 100. How do I know which value to put there? Should it be related to the frame rate? I checked the frame rate of output.avi (see line cap.get(5) in second program) and got 20. But if I use 20 as delay for cv2.waitKey() the video is still too fast.
Any help would be appreciated.
From the OpenCV documentation:
The function cv.waitKey([, delay]) waits for a key event infinitely
(when delay <= 0) or for delay milliseconds, when it is positive.
If the FPS is equal to 20, then you should wait 0,05 seconds between displaying the consecutive frames. So just put waitKey(50) after imshow() in order to have the desired speed for the playback.
For what it is worth, I have tried all sorts of tricks with setting the cv2.waitKey() delay time and they have all failed. What I have found to work is to try something like:key = cv2.waitKey(1) inside of your while(cap.isOpened()) like so:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.cv.CV_FOURCC(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
key = cv2.waitKey(1)
frame = cv2.flip(frame,0)
# write the flipped frame
out.write(frame)
cv2.imshow('frame',frame)
if key & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
I hope this helps someone out there.
put waitKey(60) after imshow() and it will be displayed at normal speed.

Categories

Resources