File size: 3,900 Bytes
e0336bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import os
import numpy as np
from PIL import Image
import ffmpeg
import argparse

def add_noise(image: np.ndarray, noise_level: float) -> np.ndarray:
    """
    Add Gaussian noise to an image with increasing intensity.
    
    Args:
        image: Input image as numpy array (0-255)
        noise_level: Amount of noise to add (0-1)
    """
    # Convert to float for calculations
    img_float = image.astype(float)
    
    # Generate noise
    noise = np.random.normal(0, 255 * noise_level, image.shape)
    
    # Add noise to image
    noisy_image = img_float + noise
    
    # Clip values to valid range
    noisy_image = np.clip(noisy_image, 0, 255)
    
    return noisy_image.astype(np.uint8)

def create_noise_sequence(input_image_path: str, output_folder: str, num_frames: int = 201):
    """
    Create a sequence of increasingly noisy images.
    
    Args:
        input_image_path: Path to the input image
        output_folder: Folder to save the sequence
        num_frames: Number of frames to generate
    """
    # Create output folder if it doesn't exist
    os.makedirs(output_folder, exist_ok=True)
    
    # Load the image
    image = Image.open(input_image_path)
    image_array = np.array(image)
    
    # Calculate noise levels
    # First 5 frames are clean, then noise increases to 0.25
    noise_levels = np.zeros(num_frames)
    if num_frames > 5:
        noise_levels[5:] = np.linspace(0, 0.50, num_frames - 5)
    
    # Generate and save frames
    for i, noise_level in enumerate(noise_levels):
        # First 5 frames are the original image
        if i < 5:
            noisy_image = image_array
        else:
            noisy_image = add_noise(image_array, noise_level)
            
        # Save frame
        output_path = os.path.join(output_folder, f"frame_{i:03d}.png")
        Image.fromarray(noisy_image).save(output_path)
        
        # Print progress
        if (i + 1) % 20 == 0:
            print(f"Generated {i + 1}/{num_frames} frames")

def create_video(image_folder: str, output_path: str, fps: int = 24):
    """
    Create a video from a sequence of images using ffmpeg command line.
    
    Args:
        image_folder: Folder containing the image sequence
        output_path: Path for the output video
        fps: Frames per second for the video
    """
    input_pattern = os.path.join(image_folder, 'frame_%03d.png')
    
    # Construct ffmpeg command
    cmd = [
        'ffmpeg',
        '-y',  # Overwrite output file if it exists
        '-framerate', str(fps),
        '-i', input_pattern,
        '-c:v', 'libx264',
        '-pix_fmt', 'yuv420p',
        '-preset', 'medium',
        '-crf', '23',
        output_path
    ]
    
    # Run ffmpeg command
    import subprocess
    try:
        subprocess.run(cmd, check=True, capture_output=True)
    except subprocess.CalledProcessError as e:
        print(f"Error creating video: {e.stderr.decode()}")
        raise

def main():
    parser = argparse.ArgumentParser(description="Generate a sequence of increasingly noisy images and create a video")
    parser.add_argument("input_image", help="Path to input image")
    parser.add_argument("--output_folder", default="noise_sequence", help="Output folder for image sequence")
    parser.add_argument("--output_video", default="noise_sequence.mp4", help="Output video path")
    parser.add_argument("--fps", type=int, default=24, help="Frames per second for the video")
    parser.add_argument("--frames", type=int, default=201, help="Number of frames to generate")
    
    args = parser.parse_args()
    
    print("Generating noise sequence...")
    create_noise_sequence(args.input_image, args.output_folder, args.frames)
    
    print("Creating video...")
    create_video(args.output_folder, args.output_video, args.fps)
    
    print(f"Video saved to {args.output_video}")

if __name__ == "__main__":
    main()