Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import cv2 | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import os | |
| # Define um estilo de gráfico que fica bem no modo escuro do Gradio | |
| plt.style.use('dark_background') | |
| def analyze_videos(video_original_path, video_interpolado_path, progress=gr.Progress()): | |
| """ | |
| Função principal que é chamada pelo Gradio para analisar os vídeos. | |
| """ | |
| if video_original_path is None or video_interpolado_path is None: | |
| return None, "Por favor, envie os dois arquivos de vídeo para iniciar a análise." | |
| # --- 1. Carregar frames do vídeo original --- | |
| progress(0, desc="Carregando vídeo original...") | |
| try: | |
| cap_orig = cv2.VideoCapture(video_original_path) | |
| frames_originais = [] | |
| while True: | |
| ret, frame = cap_orig.read() | |
| if not ret: break | |
| frames_originais.append(frame) | |
| cap_orig.release() | |
| if not frames_originais: | |
| return None, "Erro: Não foi possível ler frames do vídeo original. O arquivo pode estar corrompido." | |
| except Exception as e: | |
| return None, f"Erro ao processar o vídeo original: {e}" | |
| # --- 2. Comparar com o vídeo longo --- | |
| try: | |
| cap_longo = cv2.VideoCapture(video_interpolado_path) | |
| total_frames_longo = int(cap_longo.get(cv2.CAP_PROP_FRAME_COUNT)) | |
| if total_frames_longo == 0: | |
| return None, "Erro: O vídeo gerado parece não ter frames." | |
| posicoes_encontradas = [] | |
| index_frame_longo = 0 | |
| while True: | |
| ret, frame_longo = cap_longo.read() | |
| if not ret: break | |
| # Atualiza a barra de progresso | |
| progress(index_frame_longo / total_frames_longo, desc=f"Analisando Frame {index_frame_longo}/{total_frames_longo}") | |
| for index_original, frame_original in enumerate(frames_originais): | |
| if frame_longo.shape == frame_original.shape: | |
| # Comparação pixel a pixel | |
| if np.array_equal(frame_longo, frame_original): | |
| posicoes_encontradas.append((index_original, index_frame_longo)) | |
| break # Otimização: se encontrou, vai para o próximo frame do vídeo longo | |
| index_frame_longo += 1 | |
| cap_longo.release() | |
| except Exception as e: | |
| return None, f"Erro ao processar o vídeo gerado: {e}" | |
| # --- 3. Gerar o gráfico e o relatório --- | |
| fig = create_plot(posicoes_encontradas) | |
| report = create_report(posicoes_encontradas, len(frames_originais), total_frames_longo) | |
| return fig, report | |
| def create_plot(results): | |
| """Cria a figura do Matplotlib para exibir no Gradio.""" | |
| fig, ax = plt.subplots(figsize=(10, 6)) | |
| if not results: | |
| ax.text(0.5, 0.5, "Nenhum frame correspondente foi encontrado.", | |
| ha='center', va='center', fontsize=12, color='orange') | |
| else: | |
| indices_originais, posicoes_encontradas = zip(*results) | |
| # Gráfico de "pirulito" (stem plot) | |
| ax.stem(posicoes_encontradas, indices_originais, linefmt='--g', markerfmt='ob', basefmt=" ") | |
| ax.set_title("Posição dos Frames Originais no Vídeo Gerado", color='white', fontsize=16) | |
| ax.set_xlabel("Índice do Frame no Vídeo Longo", color='white', fontsize=12) | |
| ax.set_ylabel("Índice do Frame Original", color='white', fontsize=12) | |
| ax.grid(True, linestyle='--', alpha=0.5) | |
| ax.tick_params(axis='x', colors='white') | |
| ax.tick_params(axis='y', colors='white') | |
| fig.tight_layout() | |
| return fig | |
| def create_report(results, total_original, total_longo): | |
| """Cria um relatório em texto formatado com Markdown.""" | |
| if not results: | |
| 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." | |
| report_md = f""" | |
| ## Relatório de Análise | |
| **Análise Concluída com Sucesso!** | |
| - **Vídeo Original:** {total_original} frames. | |
| - **Vídeo Gerado:** {total_longo} frames. | |
| - **Correspondências Encontradas:** {len(results)} frames. | |
| ### Detalhes das Posições: | |
| """ | |
| for idx_original, idx_longo in results: | |
| report_md += f"- O **Frame Original #{idx_original}** foi encontrado na **Posição #{idx_longo}** do vídeo gerado.\n" | |
| return report_md | |
| # --- Interface Gradio --- | |
| with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
| gr.Markdown( | |
| """ | |
| # 📊 Analisador de Frames de Vídeo | |
| 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). | |
| 1. Suba o vídeo original (ex: 10 frames). | |
| 2. Suba o vídeo gerado a partir do original (ex: 100 frames). | |
| 3. Clique em "Analisar" e veja o gráfico e o relatório. | |
| """ | |
| ) | |
| with gr.Row(): | |
| video_original_input = gr.Video(label="1. Vídeo Original (Curto)") | |
| video_interpolado_input = gr.Video(label="2. Vídeo Gerado (Longo/Interpolado)") | |
| btn_analisar = gr.Button("Analisar Vídeos", variant="primary") | |
| gr.Markdown("---") | |
| gr.Markdown("## Resultados") | |
| plot_output = gr.Plot(label="Gráfico de Comparação") | |
| report_output = gr.Markdown(label="Relatório Detalhado") | |
| btn_analisar.click( | |
| fn=analyze_videos, | |
| inputs=[video_original_input, video_interpolado_input], | |
| outputs=[plot_output, report_output] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |