Carlexx commited on
Commit
826a091
·
verified ·
1 Parent(s): 7b1d625

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +235 -0
app.py CHANGED
@@ -7,6 +7,241 @@ from PIL import Image
7
  import imagehash
8
  import torch
9
  from scipy.stats import pearsonr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # --- MÓDULO DE INICIALIZAÇÃO ---
12
  CLIP_AVAILABLE, SALIENCY_AVAILABLE = False, False
 
7
  import imagehash
8
  import torch
9
  from scipy.stats import pearsonr
10
+ import os
11
+
12
+ # --- MÓDULO DE INICIALIZAÇÃO ---
13
+ # Tenta carregar os modelos e módulos, definindo flags de disponibilidade.
14
+ CLIP_AVAILABLE, SALIENCY_AVAILABLE = False, False
15
+ try:
16
+ from transformers import CLIPProcessor, CLIPModel
17
+ MODEL_ID = "openai/clip-vit-base-patch32"
18
+ clip_model = CLIPModel.from_pretrained(MODEL_ID)
19
+ clip_processor = CLIPProcessor.from_pretrained(MODEL_ID)
20
+ CLIP_AVAILABLE = True
21
+ print("Modelo CLIP carregado com sucesso.")
22
+ except Exception as e:
23
+ print(f"AVISO: Modelo CLIP não carregado. Teste de Inteligência desabilitado. Erro: {e}")
24
+
25
+ try:
26
+ saliency_detector = cv2.saliency.StaticSaliencySpectralResidual_create()
27
+ SALIENCY_AVAILABLE = True
28
+ print("Módulo de Saliência carregado com sucesso.")
29
+ except AttributeError:
30
+ print("AVISO: Módulo de Saliência não encontrado. Análise de Foco Móvel desabilitada.")
31
+ print("Certifique-se de que 'opencv-contrib-python-headless' está no requirements.txt")
32
+ except Exception as e:
33
+ print(f"AVISO: Módulo de Saliência não carregado. Erro: {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)
51
+ ssim_val, _ = ssim(gray1, gray2, full=True, data_range=gray1.max() - gray1.min())
52
+
53
+ pil_img1 = Image.fromarray(frames[i])
54
+ pil_img2 = Image.fromarray(frames[i+1])
55
+ phash_dist = imagehash.phash(pil_img1) - imagehash.phash(pil_img2)
56
+
57
+ ssim_scores.append(ssim_val)
58
+ phash_distances.append(phash_dist)
59
+
60
+ return frames, fps, ssim_scores, phash_distances
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)
67
+ hist1_lum = cv2.calcHist([gray1], [0], None, [256], [0,256])
68
+ hist2_lum = cv2.calcHist([gray2], [0], None, [256], [0,256])
69
+ cv2.normalize(hist1_lum, hist1_lum, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
70
+ cv2.normalize(hist2_lum, hist2_lum, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
71
+ lum_corr = cv2.compareHist(hist1_lum, hist2_lum, cv2.HISTCMP_CORREL)
72
+ lum_corr_scores.append(lum_corr)
73
+
74
+ corrs = []
75
+ for chan in range(3):
76
+ hist1 = cv2.calcHist([frame1],[chan],None,[256],[0,256])
77
+ hist2 = cv2.calcHist([frame2],[chan],None,[256],[0,256])
78
+ cv2.normalize(hist1, hist1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
79
+ cv2.normalize(hist2, hist2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
80
+ corrs.append(cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL))
81
+ color_corr_scores.append(np.mean(corrs))
82
+ return lum_corr_scores, color_corr_scores
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)
90
+ flow = cv2.calcOpticalFlowFarneback(prev_gray, current_gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
91
+ magnitude, angle = cv2.cartToPolar(flow[...,0], flow[...,1], angleInDegrees=True)
92
+ magnitude_scores.append(np.mean(magnitude))
93
+ orientation_variance_scores.append(np.var(angle))
94
+ prev_gray = current_gray
95
+ return magnitude_scores, orientation_variance_scores
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)
102
+ try:
103
+ _, saliencyMap1 = saliency_detector.computeSaliency(frame1_cv)
104
+ _, saliencyMap2 = saliency_detector.computeSaliency(frame2_cv)
105
+ saliencyMap1_8bit, saliencyMap2_8bit = (saliencyMap1 * 255).astype("uint8"), (saliencyMap2 * 255).astype("uint8")
106
+ _, thresh1 = cv2.threshold(saliencyMap1_8bit, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
107
+ _, thresh2 = cv2.threshold(saliencyMap2_8bit, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
108
+ contours1, _ = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
109
+ contours2, _ = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
110
+
111
+ if contours1 and contours2:
112
+ x1, y1, w1, h1 = cv2.boundingRect(max(contours1, key=cv2.contourArea))
113
+ x2, y2, w2, h2 = cv2.boundingRect(max(contours2, key=cv2.contourArea))
114
+ roi1_gray, roi2_gray = cv2.cvtColor(frames[i][y1:y1+h1, x1:x1+w1], cv2.COLOR_RGB2GRAY), cv2.cvtColor(frames[i+1][y2:y2+h2, x2:x2+w2], cv2.COLOR_RGB2GRAY)
115
+ if roi1_gray.size == 0 or roi2_gray.size == 0: raise ValueError("ROI vazia")
116
+ roi2_gray_resized = cv2.resize(roi2_gray, (roi1_gray.shape[1], roi1_gray.shape[0]))
117
+
118
+ ssim_foco, _ = ssim(roi1_gray, roi2_gray_resized, full=True, data_range=255) if min(roi1_gray.shape) > 7 else (0, None)
119
+ ssim_foco_scores.append(ssim_foco)
120
+
121
+ center = (x1 + w1/2, y1 + h1/2)
122
+ jitter_foco_scores.append(np.linalg.norm(np.array(center) - np.array(last_roi_center)) if last_roi_center else 0)
123
+ last_roi_center = center
124
+ else:
125
+ ssim_foco_scores.append(0); jitter_foco_scores.append(0)
126
+ except Exception:
127
+ ssim_foco_scores.append(0); jitter_foco_scores.append(0)
128
+ return ssim_foco_scores, jitter_foco_scores
129
+
130
+ 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):
137
+ path = f"{filename}.png"
138
+ fig.savefig(path)
139
+ plt.close(fig)
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')
146
+ ax2.plot(x_axis, phash, label='pHash Distance', color='red')
147
+ ax1.set_title('Fidelidade Estrutural (SSIM)'); ax2.set_title('Mudança Perceptual (pHash)')
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')
154
+ ax2.plot(x_axis, color, label='Cor (RGB)', color='magenta')
155
+ ax1.set_title('Consistência de Iluminação'); ax2.set_title('Consistência de Cor')
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')
162
+ ax2.plot(x_axis, var, label='Variância de Orientação', color='red')
163
+ ax1.set_title('Magnitude do Movimento'); ax2.set_title('Incoerência de Movimento (Glitches)')
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')
170
+ ax1.plot(x_axis, ssim_foco, label='Foco')
171
+ ax2.plot(x_axis, jitter, label='Jitter', color='coral')
172
+ ax1.set_title('Estabilidade de Foco (SSIM)'); ax2.set_title('Jitter de Foco')
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)
185
+
186
+ progress(0.3, desc="Analisando cor e iluminação...")
187
+ lum_scores, color_scores = analisar_cor_iluminacao(frames)
188
+ cor_plot_path = gerar_grafico_cor(lum_scores, color_scores, len(frames), fps)
189
+
190
+ progress(0.4, desc="Analisando glitches de movimento...")
191
+ mag_scores, var_scores = analisar_anomalias_movimento(frames)
192
+ anomalias_plot_path = gerar_grafico_anomalias(mag_scores, var_scores, len(frames), fps)
193
+
194
+ foco_plot_path = None
195
+ if SALIENCY_AVAILABLE:
196
+ progress(0.6, desc="Analisando foco móvel...")
197
+ ssim_foco, jitter_foco = analisar_estabilidade_foco(frames)
198
+ foco_plot_path = gerar_grafico_foco(ssim_scores, ssim_foco, jitter_foco, len(frames), fps)
199
+
200
+ semantico_path = None
201
+ if CLIP_AVAILABLE and descriptions_text.strip():
202
+ progress(0.8, desc="Executando teste semântico...")
203
+ semantico_path, error_msg = executar_teste_semantico(phash_distances, descriptions_text)
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"):
221
+ plot_cor = gr.Image(label="Gráfico de Análise de Cor e Luminância")
222
+ with gr.TabItem("3. Foco (Vídeo Móvel)"):
223
+ plot_foco = gr.Image(label="Gráfico de Análise de Foco e Jitter")
224
+ with gr.TabItem("4. Glitches de Movimento"):
225
+ plot_anomalias = gr.Image(label="Gráfico do Detector de Anomalias de Movimento")
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__":
236
+ demo.queue().launch()import gradio as gr
237
+ import cv2
238
+ import numpy as np
239
+ from skimage.metrics import structural_similarity as ssim
240
+ import matplotlib.pyplot as plt
241
+ from PIL import Image
242
+ import imagehash
243
+ import torch
244
+ from scipy.stats import pearsonr
245
 
246
  # --- MÓDULO DE INICIALIZAÇÃO ---
247
  CLIP_AVAILABLE, SALIENCY_AVAILABLE = False, False