| import cv2 |
| import os |
| import re |
| import argparse |
| from pathlib import Path |
|
|
| def natural_sort_key(filename): |
| """提取文件名中的数字进行自然排序""" |
| numbers = re.findall(r'\d+', filename) |
| return [int(num) for num in numbers] if numbers else [0] |
|
|
| def create_video_from_images(input_folder, output_path="output_video.mp4", fps=30): |
| """ |
| 将文件夹中的图片按索引顺序合成视频 |
| |
| 参数: |
| - input_folder: 输入图片文件夹路径 |
| - output_path: 输出视频文件路径 |
| - fps: 视频帧率 |
| """ |
| |
| |
| image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif'} |
| |
| |
| image_files = [] |
| for file in os.listdir(input_folder): |
| if Path(file).suffix.lower() in image_extensions: |
| image_files.append(file) |
| |
| if not image_files: |
| print("未找到支持的图片文件!") |
| return False |
| |
| |
| image_files.sort(key=natural_sort_key) |
| print(image_files) |
| |
| print(f"找到 {len(image_files)} 张图片") |
| print(f"第一张图片: {image_files[0]}") |
| print(f"最后一张图片: {image_files[-1]}") |
| |
| |
| first_image_path = os.path.join(input_folder, image_files[0]) |
| first_image = cv2.imread(first_image_path) |
| |
| if first_image is None: |
| print(f"无法读取图片: {first_image_path}") |
| return False |
| |
| height, width, layers = first_image.shape |
| print(f"视频尺寸: {width}x{height}") |
| |
| |
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| video_writer = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) |
| |
| if not video_writer.isOpened(): |
| print("无法创建视频文件!") |
| return False |
| |
| |
| for i, image_file in enumerate(image_files): |
| image_path = os.path.join(input_folder, image_file) |
| image = cv2.imread(image_path) |
| |
| if image is None: |
| print(f"跳过无效图片: {image_file}") |
| continue |
| |
| |
| if image.shape[:2] != (height, width): |
| image = cv2.resize(image, (width, height)) |
| |
| video_writer.write(image) |
| |
| |
| if (i + 1) % 10 == 0 or i == len(image_files) - 1: |
| print(f"处理进度: {i + 1}/{len(image_files)}") |
| |
| |
| video_writer.release() |
| cv2.destroyAllWindows() |
| |
| print(f"视频生成完成: {output_path}") |
| print(f"视频参数: {width}x{height}, {fps}fps, {len(image_files)}帧") |
| return True |
|
|
| def main(): |
| parser = argparse.ArgumentParser(description='将图片序列合成为视频') |
| parser.add_argument('--input', '-i', default='.', help='输入图片文件夹路径 (默认: 当前目录)') |
| parser.add_argument('--output', '-o', default='output_video.mp4', help='输出视频文件路径 (默认: output_video.mp4)') |
| parser.add_argument('--fps', '-f', type=int, default=30, help='视频帧率 (默认: 30)') |
| |
| args = parser.parse_args() |
| |
| |
| if not os.path.exists(args.input): |
| print(f"错误: 输入文件夹不存在: {args.input}") |
| return |
| |
| print(f"输入文件夹: {args.input}") |
| print(f"输出文件: {args.output}") |
| print(f"帧率: {args.fps}") |
| print("=" * 50) |
| |
| |
| success = create_video_from_images(args.input, args.output, args.fps) |
| |
| if success: |
| print("视频生成成功!") |
| else: |
| print("视频生成失败!") |
|
|
| if __name__ == "__main__": |
| main() |