Created
April 22, 2025 05:58
-
-
Save me-suzy/e86bd47aa730cb70fd85386cec026b55 to your computer and use it in GitHub Desktop.
Efect Flaire 2.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import numpy as np | |
from moviepy.editor import ImageClip, CompositeVideoClip, vfx | |
from PIL import Image | |
import cv2 | |
# Calea imaginii | |
IMAGE_PATH = r"d:\family-hugging.jpg" | |
OUTPUT_PATH = r"d:\family-hugging-animation.mp4" | |
# Durata animației | |
DURATION = 10 # 10 secunde | |
def apply_ken_burns_effect(clip, duration, zoom_factor=1.2): | |
"""Aplică efectul Ken Burns: zoom și panoramare simulată""" | |
print("Aplic efect Ken Burns...") | |
width, height = clip.size | |
original_w, original_h = clip.size | |
def make_frame(t): | |
# Zoom progresiv | |
scale = 1 + (zoom_factor - 1) * (t / duration) | |
new_w, new_h = int(original_w * scale), int(original_h * scale) | |
# Calculăm poziția pentru panoramare (stânga-dreapta) | |
max_shift = (new_w - original_w) / 2 | |
x_shift = max_shift * np.sin((t / duration) * 2 * np.pi) # Mișcare sinusoidală | |
x_center = (new_w - original_w) / 2 - x_shift | |
y_center = (new_h - original_h) / 2 | |
# Redimensionăm și decupăm imaginea pentru a simula zoom și panoramare | |
resized = clip.resize((new_w, new_h)) | |
cropped = resized.crop( | |
x_center=x_center, | |
y_center=y_center, | |
width=original_w, | |
height=original_h | |
) | |
return cropped.get_frame(t) | |
# Creăm un clip nou cu cadrele generate | |
return clip.set_duration(duration).set_make_frame(make_frame) | |
def create_light_flare_effect(width, height, duration): | |
"""Creează un efect de lumină care se mișcă peste imagine""" | |
print("Creez efect de lumină...") | |
def flare_frame(t): | |
frame = np.zeros((height, width, 3), dtype=np.uint8) | |
flare_center_x = int(width * (t / duration)) | |
flare_center_y = height // 2 + int(100 * np.sin((t * 2 * np.pi) / duration)) | |
for y in range(height): | |
for x in range(width): | |
distance = np.sqrt((x - flare_center_x)**2 + (y - flare_center_y)**2) | |
if distance < 150: | |
intensity = 255 * (1 - distance / 150) | |
frame[y, x] = [int(intensity), int(intensity), 100] | |
return frame | |
flare_clip = ImageClip(flare_frame(0), duration=duration) | |
flare_clip = flare_clip.set_make_frame(lambda t: flare_frame(t)) | |
return flare_clip.set_opacity(0.3) | |
def create_particles_effect(width, height, duration, num_particles=50): | |
"""Creează particule animate (scântei sau petale)""" | |
print("Creez efect de particule...") | |
particles = [] | |
for _ in range(num_particles): | |
x = np.random.randint(0, width) | |
y = np.random.randint(0, height) | |
particle_duration = np.random.uniform(2, duration) | |
speed = np.random.uniform(30, 70) | |
# Captăm valorile în closure | |
x_start, y_start = x, y | |
p_duration, p_speed = particle_duration, speed | |
def make_particle_frame(t, x=x_start, y=y_start, | |
particle_duration=p_duration, speed=p_speed): | |
frame = np.zeros((height, width, 3), dtype=np.uint8) | |
if t < particle_duration: | |
x_pos = x + 50 * np.sin((t * 2 * np.pi) / particle_duration) | |
y_pos = y - t * speed | |
if 0 <= y_pos < height and 0 <= x_pos < width: | |
cv2.circle(frame, (int(x_pos), int(y_pos)), 2, (255, 255, 200), -1) | |
return frame | |
particle = ImageClip(make_particle_frame(0), duration=duration) | |
particle = particle.set_make_frame(lambda t: make_particle_frame(t)) | |
particles.append(particle.set_opacity(0.7)) | |
return particles | |
def create_color_shift_effect(clip, duration): | |
"""Aplică o tranziție subtilă de luminozitate""" | |
print("Aplic efect de tranziție de luminozitate...") | |
def make_frame(t): | |
# Obținem cadrul curent | |
frame = clip.get_frame(t) | |
# Calculăm factorul de luminozitate | |
factor = 0.8 + 0.2 * np.sin((t / duration) * 2 * np.pi) # Variază între 0.8 și 1.0 | |
# Aplicăm factorul direct și asigurăm că valorile rămân între 0-255 | |
return np.clip(frame * factor, 0, 255).astype('uint8') | |
# Creăm un clip nou cu funcția de transformare | |
return clip.fl_image(lambda img: make_frame(clip.to_seconds(img))) | |
def create_color_tone_effect(clip, duration): | |
"""Aplică o tranziție de tonuri de culoare (cald-rece)""" | |
print("Aplic efect de tranziție de tonuri de culoare...") | |
def tone_transform(get_frame, t): | |
frame = get_frame(t) | |
factor = np.sin((t / duration) * 2 * np.pi) | |
# Ajustăm canalele RGB pentru a simula tranziția cald-rece | |
r_factor = 1 + 0.2 * factor # Accentuăm roșul pentru tonuri calde | |
b_factor = 1 - 0.2 * factor # Accentuăm albastrul pentru tonuri reci | |
new_frame = frame.copy() | |
new_frame[:, :, 0] = np.clip(frame[:, :, 0] * r_factor, 0, 255) # Canalul R | |
new_frame[:, :, 2] = np.clip(frame[:, :, 2] * b_factor, 0, 255) # Canalul B | |
return new_frame | |
return clip.fl(tone_transform) | |
def main(): | |
print(f"Încarc imaginea: {IMAGE_PATH}") | |
try: | |
image = Image.open(IMAGE_PATH) | |
width, height = image.size | |
print(f"Dimensiune imagine: {width}x{height}") | |
base_clip = ImageClip(np.array(image), duration=DURATION) | |
print("Imaginea a fost convertită în clip video") | |
# Aplicăm efectul Ken Burns | |
ken_burns_clip = apply_ken_burns_effect(base_clip, DURATION) | |
# Creăm efectul de lumină | |
flare_clip = create_light_flare_effect(width, height, DURATION) | |
# Creăm particulele | |
particle_clips = create_particles_effect(width, height, DURATION) | |
# Aplicăm efectul de luminozitate | |
enhanced_clip = create_color_shift_effect(ken_burns_clip, DURATION) | |
# Aplicăm efectul de tonuri de culoare | |
final_base_clip = create_color_tone_effect(enhanced_clip, DURATION) | |
print("Combin efectele...") | |
all_clips = [final_base_clip, flare_clip] + particle_clips | |
final_video = CompositeVideoClip(all_clips) | |
print(f"Salvez animația: {OUTPUT_PATH}") | |
final_video.write_videofile( | |
OUTPUT_PATH, | |
fps=24, | |
codec='libx264', | |
audio_codec='aac', | |
bitrate="2000k", | |
ffmpeg_params=["-crf", "23"], | |
threads=4 | |
) | |
print("\n✅ Animația a fost creată cu succes!") | |
except Exception as e: | |
print(f"❌ Eroare: {str(e)}") | |
import traceback | |
traceback.print_exc() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment