Skip to content

Instantly share code, notes, and snippets.

@me-suzy
Last active April 22, 2025 14:36
Show Gist options
  • Save me-suzy/a93ba4acddacd9a4cc5227fde220ac1c to your computer and use it in GitHub Desktop.
Save me-suzy/a93ba4acddacd9a4cc5227fde220ac1c to your computer and use it in GitHub Desktop.
cod reparat eroare.txt
#!/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)
def make_particle_frame(t):
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 * 50
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 brightness_shift(t):
# Ajustăm luminozitatea cu o variație sinusoidală
factor = 0.8 + 0.2 * np.sin((t / duration) * 2 * np.pi) # Variază între 0.8 și 1.0
return factor
# Aplicăm efectul de luminozitate
return clip.fx(vfx.colorx, brightness_shift)
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 make_frame(t):
frame = clip.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.set_make_frame(make_frame)
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")
ken_burns_clip = apply_ken_burns_effect(base_clip, DURATION)
flare_clip = create_light_flare_effect(width, height, DURATION)
particle_clips = create_particles_effect(width, height, DURATION)
# Aplicăm mai întâi efectul de luminozitate
brightness_clip = create_color_shift_effect(ken_burns_clip, DURATION)
# Aplicăm apoi efectul de tranziție de tonuri de culoare
final_clip = create_color_tone_effect(brightness_clip, DURATION)
print("Combin efectele...")
all_clips = [final_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"]
)
print("\n✅ Animația a fost creată cu succes!")
final_video.close()
except Exception as e:
print(f"❌ Eroare: {str(e)}")
if __name__ == "__main__":
main()
*** Remote Interpreter Reinitialized ***
Încarc imaginea: d:\family-hugging.jpg
Dimensiune imagine: 1277x822
Imaginea a fost convertită în clip video
Aplic efect Ken Burns...
Creez efect de lumină...
Creez efect de particule...
Aplic efect de tranziție de luminozitate...
❌ Eroare: unsupported operand type(s) for *: 'function' and 'int'
>>>
Eroarea
❌ Eroare: unsupported operand type(s) for *: 'function' and 'int'
vine din faptul că vfx.colorx aşteaptă un factor numeric, nu o funcție. Când îi dai brightness_shift (o funcție), intern încearcă să înmulțească funcția cu un int și pică.
Cum o repari
În loc să folosești direct clip.fx(vfx.colorx, brightness_shift), trebuie să aplici dinamic luminozitatea cadru cu cadru, cu .fl sau .fl_image. Iată o variantă cu .fl:
def create_color_shift_effect(clip, duration):
"""Aplică un shift de luminozitate cadru cu cadru."""
def fl_brightness(get_frame, t):
frame = get_frame(t)
# calculăm factorul la momentul t
factor = 0.8 + 0.2 * np.sin((t / duration) * 2 * np.pi)
# multiplicăm frame-ul cu factorul
return np.clip(frame * factor, 0, 255).astype('uint8')
# .fl primește un callable (get_frame, t) -> frame nou
return clip.fl(fl_brightness, apply_to=['mask', 'video'])
Ce se întâmplă aici
.fl(fl_brightness) – primește ca argument o funcție care, pentru fiecare timp t, primește funcția get_frame(t) și returnează imaginea modificată.
În interiorul lui fl_brightness calculăm factor (sinusoidal) și aplicăm direct pe matricea de pixeli:
new_frame = frame * factor
Astfel, codul nu mai încearcă să înmulțească o funcție cu un int, ci efectuează pe rând operația np.ndarray * float.
Integrare în main
Înlocuiește definiția create_color_shift_effect din script cu cea de mai sus, apoi:
# Aplicăm mai întâi efectul de luminozitate
brightness_clip = create_color_shift_effect(ken_burns_clip, DURATION)
# Aplicăm apoi efectul de tonare
final_clip = create_color_tone_effect(brightness_clip, DURATION)
Cu această abordare, animația ta nu va mai genera eroarea și vei obține un shift subtil și fluid de luminozitate pe parcursul celor 10 secunde.
Văd că ai un script Python care încearcă să creeze o animație din imaginea ta "family-hugging.jpg", dar întâmpini o eroare. Problema este în funcția create_color_shift_effect unde încerci să aplici un efect de luminozitate variabilă.
Eroarea "unsupported operand type(s) for *: 'function' and 'int'" apare deoarece funcția brightness_shift este utilizată incorect cu vfx.colorx. În implementarea actuală, MoviePy se așteaptă ca vfx.colorx să primească un factor constant, nu o funcție.
Iată cum poți remedia codul:
pythondef 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
return frame * factor
# Returnăm un nou clip cu frame-urile procesate
return clip.fl(lambda gf, t: make_frame(t))
Această modificare înlocuiește utilizarea vfx.colorx cu o abordare mai directă, folosind metoda fl (frame_transform) a MoviePy pentru a aplica transformarea la fiecare cadru.
Dacă această soluție nu funcționează, poți încerca și această alternativă mai simplă:
pythondef 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):
frame = clip.get_frame(t)
factor = 0.8 + 0.2 * np.sin((t / duration) * 2 * np.pi)
return np.clip(frame * factor, 0, 255).astype('uint8')
return clip.fl_image(lambda img: make_frame(clip.to_seconds(img)))
Asigură-te că ai instalate toate dependențele necesare, inclusiv MoviePy într-o versiune recentă:
pip install moviepy numpy pillow opencv-python
După această modificare, scriptul tău ar trebui să funcționeze corect și să genereze o animație frumoasă cu efecte Ken Burns, particule și tranziții de lumină.
-------Codul corect------
#!/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 și a fișierului de ieșire
IMAGE_PATH = r"d:\family-hugging.jpg"
OUTPUT_PATH = r"d:\family-hugging-animation.mp4"
# Durata animației (secunde)
DURATION = 10
def read_file_with_fallback_encoding(file_path):
"""Încearcă mai multe encodări pentru a citi un fișier text."""
encodings = ['utf-8', 'latin1', 'cp1252', 'iso-8859-1']
for encoding in encodings:
try:
with open(file_path, 'r', encoding=encoding):
return open(file_path, 'r', encoding=encoding).read()
except UnicodeDecodeError:
continue
print(f"Nu s-a putut citi fișierul {file_path}")
return None
def replace_special_chars(val):
"""Înlocuiește dash-uri tipografice cu minus simplu."""
return val.replace('–', '-').replace('—', '-')
def normalize_value(val):
"""Normalizează un șir: spații non-break, dash-uri speciale, strip+lower."""
if val is None:
return None
val = val.replace('\xa0', ' ')
val = replace_special_chars(val)
return val.strip().lower()
def apply_ken_burns_effect(clip, duration, zoom_factor=1.2):
"""Aplică efectul Ken Burns: zoom și panoramare sinusoidală."""
original_w, original_h = clip.size
def make_frame(t):
# calcul zoom
scale = 1 + (zoom_factor - 1) * (t / duration)
new_w, new_h = int(original_w * scale), int(original_h * scale)
# panoramare pe orizontală
max_shift = (new_w - original_w) / 2
x_shift = max_shift * np.sin((t / duration) * 2 * np.pi)
x_center = (new_w - original_w) / 2 - x_shift
y_center = (new_h - original_h) / 2
resized = clip.resize((new_w, new_h))
return resized.crop(
x_center=x_center,
y_center=y_center,
width=original_w,
height=original_h
).get_frame(t)
return clip.set_duration(duration).set_make_frame(make_frame)
def create_light_flare_effect(width, height, duration):
"""Creează un flare lumină care se mișcă și oscilează pe verticală."""
def flare_frame(t):
frame = np.zeros((height, width, 3), dtype=np.uint8)
fx = int(width * (t / duration))
fy = height // 2 + int(100 * np.sin((t * 2 * np.pi) / duration))
for y in range(height):
for x in range(width):
d = np.hypot(x - fx, y - fy)
if d < 150:
intensity = 255 * (1 - d / 150)
frame[y, x] = [int(intensity), int(intensity), 100]
return frame
clip = ImageClip(flare_frame(0), duration=duration)
clip = clip.set_make_frame(lambda t: flare_frame(t))
return clip.set_opacity(0.3)
def create_particles_effect(width, height, duration, num_particles=50):
"""Creează particule animate (scântei/petale) care urcă și oscilează."""
particles = []
for _ in range(num_particles):
x0 = np.random.randint(0, width)
y0 = np.random.randint(0, height)
pd = np.random.uniform(2, duration)
def make_particle_frame(t, x0=x0, y0=y0, pd=pd):
frame = np.zeros((height, width, 3), dtype=np.uint8)
if t < pd:
x = x0 + 50 * np.sin((t * 2 * np.pi) / pd)
y = y0 - t * 50
if 0 <= x < width and 0 <= y < height:
cv2.circle(frame, (int(x), int(y)), 2, (255, 255, 200), -1)
return frame
pclip = ImageClip(make_particle_frame(0), duration=duration)
pclip = pclip.set_make_frame(lambda t, f=make_particle_frame: f(t))
particles.append(pclip.set_opacity(0.7))
return particles
def create_color_shift_effect(clip, duration):
"""Aplică shift de luminozitate cadru cu cadru."""
def fl_brightness(get_frame, t):
frame = get_frame(t).astype(np.float32)
factor = 0.8 + 0.2 * np.sin((t / duration) * 2 * np.pi)
shifted = np.clip(frame * factor, 0, 255)
return shifted.astype('uint8')
return clip.fl(fl_brightness, apply_to=['video', 'mask'])
def create_color_tone_effect(clip, duration):
"""Aplică tranziție cald–rece pe tonurile de culoare."""
def make_frame(t):
frame = clip.get_frame(t).astype(np.float32)
f = np.sin((t / duration) * 2 * np.pi)
r_factor = 1 + 0.2 * f
b_factor = 1 - 0.2 * f
frame[:, :, 0] = np.clip(frame[:, :, 0] * r_factor, 0, 255)
frame[:, :, 2] = np.clip(frame[:, :, 2] * b_factor, 0, 255)
return frame.astype('uint8')
return clip.set_make_frame(make_frame)
def main():
print(f"Încarc imaginea: {IMAGE_PATH}")
image = Image.open(IMAGE_PATH)
width, height = image.size
print(f"Dimensiune imagine: {width}x{height}")
base = ImageClip(np.array(image), duration=DURATION)
print("Aplic efect Ken Burns...")
kb = apply_ken_burns_effect(base, DURATION)
print("Creez efect flare...")
flare = create_light_flare_effect(width, height, DURATION)
print("Creez particule...")
particles = create_particles_effect(width, height, DURATION)
print("Aplic efect shift de luminozitate...")
bright = create_color_shift_effect(kb, DURATION)
print("Aplic efect ton de culoare...")
toned = create_color_tone_effect(bright, DURATION)
print("Combin toate stratificările...")
clips = [toned, flare] + particles
final = CompositeVideoClip(clips)
print(f"Salvez animația în: {OUTPUT_PATH}")
final.write_videofile(
OUTPUT_PATH,
fps=24,
codec='libx264',
audio_codec='aac',
bitrate="2000k",
ffmpeg_params=["-crf", "23"]
)
final.close()
print("✅ Animația a fost creată cu succes!")
if __name__ == "__main__":
main()
Iată codul complet rescris, cu problema din funcția `create_color_shift_effect` rezolvată și câteva optimizări:
```python
#!/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()
```
Principalele modificări:
1. Am rezolvat problema din `create_color_shift_effect` prin utilizarea metodei `fl_image` pentru a aplica transformarea de luminozitate corect.
2. Am îmbunătățit funcția `create_color_tone_effect` pentru a utiliza metoda `fl` pentru transformarea cadrelor.
3. Am adăugat gestionarea mai robustă a erorilor cu afișarea stack trace-ului complet.
4. Am optimizat crearea particulelor pentru a evita problemele cu lambda și valorile închise în closure.
5. Am adăugat parametrul `threads=4` la scrierea videoclipului pentru a accelera procesul de export.
Acest cod ar trebui să funcționeze fără eroarea anterioară și să producă o animație frumoasă cu efectele dorite.
*** Remote Interpreter Reinitialized ***
Încarc imaginea: d:\family-hugging.jpg
Dimensiune imagine: 1277x822
Imaginea a fost convertită în clip video
Aplic efect Ken Burns...
Creez efect de lumină...
Creez efect de particule...
Aplic efect de tranziție de luminozitate...
❌ Eroare: 'ImageClip' object has no attribute 'to_seconds'
Traceback (most recent call last):
File "D:\module1.py", line 150, in main
enhanced_clip = create_color_shift_effect(ken_burns_clip, DURATION)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\module1.py", line 110, in create_color_shift_effect
return clip.fl_image(lambda img: make_frame(clip.to_seconds(img)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<decorator-gen-72>", line 2, in fl_image
File "C:\Users\necul\AppData\Local\Programs\Python\Python312\Lib\site-packages\moviepy\decorators.py", line 14, in outplace
f(newclip, *a, **k)
File "C:\Users\necul\AppData\Local\Programs\Python\Python312\Lib\site-packages\moviepy\video\VideoClip.py", line 936, in fl_image
arr = image_func(self.get_frame(0))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\module1.py", line 110, in <lambda>
return clip.fl_image(lambda img: make_frame(clip.to_seconds(img)))
^^^^^^^^^^^^^^^
AttributeError: 'ImageClip' object has no attribute 'to_seconds'
>>>
#!/usr/bin/env python3
import numpy as np
from moviepy.editor import VideoClip
from PIL import Image
import cv2
import time
# Calea imaginii
IMAGE_PATH = r"d:\family-hugging.jpg"
OUTPUT_PATH = r"d:\family-hugging-animation.mp4"
# Durata totală și pentru fiecare efect
TOTAL_DURATION = 20 # secunde totale
EFFECT_DURATION = 5 # durata fiecărui efect
def create_animation(image_array):
"""Creează un videoclip complet cu toate efectele aplicate secvențial"""
h, w = image_array.shape[:2]
print(f"Dimensiune imagine originală: {w}x{h}")
print(f"Shape array imagine: {image_array.shape}")
print(f"Tip date imagine: {image_array.dtype}")
print(f"Valori min/max imagine: {np.min(image_array)}/{np.max(image_array)}")
# Contorizam cadrele procesate pentru fiecare efect
effect1_frames = 0
effect2_frames = 0
effect3_frames = 0
effect4_frames = 0
def make_frame(t):
nonlocal effect1_frames, effect2_frames, effect3_frames, effect4_frames
# Pentru debugging, afișăm timpul curent la fiecare secundă
if t % 1 < 0.034: # Aproximativ un cadru la fiecare secundă (pentru 30fps)
print(f"Procesez cadru la timpul t={t:.2f}s")
# Determinăm ce efect trebuie aplicat în funcție de timestamp
if t < EFFECT_DURATION: # 0-5 secunde: zoom in
effect1_frames += 1
if effect1_frames % 30 == 0: # La fiecare ~secunda
print(f"Efect 1 (zoom): cadrul {effect1_frames}, t={t:.2f}")
# Zoom de la 1.0 la 1.3
zoom = 1.0 + (0.3 * t / EFFECT_DURATION)
# Redimensionăm și decupăm pentru efect de zoom
zoomed_h, zoomed_w = int(h * zoom), int(w * zoom)
zoomed = cv2.resize(image_array, (zoomed_w, zoomed_h), interpolation=cv2.INTER_CUBIC)
offset_x = int((zoomed_w - w) / 2)
offset_y = int((zoomed_h - h) / 2)
try:
result = zoomed[offset_y:offset_y + h, offset_x:offset_x + w]
if result.shape != (h, w, 3):
print(f"ATENȚIE: Formă incorectă rezultat efect 1: {result.shape}, ar trebui {(h, w, 3)}")
return result
except Exception as e:
print(f"EROARE în efect 1: {e}")
print(f"zoom={zoom}, zoomed_shape={zoomed.shape}, offset=({offset_x}, {offset_y})")
return image_array # Returnăm imaginea originală în caz de eroare
elif t < 2 * EFFECT_DURATION: # 5-10 secunde: panoramare stânga-dreapta
effect2_frames += 1
if effect2_frames % 30 == 0: # La fiecare ~secunda
print(f"Efect 2 (panoramare): cadrul {effect2_frames}, t={t:.2f}")
# Timpul relativ în cadrul acestui efect
rel_t = t - EFFECT_DURATION
# Zoom constant pentru panoramare
zoom = 1.2
# Redimensionăm imaginea
zoomed_h, zoomed_w = int(h * zoom), int(w * zoom)
print(f"Efect 2: zoomed_dim={zoomed_w}x{zoomed_h}, rel_t={rel_t:.2f}")
try:
zoomed = cv2.resize(image_array, (zoomed_w, zoomed_h), interpolation=cv2.INTER_CUBIC)
print(f"Efect 2: zoomed.shape={zoomed.shape}")
# Calculăm offset-ul pentru panoramare progresivă
progress = rel_t / EFFECT_DURATION
max_offset_x = zoomed_w - w
offset_x = int(max_offset_x * progress)
offset_y = int((zoomed_h - h) / 2)
# Ne asigurăm că rămânem în limitele imaginii
offset_x = max(0, min(offset_x, zoomed_w - w))
offset_y = max(0, min(offset_y, zoomed_h - h))
print(f"Efect 2: progress={progress:.2f}, offset=({offset_x}, {offset_y})")
result = zoomed[offset_y:offset_y + h, offset_x:offset_x + w]
print(f"Efect 2: result.shape={result.shape}")
if result.shape != (h, w, 3):
print(f"ATENȚIE: Formă incorectă rezultat efect 2: {result.shape}, ar trebui {(h, w, 3)}")
return result
except Exception as e:
print(f"EROARE în efect 2: {e}")
print(f"zoom={zoom}, zoomed_shape={zoomed_w}x{zoomed_h}, offset=({offset_x}, {offset_y})")
# Returnăm imaginea originală în caz de eroare
return image_array
elif t < 3 * EFFECT_DURATION: # 10-15 secunde: focalizare pe o față
effect3_frames += 1
if effect3_frames % 30 == 0: # La fiecare ~secunda
print(f"Efect 3 (focalizare): cadrul {effect3_frames}, t={t:.2f}")
# Timpul relativ în cadrul acestui efect
rel_t = t - (2 * EFFECT_DURATION)
# Definim poziția de focalizare (pe unul dintre copii)
focus_x, focus_y = 0.4, 0.4 # Ajustează coordonatele pentru a focaliza pe un copil
focus_pixel_x = int(w * focus_x)
focus_pixel_y = int(h * focus_y)
# Zoom progresiv
zoom_start = 1.1
zoom_end = 1.5
zoom = zoom_start + (zoom_end - zoom_start) * (rel_t / EFFECT_DURATION)
try:
# Redimensionăm imaginea
zoomed_h, zoomed_w = int(h * zoom), int(w * zoom)
zoomed = cv2.resize(image_array, (zoomed_w, zoomed_h), interpolation=cv2.INTER_CUBIC)
# Calculăm offset-ul pentru a focaliza pe punctul de interes
offset_x = int(focus_pixel_x * zoom) - (w // 2)
offset_y = int(focus_pixel_y * zoom) - (h // 2)
# Ne asigurăm că rămânem în limitele imaginii
offset_x = max(0, min(offset_x, zoomed_w - w))
offset_y = max(0, min(offset_y, zoomed_h - h))
result = zoomed[offset_y:offset_y + h, offset_x:offset_x + w]
if result.shape != (h, w, 3):
print(f"ATENȚIE: Formă incorectă rezultat efect 3: {result.shape}, ar trebui {(h, w, 3)}")
return result
except Exception as e:
print(f"EROARE în efect 3: {e}")
return image_array # Returnăm imaginea originală în caz de eroare
else: # 15-20 secunde: efect de pulsație și strălucire
effect4_frames += 1
if effect4_frames % 30 == 0: # La fiecare ~secunda
print(f"Efect 4 (pulsație): cadrul {effect4_frames}, t={t:.2f}")
# Timpul relativ în cadrul acestui efect
rel_t = t - (3 * EFFECT_DURATION)
try:
# Aplicăm un efect de pulsație și strălucire
frame = image_array.copy()
# Convertim la HSV pentru a manipula saturația și luminozitatea
hsv = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV).astype(float)
# Factori pentru pulsație
brightness_factor = 1.0 + 0.2 * np.sin(rel_t * np.pi)
saturation_factor = 1.0 + 0.3 * np.sin(rel_t * np.pi * 1.5)
# Aplicăm factorii
hsv[:, :, 1] = np.clip(hsv[:, :, 1] * saturation_factor, 0, 255)
hsv[:, :, 2] = np.clip(hsv[:, :, 2] * brightness_factor, 0, 255)
# Convertim înapoi la RGB
result = cv2.cvtColor(hsv.astype(np.uint8), cv2.COLOR_HSV2RGB)
# Adăugăm un efect de strălucire
blur = cv2.GaussianBlur(result, (21, 21), 0)
result = cv2.addWeighted(result, 1.0, blur, 0.2 * np.sin(rel_t * np.pi), 0)
if result.shape != (h, w, 3):
print(f"ATENȚIE: Formă incorectă rezultat efect 4: {result.shape}, ar trebui {(h, w, 3)}")
return result
except Exception as e:
print(f"EROARE în efect 4: {e}")
return image_array # Returnăm imaginea originală în caz de eroare
# Creăm un singur VideoClip cu toate efectele combinate
return VideoClip(make_frame, duration=TOTAL_DURATION)
def main():
print(f"Încarc imaginea: {IMAGE_PATH}")
start_time = time.time()
try:
# Deschidem imaginea folosind PIL și o convertim la numpy array
pil_img = Image.open(IMAGE_PATH)
img_array = np.array(pil_img)
print(f"Imagine încărcată: format={pil_img.format}, mode={pil_img.mode}")
print(f"Dimensiune imagine originală: {pil_img.width}x{pil_img.height}")
# Verificăm și convertim la RGB dacă e necesar
if len(img_array.shape) == 3 and img_array.shape[2] == 4: # Imagine cu canal alfa
print("Convertim imagine RGBA la RGB")
img_array = cv2.cvtColor(img_array, cv2.COLOR_RGBA2RGB)
elif len(img_array.shape) == 2: # Imagine grayscale
print("Convertim imagine grayscale la RGB")
img_array = cv2.cvtColor(img_array, cv2.COLOR_GRAY2RGB)
print(f"Array imagine după conversie: shape={img_array.shape}, dtype={img_array.dtype}")
# Creăm videoclipul cu toate efectele
print("Creez videoclipul cu toate efectele...")
final_clip = create_animation(img_array)
# Scriem videoclipul în fișier
print(f"Salvez animația: {OUTPUT_PATH}")
final_clip.write_videofile(
OUTPUT_PATH,
fps=30,
codec='libx264',
audio=False,
preset='medium',
bitrate="5000k"
)
elapsed_time = time.time() - start_time
print(f"\n✅ Animația a fost creată cu succes în {elapsed_time:.2f} secunde!")
except Exception as e:
print(f"❌ Eroare generală: {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