EU-IA commited on
Commit
41b4608
·
verified ·
1 Parent(s): 60805fc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -13
app.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
@@ -34,17 +36,42 @@ except Exception as e:
34
 
35
  # --- FUNÇÕES DE ANÁLISE ---
36
 
37
- def analisar_fidelidade(video_path):
 
 
38
  cap = cv2.VideoCapture(video_path)
 
 
 
39
  frames, ssim_scores, phash_distances = [], [], []
40
  fps = cap.get(cv2.CAP_PROP_FPS) or 30
 
 
 
 
41
 
42
- while True:
 
 
 
 
 
 
 
 
 
 
43
  ret, frame = cap.read()
44
  if not ret: break
45
  frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
 
 
46
  cap.release()
47
 
 
 
 
 
48
  for i in range(len(frames) - 1):
49
  gray1 = cv2.cvtColor(frames[i], cv2.COLOR_RGB2GRAY)
50
  gray2 = cv2.cvtColor(frames[i+1], cv2.COLOR_RGB2GRAY)
@@ -61,6 +88,7 @@ def analisar_fidelidade(video_path):
61
 
62
  def analisar_cor_iluminacao(frames):
63
  lum_corr_scores, color_corr_scores = [], []
 
64
  for i in range(len(frames) - 1):
65
  frame1, frame2 = frames[i], frames[i+1]
66
  gray1, gray2 = cv2.cvtColor(frame1, cv2.COLOR_RGB2GRAY), cv2.cvtColor(frame2, cv2.COLOR_RGB2GRAY)
@@ -83,7 +111,7 @@ def analisar_cor_iluminacao(frames):
83
 
84
  def analisar_anomalias_movimento(frames):
85
  magnitude_scores, orientation_variance_scores = [], []
86
- if not frames: return [], []
87
  prev_gray = cv2.cvtColor(frames[0], cv2.COLOR_RGB2GRAY)
88
  for i in range(1, len(frames)):
89
  current_gray = cv2.cvtColor(frames[i], cv2.COLOR_RGB2GRAY)
@@ -96,6 +124,7 @@ def analisar_anomalias_movimento(frames):
96
 
97
  def analisar_estabilidade_foco(frames):
98
  ssim_foco_scores, jitter_foco_scores = [], []
 
99
  last_roi_center = None
100
  for i in range(len(frames) - 1):
101
  frame1_cv, frame2_cv = cv2.cvtColor(frames[i], cv2.COLOR_RGB2BGR), cv2.cvtColor(frames[i+1], cv2.COLOR_RGB2BGR)
@@ -131,6 +160,46 @@ def executar_teste_semantico(phash_distances, descriptions_text):
131
  # (Função como definida anteriormente)
132
  return None, "Função ainda não implementada completamente no template"
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  # --- FUNÇÕES DE PLOTAGEM ---
136
  def plot_to_file(fig, filename):
@@ -140,6 +209,7 @@ def plot_to_file(fig, filename):
140
  return path
141
 
142
  def gerar_grafico_fidelidade(ssim, phash, num_frames, fps):
 
143
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
144
  x_axis = [i/fps for i in range(len(ssim))]
145
  ax1.plot(x_axis, ssim, label='SSIM')
@@ -148,6 +218,7 @@ def gerar_grafico_fidelidade(ssim, phash, num_frames, fps):
148
  return plot_to_file(fig, "fidelidade")
149
 
150
  def gerar_grafico_cor(lum, color, num_frames, fps):
 
151
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
152
  x_axis = [i/fps for i in range(len(lum))]
153
  ax1.plot(x_axis, lum, label='Luminância', color='gold')
@@ -156,6 +227,7 @@ def gerar_grafico_cor(lum, color, num_frames, fps):
156
  return plot_to_file(fig, "cor")
157
 
158
  def gerar_grafico_anomalias(mag, var, num_frames, fps):
 
159
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
160
  x_axis = [i/fps for i in range(len(mag))]
161
  ax1.plot(x_axis, mag, label='Magnitude')
@@ -164,6 +236,7 @@ def gerar_grafico_anomalias(mag, var, num_frames, fps):
164
  return plot_to_file(fig, "anomalias")
165
 
166
  def gerar_grafico_foco(ssim_global, ssim_foco, jitter, num_frames, fps):
 
167
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
168
  x_axis = [i/fps for i in range(len(ssim_global))]
169
  ax1.plot(x_axis, ssim_global, label='Global')
@@ -173,12 +246,18 @@ def gerar_grafico_foco(ssim_global, ssim_foco, jitter, num_frames, fps):
173
  return plot_to_file(fig, "foco")
174
 
175
 
176
- # --- FUNÇÃO DE CALLBACK PRINCIPAL ---
177
- def run_full_analysis(video_path, descriptions_text, progress=gr.Progress()):
178
  if video_path is None: raise gr.Error("Por favor, faça o upload de um vídeo.")
179
 
180
- progress(0, desc="Analisando fidelidade...")
181
- frames, fps, ssim_scores, phash_distances = analisar_fidelidade(video_path)
 
 
 
 
 
 
182
 
183
  progress(0.2, desc="Gerando gráfico de fidelidade...")
184
  fidelidade_plot_path = gerar_grafico_fidelidade(ssim_scores, phash_distances, len(frames), fps)
@@ -204,17 +283,28 @@ def run_full_analysis(video_path, descriptions_text, progress=gr.Progress()):
204
  if error_msg: gr.Warning(error_msg)
205
 
206
  progress(1.0, desc="Análise completa!")
207
- return fidelidade_plot_path, cor_plot_path, foco_plot_path, semantico_path, anomalias_plot_path
 
208
 
209
- # --- INTERFACE GRADIO ---
210
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
211
  gr.Markdown("# Suíte de Validação Completa para Geração de Vídeo (ADUC-SDR)")
212
  with gr.Row():
213
  with gr.Column(scale=1):
214
  video_input = gr.Video(label="1. Upload do vídeo")
215
- descriptions_input = gr.Textbox(lines=5, label="2. Descrições (Opcional)", placeholder="Uma descrição por cena para o teste de inteligência...")
216
- analyze_button = gr.Button("3. Executar Análise Completa", variant="primary")
 
 
 
 
 
 
 
217
  with gr.Tabs():
 
 
 
218
  with gr.TabItem("1. Fidelidade e Coerência"):
219
  plot_fidelidade = gr.Image(label="Gráfico de Análise de Fidelidade (SSIM e pHash)")
220
  with gr.TabItem("2. Cor e Iluminação"):
@@ -226,10 +316,11 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
226
  with gr.TabItem("5. Inteligência Adaptativa"):
227
  plot_semantico = gr.Image(label="Gráfico de Estresse Semântico")
228
 
 
229
  analyze_button.click(
230
  fn=run_full_analysis,
231
- inputs=[video_input, descriptions_input],
232
- outputs=[plot_fidelidade, plot_cor, plot_foco, plot_semantico, plot_anomalias]
233
  )
234
 
235
  if __name__ == "__main__":
 
1
+ --- START OF FILE app.py ---
2
+
3
  import gradio as gr
4
  import cv2
5
  import numpy as np
 
36
 
37
  # --- FUNÇÕES DE ANÁLISE ---
38
 
39
+ # --- MODIFICADO ---
40
+ # Agora aceita start_frame e end_frame para analisar apenas um trecho.
41
+ def analisar_fidelidade(video_path, start_frame=0, end_frame=0):
42
  cap = cv2.VideoCapture(video_path)
43
+ if not cap.isOpened():
44
+ raise gr.Error("Não foi possível abrir o arquivo de vídeo.")
45
+
46
  frames, ssim_scores, phash_distances = [], [], []
47
  fps = cap.get(cv2.CAP_PROP_FPS) or 30
48
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
49
+
50
+ # Valida e ajusta os frames de início e fim
51
+ process_full_video = (start_frame == 0 and end_frame == 0) or (start_frame >= end_frame)
52
 
53
+ if process_full_video:
54
+ start_frame = 0
55
+ end_frame = total_frames
56
+ else:
57
+ start_frame = max(0, start_frame)
58
+ end_frame = min(total_frames, end_frame)
59
+
60
+ cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
61
+
62
+ current_frame_pos = start_frame
63
+ while current_frame_pos < end_frame:
64
  ret, frame = cap.read()
65
  if not ret: break
66
  frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
67
+ current_frame_pos += 1
68
+
69
  cap.release()
70
 
71
+ if len(frames) < 2:
72
+ gr.Warning("O trecho selecionado é muito curto para análise (menos de 2 frames).")
73
+ return frames, fps, [], []
74
+
75
  for i in range(len(frames) - 1):
76
  gray1 = cv2.cvtColor(frames[i], cv2.COLOR_RGB2GRAY)
77
  gray2 = cv2.cvtColor(frames[i+1], cv2.COLOR_RGB2GRAY)
 
88
 
89
  def analisar_cor_iluminacao(frames):
90
  lum_corr_scores, color_corr_scores = [], []
91
+ if len(frames) < 2: return [], []
92
  for i in range(len(frames) - 1):
93
  frame1, frame2 = frames[i], frames[i+1]
94
  gray1, gray2 = cv2.cvtColor(frame1, cv2.COLOR_RGB2GRAY), cv2.cvtColor(frame2, cv2.COLOR_RGB2GRAY)
 
111
 
112
  def analisar_anomalias_movimento(frames):
113
  magnitude_scores, orientation_variance_scores = [], []
114
+ if len(frames) < 2: return [], []
115
  prev_gray = cv2.cvtColor(frames[0], cv2.COLOR_RGB2GRAY)
116
  for i in range(1, len(frames)):
117
  current_gray = cv2.cvtColor(frames[i], cv2.COLOR_RGB2GRAY)
 
124
 
125
  def analisar_estabilidade_foco(frames):
126
  ssim_foco_scores, jitter_foco_scores = [], []
127
+ if len(frames) < 2: return [], []
128
  last_roi_center = None
129
  for i in range(len(frames) - 1):
130
  frame1_cv, frame2_cv = cv2.cvtColor(frames[i], cv2.COLOR_RGB2BGR), cv2.cvtColor(frames[i+1], cv2.COLOR_RGB2BGR)
 
160
  # (Função como definida anteriormente)
161
  return None, "Função ainda não implementada completamente no template"
162
 
163
+ # --- NOVA FUNÇÃO ---
164
+ # Extrai frames de um trecho e os une em uma única imagem.
165
+ def extrair_e_visualizar_frames(video_path, start_frame, end_frame):
166
+ if not video_path or start_frame >= end_frame:
167
+ return None
168
+
169
+ cap = cv2.VideoCapture(video_path)
170
+ if not cap.isOpened():
171
+ return None
172
+
173
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
174
+ start_frame = max(0, start_frame)
175
+ end_frame = min(total_frames, end_frame)
176
+
177
+ cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
178
+
179
+ extracted_frames = []
180
+ for i in range(start_frame, end_frame):
181
+ ret, frame = cap.read()
182
+ if not ret:
183
+ break
184
+ # Adiciona texto com o número do frame
185
+ frame_num_text = f"Frame: {i}"
186
+ cv2.putText(frame, frame_num_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
187
+ extracted_frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
188
+
189
+ cap.release()
190
+
191
+ if not extracted_frames:
192
+ return None
193
+
194
+ # Une os frames horizontalmente
195
+ combined_image = np.hstack(extracted_frames)
196
+
197
+ # Salva a imagem combinada em um arquivo temporário
198
+ pil_img = Image.fromarray(combined_image)
199
+ path = "frames_extraidos.png"
200
+ pil_img.save(path)
201
+ return path
202
+
203
 
204
  # --- FUNÇÕES DE PLOTAGEM ---
205
  def plot_to_file(fig, filename):
 
209
  return path
210
 
211
  def gerar_grafico_fidelidade(ssim, phash, num_frames, fps):
212
+ if not ssim: return None
213
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
214
  x_axis = [i/fps for i in range(len(ssim))]
215
  ax1.plot(x_axis, ssim, label='SSIM')
 
218
  return plot_to_file(fig, "fidelidade")
219
 
220
  def gerar_grafico_cor(lum, color, num_frames, fps):
221
+ if not lum: return None
222
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
223
  x_axis = [i/fps for i in range(len(lum))]
224
  ax1.plot(x_axis, lum, label='Luminância', color='gold')
 
227
  return plot_to_file(fig, "cor")
228
 
229
  def gerar_grafico_anomalias(mag, var, num_frames, fps):
230
+ if not mag: return None
231
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
232
  x_axis = [i/fps for i in range(len(mag))]
233
  ax1.plot(x_axis, mag, label='Magnitude')
 
236
  return plot_to_file(fig, "anomalias")
237
 
238
  def gerar_grafico_foco(ssim_global, ssim_foco, jitter, num_frames, fps):
239
+ if not ssim_global: return None
240
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
241
  x_axis = [i/fps for i in range(len(ssim_global))]
242
  ax1.plot(x_axis, ssim_global, label='Global')
 
246
  return plot_to_file(fig, "foco")
247
 
248
 
249
+ # --- FUNÇÃO DE CALLBACK PRINCIPAL (MODIFICADA) ---
250
+ def run_full_analysis(video_path, descriptions_text, start_frame, end_frame, progress=gr.Progress()):
251
  if video_path is None: raise gr.Error("Por favor, faça o upload de um vídeo.")
252
 
253
+ # Converte para inteiros
254
+ start_frame, end_frame = int(start_frame), int(end_frame)
255
+
256
+ progress(0, desc="Extraindo frames para visualização...")
257
+ frames_imagem_path = extrair_e_visualizar_frames(video_path, start_frame, end_frame)
258
+
259
+ progress(0.1, desc="Analisando fidelidade do trecho...")
260
+ frames, fps, ssim_scores, phash_distances = analisar_fidelidade(video_path, start_frame, end_frame)
261
 
262
  progress(0.2, desc="Gerando gráfico de fidelidade...")
263
  fidelidade_plot_path = gerar_grafico_fidelidade(ssim_scores, phash_distances, len(frames), fps)
 
283
  if error_msg: gr.Warning(error_msg)
284
 
285
  progress(1.0, desc="Análise completa!")
286
+ # --- MODIFICADO --- Retorna o caminho da nova imagem de frames também
287
+ return frames_imagem_path, fidelidade_plot_path, cor_plot_path, foco_plot_path, semantico_path, anomalias_plot_path
288
 
289
+ # --- INTERFACE GRADIO (MODIFICADA) ---
290
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
291
  gr.Markdown("# Suíte de Validação Completa para Geração de Vídeo (ADUC-SDR)")
292
  with gr.Row():
293
  with gr.Column(scale=1):
294
  video_input = gr.Video(label="1. Upload do vídeo")
295
+ descriptions_input = gr.Textbox(lines=5, label="3. Descrições (Opcional)", placeholder="Uma descrição por cena para o teste de inteligência...")
296
+
297
+ # --- NOVOS COMPONENTES ---
298
+ with gr.Row():
299
+ start_frame_input = gr.Number(label="Frame Inicial", value=0, precision=0, info="Deixe 0 e 0 para analisar o vídeo inteiro.")
300
+ end_frame_input = gr.Number(label="Frame Final", value=0, precision=0, info="Ex: 88 e 94 para analisar esse trecho.")
301
+
302
+ analyze_button = gr.Button("4. Executar Análise Completa", variant="primary")
303
+
304
  with gr.Tabs():
305
+ # --- NOVA ABA ---
306
+ with gr.TabItem("Frames Extraídos"):
307
+ extracted_frames_img = gr.Image(label="Visualização dos Frames Lado a Lado")
308
  with gr.TabItem("1. Fidelidade e Coerência"):
309
  plot_fidelidade = gr.Image(label="Gráfico de Análise de Fidelidade (SSIM e pHash)")
310
  with gr.TabItem("2. Cor e Iluminação"):
 
316
  with gr.TabItem("5. Inteligência Adaptativa"):
317
  plot_semantico = gr.Image(label="Gráfico de Estresse Semântico")
318
 
319
+ # --- MODIFICADO --- Atualiza inputs e outputs do botão
320
  analyze_button.click(
321
  fn=run_full_analysis,
322
+ inputs=[video_input, descriptions_input, start_frame_input, end_frame_input],
323
+ outputs=[extracted_frames_img, plot_fidelidade, plot_cor, plot_foco, plot_semantico, plot_anomalias]
324
  )
325
 
326
  if __name__ == "__main__":