Spaces:
Sleeping
Sleeping
Upload ai_studio_code - 2025-08-18T134000.970.py
Browse files
ai_studio_code - 2025-08-18T134000.970.py
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import cv2
|
3 |
+
import numpy as np
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
+
import os
|
6 |
+
|
7 |
+
# Define um estilo de gráfico que fica bem no modo escuro do Gradio
|
8 |
+
plt.style.use('dark_background')
|
9 |
+
|
10 |
+
def analyze_videos(video_original_path, video_interpolado_path, progress=gr.Progress()):
|
11 |
+
"""
|
12 |
+
Função principal que é chamada pelo Gradio para analisar os vídeos.
|
13 |
+
"""
|
14 |
+
if video_original_path is None or video_interpolado_path is None:
|
15 |
+
return None, "Por favor, envie os dois arquivos de vídeo para iniciar a análise."
|
16 |
+
|
17 |
+
# --- 1. Carregar frames do vídeo original ---
|
18 |
+
progress(0, desc="Carregando vídeo original...")
|
19 |
+
try:
|
20 |
+
cap_orig = cv2.VideoCapture(video_original_path)
|
21 |
+
frames_originais = []
|
22 |
+
while True:
|
23 |
+
ret, frame = cap_orig.read()
|
24 |
+
if not ret: break
|
25 |
+
frames_originais.append(frame)
|
26 |
+
cap_orig.release()
|
27 |
+
if not frames_originais:
|
28 |
+
return None, "Erro: Não foi possível ler frames do vídeo original. O arquivo pode estar corrompido."
|
29 |
+
except Exception as e:
|
30 |
+
return None, f"Erro ao processar o vídeo original: {e}"
|
31 |
+
|
32 |
+
# --- 2. Comparar com o vídeo longo ---
|
33 |
+
try:
|
34 |
+
cap_longo = cv2.VideoCapture(video_interpolado_path)
|
35 |
+
total_frames_longo = int(cap_longo.get(cv2.CAP_PROP_FRAME_COUNT))
|
36 |
+
if total_frames_longo == 0:
|
37 |
+
return None, "Erro: O vídeo gerado parece não ter frames."
|
38 |
+
|
39 |
+
posicoes_encontradas = []
|
40 |
+
index_frame_longo = 0
|
41 |
+
|
42 |
+
while True:
|
43 |
+
ret, frame_longo = cap_longo.read()
|
44 |
+
if not ret: break
|
45 |
+
|
46 |
+
# Atualiza a barra de progresso
|
47 |
+
progress(index_frame_longo / total_frames_longo, desc=f"Analisando Frame {index_frame_longo}/{total_frames_longo}")
|
48 |
+
|
49 |
+
for index_original, frame_original in enumerate(frames_originais):
|
50 |
+
if frame_longo.shape == frame_original.shape:
|
51 |
+
# Comparação pixel a pixel
|
52 |
+
if np.array_equal(frame_longo, frame_original):
|
53 |
+
posicoes_encontradas.append((index_original, index_frame_longo))
|
54 |
+
break # Otimização: se encontrou, vai para o próximo frame do vídeo longo
|
55 |
+
|
56 |
+
index_frame_longo += 1
|
57 |
+
|
58 |
+
cap_longo.release()
|
59 |
+
except Exception as e:
|
60 |
+
return None, f"Erro ao processar o vídeo gerado: {e}"
|
61 |
+
|
62 |
+
# --- 3. Gerar o gráfico e o relatório ---
|
63 |
+
fig = create_plot(posicoes_encontradas)
|
64 |
+
report = create_report(posicoes_encontradas, len(frames_originais), total_frames_longo)
|
65 |
+
|
66 |
+
return fig, report
|
67 |
+
|
68 |
+
def create_plot(results):
|
69 |
+
"""Cria a figura do Matplotlib para exibir no Gradio."""
|
70 |
+
fig, ax = plt.subplots(figsize=(10, 6))
|
71 |
+
|
72 |
+
if not results:
|
73 |
+
ax.text(0.5, 0.5, "Nenhum frame correspondente foi encontrado.",
|
74 |
+
ha='center', va='center', fontsize=12, color='orange')
|
75 |
+
else:
|
76 |
+
indices_originais, posicoes_encontradas = zip(*results)
|
77 |
+
|
78 |
+
# Gráfico de "pirulito" (stem plot)
|
79 |
+
ax.stem(posicoes_encontradas, indices_originais, linefmt='--g', markerfmt='ob', basefmt=" ")
|
80 |
+
ax.set_title("Posição dos Frames Originais no Vídeo Gerado", color='white', fontsize=16)
|
81 |
+
ax.set_xlabel("Índice do Frame no Vídeo Longo", color='white', fontsize=12)
|
82 |
+
ax.set_ylabel("Índice do Frame Original", color='white', fontsize=12)
|
83 |
+
ax.grid(True, linestyle='--', alpha=0.5)
|
84 |
+
ax.tick_params(axis='x', colors='white')
|
85 |
+
ax.tick_params(axis='y', colors='white')
|
86 |
+
|
87 |
+
fig.tight_layout()
|
88 |
+
return fig
|
89 |
+
|
90 |
+
def create_report(results, total_original, total_longo):
|
91 |
+
"""Cria um relatório em texto formatado com Markdown."""
|
92 |
+
if not results:
|
93 |
+
return "## Relatório de Análise\n\nNenhuma correspondência encontrada. Verifique se o vídeo gerado realmente contém os frames do vídeo original."
|
94 |
+
|
95 |
+
report_md = f"""
|
96 |
+
## Relatório de Análise
|
97 |
+
**Análise Concluída com Sucesso!**
|
98 |
+
|
99 |
+
- **Vídeo Original:** {total_original} frames.
|
100 |
+
- **Vídeo Gerado:** {total_longo} frames.
|
101 |
+
- **Correspondências Encontradas:** {len(results)} frames.
|
102 |
+
|
103 |
+
### Detalhes das Posições:
|
104 |
+
"""
|
105 |
+
for idx_original, idx_longo in results:
|
106 |
+
report_md += f"- O **Frame Original #{idx_original}** foi encontrado na **Posição #{idx_longo}** do vídeo gerado.\n"
|
107 |
+
|
108 |
+
return report_md
|
109 |
+
|
110 |
+
# --- Interface Gradio ---
|
111 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
112 |
+
gr.Markdown(
|
113 |
+
"""
|
114 |
+
# 📊 Analisador de Frames de Vídeo
|
115 |
+
Esta ferramenta compara dois vídeos para encontrar onde os frames de um vídeo original (curto) aparecem em um vídeo gerado (longo/interpolado).
|
116 |
+
1. Suba o vídeo original (ex: 10 frames).
|
117 |
+
2. Suba o vídeo gerado a partir do original (ex: 100 frames).
|
118 |
+
3. Clique em "Analisar" e veja o gráfico e o relatório.
|
119 |
+
"""
|
120 |
+
)
|
121 |
+
|
122 |
+
with gr.Row():
|
123 |
+
video_original_input = gr.Video(label="1. Vídeo Original (Curto)")
|
124 |
+
video_interpolado_input = gr.Video(label="2. Vídeo Gerado (Longo/Interpolado)")
|
125 |
+
|
126 |
+
btn_analisar = gr.Button("Analisar Vídeos", variant="primary")
|
127 |
+
|
128 |
+
gr.Markdown("---")
|
129 |
+
gr.Markdown("## Resultados")
|
130 |
+
|
131 |
+
plot_output = gr.Plot(label="Gráfico de Comparação")
|
132 |
+
report_output = gr.Markdown(label="Relatório Detalhado")
|
133 |
+
|
134 |
+
btn_analisar.click(
|
135 |
+
fn=analyze_videos,
|
136 |
+
inputs=[video_original_input, video_interpolado_input],
|
137 |
+
outputs=[plot_output, report_output]
|
138 |
+
)
|
139 |
+
|
140 |
+
if __name__ == "__main__":
|
141 |
+
demo.launch()
|