Я нашел способ сделать это, который не очень элегантен, но он работает для меня, поэтому я хотел поделиться им.
Сначала я исказил видео на основе кода с learnopencv.com :
# source learnopencv.com
import numpy as np
import cv2
from tqdm import tqdm
def fixBorder(frame):
s = frame.shape
# Scale the image 4% without moving the center
T = cv2.getRotationMatrix2D((s[1] / 2, s[0] / 2), 0, 1.04)
frame = cv2.warpAffine(frame, T, (s[1], s[0]))
return frame
def straighten_vid(input_name, output_name, d_dx=0, d_dy=0, d_da=0):
d_da *= np.pi / 180.
# Read input video
cp = cv2.VideoCapture(input_name)
# To get number of frames
n_frames = int(cp.get(cv2.CAP_PROP_FRAME_COUNT))
# To check the number of frames in the video
width = int(cp.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cp.get(cv2.CAP_PROP_FRAME_HEIGHT))
# get the number of frames per second
fps = cp.get(cv2.CAP_PROP_FPS)
# Try doing 2*width
out = cv2.VideoWriter(output_name, 0x7634706d, fps, (width, height))
transforms_smooth = np.zeros((n_frames - 1, 3), np.float32)
for i in tqdm(range(n_frames - 2)):
transforms_smooth[i] = [d_dx, d_dy, d_da]
# Reset stream to first frame
cp.set(cv2.CAP_PROP_POS_FRAMES, 0)
# Write n_frames-1 transformed frames
for i in range(n_frames - 2):
# Read next frame
success, frame = cp.read()
if not success:
break
# Extract transformations from the new transformation array
dx = transforms_smooth[i, 0]
dy = transforms_smooth[i, 1]
da = transforms_smooth[i, 2]
# Reconstruct transformation matrix accordingly to new values
m = np.zeros((2, 3), np.float32)
m[0, 0] = np.cos(da)
m[0, 1] = -np.sin(da)
m[1, 0] = np.sin(da)
m[1, 1] = np.cos(da)
m[0, 2] = dx
m[1, 2] = dy
# Apply affine wrapping to the given frame
frame_stabilized = cv2.warpAffine(frame, m, (width, height))
# Fix border artifacts
frame_stabilized = fixBorder(frame_stabilized)
# Write the frame to the file
frame_out = frame_stabilized #cv2.hconcat([frame, frame_stabilized])
# If the image is too big, resize it.
if (frame_out.shape[1] > 1920):
frame_out = cv2.resize(frame_out, (frame_out.shape[1] // 2, frame_out.shape[0] // 2))
# cv2.imshow("Before and After", frame_out)
# cv2.waitKey(10)
out.write(frame_out)
# Release video
cp.release()
out.release()
# Close windows
cv2.destroyAllWindows()
d_da - это угол поворота, а d_dx и d_dy используются для центрирования видео. Тем не менее, это оставляет файл без звуков. Чтобы добавить это обратно, я делаю это:
import moviepy.editor as mpe
input_folder = "my_folder\\my_folder\\"
file_name = "my_file_name.MOV"
input_file = input_folder + file_name
output_file = input_folder + file_name.replace(".MOV", "_straightened.MOV")
output_file_final = input_folder + file_name.replace(".MOV", "_straightened_with_sound.mp4")
straighten_vid(input_file, output_file, 0, -70, 0.1)
my_clip = mpe.VideoFileClip(output_file)
audio_background = mpe.VideoFileClip(input_file).audio
final_clip = my_clip.set_audio(audio_background)
final_clip.write_videofile(output_file_final)