I want to apply zoom in and out effect on a video using opencv, but as opencv doesn’t come with built in zoom, I try cropping the frame to the interpolated value’s width, height, x and y and than resize back the frame to the original video size, i.e. 1920 x 1080.
But when I rendered the final video, there is shakiness in the final video. I am not sure why its happening, I want a perfect smooth zoom in and out from the specific time
I built a easing function that would give interpolated value for each frame for zoom in and out :-
video_path = 'inputTest.mp4'
cap = cv2.VideoCapture(video_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (1920, 1080))
'initialZoomWidth': 1920,
'initialZoomHeight': 1080,
async def zoomInInterpolation(initialZoomValue, desiredZoom, start, end, index):
t = (index - start) / (end - start)
eased_t = ease_out_quart(t)
interpolatedWidth = round(initialZoomValue['initialZoomWidth'] + eased_t * (desiredZoom['zoomWidth']['width'] - initialZoomValue['initialZoomWidth']), 2)
interpolatedHeight = round(initialZoomValue['initialZoomHeight'] + eased_t * (desiredZoom['zoomHeight'] - initialZoomValue['initialZoomHeight']), 2)
interpolatedX = round(initialZoomValue['initialZoomX'] + eased_t * (desiredZoom['zoomX'] - initialZoomValue['initialZoomX']), 2)
interpolatedY = round(initialZoomValue['initialZoomY'] + eased_t * (desiredZoom['zoomY'] - initialZoomValue['initialZoomY']), 2)
return {'interpolatedWidth': int(interpolatedWidth), 'interpolatedHeight': int(interpolatedHeight), 'interpolatedX': int(interpolatedX), 'interpolatedY': int(interpolatedY)}
for i, frame in enumerate(generate_frame()):
interpolatedValues = zoomInInterpolation(initialZoomValue, desiredValues, 1, 60, i)
crop = frame[interpolatedValues['interpolatedY']:(interpolatedValues['interpolatedHeight'] + interpolatedValues['interpolatedY']), interpolatedValues['interpolatedX']:(interpolatedValues['interpolatedWidth'] + interpolatedValues['interpolatedX'])]
zoomedFrame = cv2.resize(crop,(1920, 1080), interpolation = cv2.INTER_CUBIC)
# Release the video capture and close windows
<code>import cv2
video_path = 'inputTest.mp4'
cap = cv2.VideoCapture(video_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (1920, 1080))
initialZoomValue={
'initialZoomWidth': 1920,
'initialZoomHeight': 1080,
'initialZoomX': 0,
'initialZoomY': 0
}
desiredValues = {
'zoomWidth': 1672,
'zoomHeight': 941,
'zoomX': 200,
'zoomY': 0
}
def ease_out_quart(t):
return 1 - (1 - t) ** 4
async def zoomInInterpolation(initialZoomValue, desiredZoom, start, end, index):
t = (index - start) / (end - start)
eased_t = ease_out_quart(t)
interpolatedWidth = round(initialZoomValue['initialZoomWidth'] + eased_t * (desiredZoom['zoomWidth']['width'] - initialZoomValue['initialZoomWidth']), 2)
interpolatedHeight = round(initialZoomValue['initialZoomHeight'] + eased_t * (desiredZoom['zoomHeight'] - initialZoomValue['initialZoomHeight']), 2)
interpolatedX = round(initialZoomValue['initialZoomX'] + eased_t * (desiredZoom['zoomX'] - initialZoomValue['initialZoomX']), 2)
interpolatedY = round(initialZoomValue['initialZoomY'] + eased_t * (desiredZoom['zoomY'] - initialZoomValue['initialZoomY']), 2)
return {'interpolatedWidth': int(interpolatedWidth), 'interpolatedHeight': int(interpolatedHeight), 'interpolatedX': int(interpolatedX), 'interpolatedY': int(interpolatedY)}
def generate_frame():
while cap.isOpened():
code, frame = cap.read()
if code:
yield frame
else:
print("bailsdfing")
break
for i, frame in enumerate(generate_frame()):
if i >= 1 and i <= 60:
interpolatedValues = zoomInInterpolation(initialZoomValue, desiredValues, 1, 60, i)
crop = frame[interpolatedValues['interpolatedY']:(interpolatedValues['interpolatedHeight'] + interpolatedValues['interpolatedY']), interpolatedValues['interpolatedX']:(interpolatedValues['interpolatedWidth'] + interpolatedValues['interpolatedX'])]
zoomedFrame = cv2.resize(crop,(1920, 1080), interpolation = cv2.INTER_CUBIC)
out.write(zoomedFrame)
# Release the video capture and close windows
cap.release()
cv2.destroyAllWindows()
</code>
import cv2
video_path = 'inputTest.mp4'
cap = cv2.VideoCapture(video_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (1920, 1080))
initialZoomValue={
'initialZoomWidth': 1920,
'initialZoomHeight': 1080,
'initialZoomX': 0,
'initialZoomY': 0
}
desiredValues = {
'zoomWidth': 1672,
'zoomHeight': 941,
'zoomX': 200,
'zoomY': 0
}
def ease_out_quart(t):
return 1 - (1 - t) ** 4
async def zoomInInterpolation(initialZoomValue, desiredZoom, start, end, index):
t = (index - start) / (end - start)
eased_t = ease_out_quart(t)
interpolatedWidth = round(initialZoomValue['initialZoomWidth'] + eased_t * (desiredZoom['zoomWidth']['width'] - initialZoomValue['initialZoomWidth']), 2)
interpolatedHeight = round(initialZoomValue['initialZoomHeight'] + eased_t * (desiredZoom['zoomHeight'] - initialZoomValue['initialZoomHeight']), 2)
interpolatedX = round(initialZoomValue['initialZoomX'] + eased_t * (desiredZoom['zoomX'] - initialZoomValue['initialZoomX']), 2)
interpolatedY = round(initialZoomValue['initialZoomY'] + eased_t * (desiredZoom['zoomY'] - initialZoomValue['initialZoomY']), 2)
return {'interpolatedWidth': int(interpolatedWidth), 'interpolatedHeight': int(interpolatedHeight), 'interpolatedX': int(interpolatedX), 'interpolatedY': int(interpolatedY)}
def generate_frame():
while cap.isOpened():
code, frame = cap.read()
if code:
yield frame
else:
print("bailsdfing")
break
for i, frame in enumerate(generate_frame()):
if i >= 1 and i <= 60:
interpolatedValues = zoomInInterpolation(initialZoomValue, desiredValues, 1, 60, i)
crop = frame[interpolatedValues['interpolatedY']:(interpolatedValues['interpolatedHeight'] + interpolatedValues['interpolatedY']), interpolatedValues['interpolatedX']:(interpolatedValues['interpolatedWidth'] + interpolatedValues['interpolatedX'])]
zoomedFrame = cv2.resize(crop,(1920, 1080), interpolation = cv2.INTER_CUBIC)
out.write(zoomedFrame)
# Release the video capture and close windows
cap.release()
cv2.destroyAllWindows()
But the final video I get is shaking :-
Final Video
I want the video to be perfectly zoom in and out, don’t want to any shakiness