Spaces:
Paused
Paused
| 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() |