viewify-backend / app.py
fkmod000's picture
Update app.py
7418282 verified
import gradio as gr
import cv2
import numpy as np
from PIL import Image
import tempfile
import os
class VideoInpaintingApp:
def __init__(self):
self.current_video = None
self.current_frame = None
self.fps = 30
self.total_frames = 0
def load_video(self, video_path):
"""Charge la vidéo et retourne des informations"""
if video_path is None:
return None, "Aucune vidéo chargée", 0, 0, 0
cap = cv2.VideoCapture(video_path)
self.fps = int(cap.get(cv2.CAP_PROP_FPS))
self.total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = self.total_frames / self.fps if self.fps > 0 else 0
cap.release()
self.current_video = video_path
info = f"✅ Vidéo chargée: {self.total_frames} frames, {self.fps} FPS, {duration:.2f}s"
max_frame = max(0, self.total_frames - 1)
return video_path, info, 0, max_frame, max_frame
def get_frame(self, video_path, frame_number):
"""Récupère une frame spécifique de la vidéo"""
if video_path is None:
return None
try:
cap = cv2.VideoCapture(video_path)
cap.set(cv2.CAP_PROP_POS_FRAMES, int(frame_number))
ret, frame = cap.read()
cap.release()
if ret:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.current_frame = frame_rgb
return Image.fromarray(frame_rgb)
except Exception as e:
print(f"Erreur lors de la lecture de la frame: {e}")
return None
def apply_inpainting(self, video_path, start_frame, end_frame, mask_image, progress=gr.Progress()):
"""Applique l'inpainting sur la plage de frames sélectionnée"""
if video_path is None:
return None, "❌ Veuillez charger une vidéo"
if mask_image is None:
return None, "❌ Veuillez dessiner un masque sur la zone à supprimer"
try:
progress(0, desc="Préparation...")
# Ouvrir la vidéo
cap = cv2.VideoCapture(video_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# Créer un fichier temporaire pour la sortie
output_path = tempfile.mktemp(suffix='.mp4')
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# Extraire le masque
if isinstance(mask_image, dict) and 'mask' in mask_image:
mask = np.array(mask_image['mask'])
else:
mask = np.array(mask_image)
# Redimensionner le masque si nécessaire
if mask.shape[:2] != (height, width):
mask = cv2.resize(mask, (width, height))
# Convertir en masque binaire
if len(mask.shape) == 3:
mask = cv2.cvtColor(mask, cv2.COLOR_RGB2GRAY)
_, mask_binary = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)
# Traiter chaque frame
for frame_idx in range(total_frames):
ret, frame = cap.read()
if not ret:
break
# Appliquer l'inpainting seulement dans la plage sélectionnée
if start_frame <= frame_idx <= end_frame:
inpainted = cv2.inpaint(frame, mask_binary, 3, cv2.INPAINT_TELEA)
out.write(inpainted)
else:
out.write(frame)
# Mise à jour de la progression
progress((frame_idx + 1) / total_frames, desc=f"Frame {frame_idx + 1}/{total_frames}")
cap.release()
out.release()
return output_path, "✅ Inpainting terminé avec succès!"
except Exception as e:
return None, f"❌ Erreur: {str(e)}"
# Créer l'instance de l'application
app = VideoInpaintingApp()
# Interface Gradio
with gr.Blocks(title="Inpainting Vidéo IA", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🎬 Inpainting Vidéo avec IA
### Supprimez des objets indésirables de vos vidéos
**Instructions:**
1. Chargez votre vidéo
2. Sélectionnez la plage de frames avec les curseurs
3. Dessinez sur la zone à supprimer (pinceau blanc)
4. Cliquez sur "Supprimer l'objet sélectionné"
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 📁 1. Charger la vidéo")
video_input = gr.Video(label="Votre vidéo")
video_info = gr.Textbox(label="Informations", interactive=False)
gr.Markdown("### ⏱️ 2. Sélectionner la plage")
start_frame = gr.Slider(
minimum=0,
maximum=100,
value=0,
step=1,
label="Frame de début"
)
end_frame = gr.Slider(
minimum=0,
maximum=100,
value=100,
step=1,
label="Frame de fin"
)
current_frame_slider = gr.Slider(
minimum=0,
maximum=100,
value=0,
step=1,
label="Prévisualiser la frame"
)
with gr.Column(scale=2):
gr.Markdown("### 🎨 3. Dessiner la zone à supprimer")
frame_preview = gr.Image(
label="Dessinez sur la zone à supprimer",
type="pil",
tool="sketch",
brush=gr.Brush(colors=["#FFFFFF"], default_size=20)
)
gr.Markdown("### ⚙️ 4. Lancer l'inpainting")
process_btn = gr.Button("🚀 Supprimer l'objet sélectionné", variant="primary", size="lg")
status_text = gr.Textbox(label="Statut", interactive=False)
output_video = gr.Video(label="Vidéo traitée")
# Événements
video_input.change(
fn=app.load_video,
inputs=[video_input],
outputs=[video_input, video_info, start_frame, end_frame, current_frame_slider]
)
current_frame_slider.change(
fn=app.get_frame,
inputs=[video_input, current_frame_slider],
outputs=[frame_preview]
)
process_btn.click(
fn=app.apply_inpainting,
inputs=[video_input, start_frame, end_frame, frame_preview],
outputs=[output_video, status_text]
)
demo.launch()