how to resize live video in python cv2 using .set()? - python

I am learning opencv with https://www.youtube.com/watch?v=oXlwWbU8l2o&ab_channel=freeCodeCamp.org this tutorial and I arrived at part 3 (resizing and rescaling). Towards the end he creates this function which should be better for live video. The function doesn't return anything and he doesn't show how it works. The funtion is change_res(width, height) and I think it should be called in the while loop for frame_resized.
import cv2 as cv
def rescale_frame(frame, scale): # works for image, video, live video
width = int(frame.shape[1] * scale)
height = int(frame.shape[0] * scale)
dimensions = (width, height)
return cv.resize(frame, dimensions, interpolation=cv.INTER_AREA)
def change_res(width, height): # works only for live video
capture.set(3, width)
capture.set(4, height)
capture = cv.VideoCapture(0) # integer to capture from webcam, path to capture video file
while True:
isTrue, frame = capture.read()
frame_resized = rescale_frame(frame, scale=.2) # this line
cv.imshow("Video", frame)
cv.imshow("Video Resized", frame_resized)
if cv.waitKey(20) & 0xFF == ord("q"): # press "q" key to exit loop
break
capture.release()
cv.destroyAllWindows()

Thanks to #Dan Mašek 's comment I managed to understand.
The .set() method changes the resolution of the camera, it doesnt need to be in the while loop because capture = cv.VideoCapture(0) keeps going by defeault forever unless capture.release() is called.
import cv2 as cv
def rescale_frame(frame, scale): # works for image, video, live video
width = int(frame.shape[1] * scale)
height = int(frame.shape[0] * scale)
dimensions = (width, height)
return cv.resize(frame, dimensions, interpolation=cv.INTER_AREA)
capture = cv.VideoCapture(0) # integer to capture from webcam, path to capture video file
capture.set(3, 1440)
while True:
isTrue, frame = capture.read()
frame_resized = rescale_frame(frame, scale=.2)
cv.imshow("video with set", frame)
cv.imshow("Video Resized", frame_resized)
if cv.waitKey(20) & 0xFF == ord("q"): # press "q" key to exit loop
break
capture.release() # stop capturing the image/video
cv.destroyAllWindows() # close windows
So, I wanted a small and a big window showing what the webcam was capturing. Currently this code captures the video, makes it 2560x1440 (with .set) which is enormous and then it takes those frames and rescales them with the rescale_frame function to make it smaller.
I found out that this .set() method is more efficient for a single video but if I want two I should show as small the default one and then use rescale_frame to make it bigger.

Related

openCV - camera view window has different size of camera resolution

I have a 720p resolution camera and I'm trying to open the camera in a view window in openCV. here's the code:
while(True):
ret, frame = vid.read()
if render_poly:
frame = cv2.polylines(frame, [pts],
isClosed, color, thickness)
cv2.imshow('window', frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('p'):
render_poly = not render_poly
Before that, I tried to ajust the view window with this code (720p resolution):
vid = cv2.VideoCapture(0)
vid.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
vid.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
What I expected is 1280x720 view window size, but for some reason I got 1600x900 which caused incorrect positioning of the polygon I'm trying to render, and to solve that I needed to adjust its coordinates by multiplying it with the scale of 1280/1600 in width and 720/900 in height.
Can I skip that proccess (which will be more in the future project) and just to render the camera view on a window with its same resolution size? is it a good idea?

How to append an image to a video using OpenCV or FFMPEG or Moviepy or other libraries?

Do you know a library in Python to add a frame image to an existing video? The result video must have the same quality as the image.
I tried to use OpenCV to add google image: https://www.google.com/search?q=google&sxsrf=ALiCzsZhrdoHnOTmg0We4dxtguCqzma5Jg:1657603343101&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiTh8bTzfL4AhWhplYBHfXNAKwQ_AUoAXoECAIQAw&biw=1492&bih=739&dpr=1.25#imgrc=PRtenhDnrVrfOM
But the quality decreases when the video elongates.
Here is the final result video : https://drive.google.com/file/d/1ArDvoX-kN9H_oLbACk3kU1Cid93SMczC/view?usp=sharing
Here is my code using OpenCV:
image = cv2.imread(path_image)
height, width, dimensions = image.shape
video = cv2.VideoCapture(path_video)
frames = []
while(True):
ret, frame = video.read()
if ret == True:
frames.append(frame)
# frame = frame.resize(frame, (width, height), fx=0, fy=0, interpolation = cv2.INTER_CUBIC)
# Press S on keyboard
# to stop the process
if cv2.waitKey(1) & 0xFF == ord('s'):
break
# Break the loop
else:
break
video2 = cv2.VideoWriter(path_video,cv2.VideoWriter_fourcc('M','J','P','G'), 30, (width, height))
for frame in frames:
video2.write(frame)
video2.write(image)
video2.release() # releasing the video generated
print("Added {}".format(image_name))
I hope to improve the quality of this video.
I guess a simple way to achieve that using moviepy would be the following:
from moviepy.editor import *
from PIL import Image
import numpy as np
maxsize = (target_width, target_height)
jpg_image = Image.open(path_to_the_image)
# modify the image's resolution to be the target one
jpg_image.thumbnail(maxsize, Image.ANTIALIAS)
jpg_image = np.array(jpg_image)
image = ImageClip(jpg_image).set_duration(target_duration)
clip = VideoFileClip(path_to_the_video)
video = concatenate([image, clip], method="compose")
video.write_videofile("output_example.mp4", fps=target_fps)
As long as you set the target resolution of the image to match the video's one you are set with just that.

Video Screen Capture using python and OpenCv and video not opening

importing the required packages
`import pyautogui
import cv2
import numpy as np`
Specify resolution
`resolution = (1920, 1080)`
Specify video codec
`codec = cv2.VideoWriter_fourcc(*"XVID")`
Specify frames rate. We can choose any
value and experiment with it
`fps = 60.0`
Creating a VideoWriter object
`out = cv2.VideoWriter("Recording.avi", codec, fps, resolution)`
Create an Empty window
`cv2.namedWindow("Live", cv2.WINDOW_NORMAL)`
# Resize this window
`cv2.resizeWindow("Live", 480, 270)`
`while True:
# Take screenshot using PyAutoGUI
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
# Optional: Display the recording screen
cv2.imshow('Live', frame)
# Stop recording when we press 'Esc'
k = cv2.waitKey(10) & 0xFF # press 'Esc' to exit
if k == 27:
break
# Release the Video writer
out.release()
# Destroy all windows
cv2.destroyAllWindows()`
the video was successfully but in the end I could not open the video file "Recording.avi" or to be specific my video player won't play it
any help?

My Screen Recorder built using OpenCV and PyAutoGUI records only one frame

I am building a Screen Recorder in Python using numpy, OpenCV and PyAutoGUI. I have used tkinter for GUI Purposes. The problem with my screen recorder is that it records only one frame when I click on the Record Screen Button and then the screen gets jammed and I can't do anything. Here is my code so far:
from tkinter import *
import cv2
import numpy as np
import pyautogui
resolution = (1366,768)
Specify video codec:
codec = cv2.VideoWriter_fourcc(*"XVID")
Specify name of Output file:
filename = "Recordings.avi"
Specify frames rate (we can choose any value and experiment with it):
fps = 30.0
Creating a VideoWriter object:
out = cv2.VideoWriter(filename, codec, fps, resolution)
def startRecording():
window.iconify()
while True:
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
def stopRecording():
cv2.destroyAllWindows()
out.release()
window.destroy()
window = Tk()
window.title("Screen Recorder")
window.geometry("400x150")
window.config(bg='pink')
recordButton = Button(window,text="Record(F9)",font=("Bell MT",20),width=20,command=startRecording)
recordButton.pack(pady=(10,0))
stopButton = Button(window,text="Stop(F10)",font=("Bell MT",20),width=20,command=stopRecording)
stopButton.pack(pady=(10,0))
mainloop()
You cannot do a blocking call in a button callback.
As you wrote it startRecording will never end and will hence block tkinter mainloop. The recording probably works but your UI becomes unresponsive.
Your best shot would be to schedule the recording (look for the after method): record one frame every x millisecond.
Here is a simplified example based on your original code (you need to complete it)
continueRecording = True # must be declared before stopRecording
window = Tk() # must be declared before recordOneFrame
def stopRecording():
global continueRecording
continueRecording = False
def recordOneFrame():
global continueRecording
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
if continueRecording:
window.after(round(1/25. * 1000),recordOneFrame)
def startRecording():
recordOneFrame()

Closing an image window displays another window. Why?

I'm stuck. My code sucks. My silders don't work either, but the infinite image windows are driving me nuts. When I close the namedWindow, it opens a new display window with the image (infinitely). Help?
import numpy as np
import cv2
from pylepton import Lepton
#setup the Lepton image buffer
def capture(device = "/dev/spidev0.0"):
with Lepton() as l:
a,_ = l.capture() #grab the buffer
cv2.normalize(a, a, 0, 65535, cv2.NORM_MINMAX) # extend contrast
np.right_shift(a, 8, a) # fit data into 8 bits
return np.uint8(a)
#Create a window and give it features
def nothing(x):
pass
cv2.namedWindow('flir', cv2.WINDOW_NORMAL)
cv2.moveWindow('flir',1,1)
cv2.createTrackbar('thresh','flir',50,100,nothing)
cv2.createTrackbar('erode','flir',5,100,nothing)
cv2.createTrackbar('dilate','flir',7,100,nothing)
#process the buffer into an image on a continuous loop
while True:
#update the image processing variables
thresh = cv2.getTrackbarPos('thresh', 'flir')
erodeSize = cv2.getTrackbarPos('erode', 'flir')
dilateSize = cv2.getTrackbarPos('dilate', 'flir')
image = capture()
#apply some image processing
blurredBrightness = cv2.bilateralFilter(image,9,150,150)
thresh = 50
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)
_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 14
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))
adjusted_image = cv2.resize(cv2.cvtColor(mask*edges, cv2.COLOR_GRAY2RGB) | image, (640, 4$
final_image = cv2.applyColorMap(adjusted_image, cv2.COLORMAP_HOT)
#display the image
cv2.imshow('flir', final_image)
if cv2.waitKey(1) == ord('q'):
break
cv2.waitKey()
cv2.destroyWindow('flir')
Firstly, Calm down.
Secondly, look at your code closely. Closing the window wouldn't do you any good, because of the lines:
cv2.imshow('flir', final_image)
and
cv2.destroyWindow('flir')
What these 2 are doing in tandem is that you're displaying a frame in a new window, and then destroying it, then recreating that window in imshow, then displaying the next frame and destroying it...and so on and so forth.
That should explain your flickering windows.
To stop execution of your program, you've added this code:
if cv2.waitKey(1) == ord('q'):
break
What this implies is that when you press 'q' on your keyboard while your image window is in focus, your while loop will break and your program will terminate.
So I would advise you to remove cv2.destroyWindow and use 'q' key to quit your application than to close it using your mouse.

Categories