import cv2import osimport numpy as npdef images_to_video( image_folder, output_video, fps=5, target_size=(1920, 1080), fade_duration=0.5): """ 多张图片批量转MP4视频【增强版】 新增:统一分辨率、自动补黑边防变形、淡入淡出转场 :param image_folder: 图片文件夹路径 :param output_video: 输出视频路径 :param fps: 帧率 :param target_size: 目标分辨率 默认1080P :param fade_duration: 单张图片淡入淡出总时长(秒) """ img_suffix = ('.jpg', '.jpeg', '.png', '.bmp') img_list = [f for f in os.listdir(image_folder) if f.lower().endswith(img_suffix)] img_list.sort() if not img_list: print("❌ 文件夹内未找到任何图片!") return target_w, target_h = target_size fade_frame_num = int(fade_duration * fps / 2) fourcc = cv2.VideoWriter_fourcc(*'mp4v') video_writer = cv2.VideoWriter(output_video, fourcc, fps, (target_w, target_h)) def resize_and_pad(img): """统一尺寸,等比例缩放+补黑边,杜绝拉伸变形""" h, w = img.shape[:2] scale = min(target_w / w, target_h / h) new_w, new_h = int(w * scale), int(h * scale) img_resized = cv2.resize(img, (new_w, new_h)) # 计算居中填充黑边 top = (target_h - new_h) // 2 bottom = target_h - new_h - top left = (target_w - new_w) // 2 right = target_w - new_w - left return cv2.copyMakeBorder( img_resized, top, bottom, left, right, cv2.BORDER_CONSTANT, value=[0, 0, 0] ) def fade_transition(frame1, frame2, fade_frames): """生成两张图片之间的淡入淡出过渡帧""" frames = [] for i in range(fade_frames): alpha = i / fade_frames blend = cv2.addWeighted(frame1, 1 - alpha, frame2, alpha, 0) frames.append(blend) return frames frame_buffer = [] for idx, img_name in enumerate(img_list): img_path = os.path.join(image_folder, img_name) frame = cv2.imread(img_path) if frame is None: print(f"⚠️ 读取失败:{img_name}") continue # 统一尺寸 frame_pad = resize_and_pad(frame) frame_buffer.append(frame_pad) print(f"✅ 预处理完成:{img_name}") # 逐帧写入 + 首尾淡入淡出 + 图片间转场 total_img = len(frame_buffer) stay_frames = int(1.0 * fps) for i in range(total_img): current_frame = frame_buffer[i] # 开头淡入 if i == 0: for n in range(fade_frame_num): alpha = n / fade_frame_num blank = np.zeros_like(current_frame) fade_in = cv2.addWeighted(blank, 1 - alpha, current_frame, alpha, 0) video_writer.write(fade_in) # 主体停留帧 for _ in range(stay_frames): video_writer.write(current_frame) # 图片之间淡出转场(最后一张不淡出) if i != total_img - 1: next_frame = frame_buffer[i+1] trans_frames = fade_transition(current_frame, next_frame, fade_frame_num) for f in trans_frames: video_writer.write(f) # 结尾淡出 elif i == total_img - 1: for n in range(fade_frame_num, 0, -1): alpha = n / fade_frame_num blank = np.zeros_like(current_frame) fade_out = cv2.addWeighted(blank, 1 - alpha, current_frame, alpha, 0) video_writer.write(fade_out) video_writer.release() print(f"\n🎉 高清视频合成完成!保存路径:{output_video}")# ==================== 自定义配置区 ====================if __name__ == "__main__": IMAGE_FOLDER = "./images" OUTPUT_VIDEO = "./output.mp4" FPS = 8 RESOLUTION = (1920, 1080) # 可改为 (1280,720) 720P FADE_TIME = 0.6 # 转场时长 images_to_video( image_folder=IMAGE_FOLDER, output_video=OUTPUT_VIDEO, fps=FPS, target_size=RESOLUTION, fade_duration=FADE_TIME )