Update app.py
Browse files
app.py
CHANGED
|
@@ -232,200 +232,5 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 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
|
| 248 |
-
try:
|
| 249 |
-
from transformers import CLIPProcessor, CLIPModel
|
| 250 |
-
MODEL_ID = "openai/clip-vit-base-patch32"
|
| 251 |
-
clip_model = CLIPModel.from_pretrained(MODEL_ID)
|
| 252 |
-
clip_processor = CLIPProcessor.from_pretrained(MODEL_ID)
|
| 253 |
-
CLIP_AVAILABLE = True
|
| 254 |
-
print("Modelo CLIP carregado com sucesso.")
|
| 255 |
-
except Exception as e:
|
| 256 |
-
print(f"AVISO: Modelo CLIP n茫o carregado. Teste de Intelig锚ncia desabilitado. Erro: {e}")
|
| 257 |
-
|
| 258 |
-
try:
|
| 259 |
-
saliency_detector = cv2.saliency.StaticSaliencySpectralResidual_create()
|
| 260 |
-
SALIENCY_AVAILABLE = True
|
| 261 |
-
print("M贸dulo de Sali锚ncia carregado com sucesso.")
|
| 262 |
-
except AttributeError:
|
| 263 |
-
print("AVISO: M贸dulo de Sali锚ncia n茫o encontrado. An谩lise de Foco M贸vel desabilitada.")
|
| 264 |
-
print("Certifique-se de que 'opencv-contrib-python-headless' est谩 no requirements.txt")
|
| 265 |
-
except Exception as e:
|
| 266 |
-
print(f"AVISO: M贸dulo de Sali锚ncia n茫o carregado. Erro: {e}")
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
# --- FUN脟脮ES DE AN脕LISE ---
|
| 270 |
-
|
| 271 |
-
def analisar_fidelidade(video_path):
|
| 272 |
-
cap = cv2.VideoCapture(video_path)
|
| 273 |
-
frames, ssim_scores, phash_distances = [], [], []
|
| 274 |
-
fps = cap.get(cv2.CAP_PROP_FPS) or 30
|
| 275 |
-
|
| 276 |
-
while True:
|
| 277 |
-
ret, frame = cap.read()
|
| 278 |
-
if not ret: break
|
| 279 |
-
frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
|
| 280 |
-
cap.release()
|
| 281 |
-
|
| 282 |
-
for i in range(len(frames) - 1):
|
| 283 |
-
gray1 = cv2.cvtColor(frames[i], cv2.COLOR_RGB2GRAY)
|
| 284 |
-
gray2 = cv2.cvtColor(frames[i+1], cv2.COLOR_RGB2GRAY)
|
| 285 |
-
ssim_val, _ = ssim(gray1, gray2, full=True, data_range=gray1.max() - gray1.min())
|
| 286 |
-
|
| 287 |
-
pil_img1 = Image.fromarray(frames[i])
|
| 288 |
-
pil_img2 = Image.fromarray(frames[i+1])
|
| 289 |
-
phash_dist = imagehash.phash(pil_img1) - imagehash.phash(pil_img2)
|
| 290 |
-
|
| 291 |
-
ssim_scores.append(ssim_val)
|
| 292 |
-
phash_distances.append(phash_dist)
|
| 293 |
-
|
| 294 |
-
return frames, fps, ssim_scores, phash_distances
|
| 295 |
-
|
| 296 |
-
def analisar_cor_iluminacao(frames):
|
| 297 |
-
lum_corr_scores, color_corr_scores = [], []
|
| 298 |
-
for i in range(len(frames) - 1):
|
| 299 |
-
frame1, frame2 = frames[i], frames[i+1]
|
| 300 |
-
gray1, gray2 = cv2.cvtColor(frame1, cv2.COLOR_RGB2GRAY), cv2.cvtColor(frame2, cv2.COLOR_RGB2GRAY)
|
| 301 |
-
hist1_lum, hist2_lum = cv2.calcHist([gray1], [0], None, [256], [0,256]), cv2.calcHist([gray2], [0], None, [256], [0,256])
|
| 302 |
-
lum_corr = cv2.compareHist(hist1_lum, hist2_lum, cv2.HISTCMP_CORREL)
|
| 303 |
-
lum_corr_scores.append(lum_corr)
|
| 304 |
-
|
| 305 |
-
corrs = []
|
| 306 |
-
for chan in range(3):
|
| 307 |
-
hist1, hist2 = cv2.calcHist([frame1],[chan],None,[256],[0,256]), cv2.calcHist([frame2],[chan],None,[256],[0,256])
|
| 308 |
-
corrs.append(cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL))
|
| 309 |
-
color_corr_scores.append(np.mean(corrs))
|
| 310 |
-
|
| 311 |
-
return lum_corr_scores, color_corr_scores
|
| 312 |
-
|
| 313 |
-
def analisar_anomalias_movimento(frames):
|
| 314 |
-
magnitude_scores, orientation_variance_scores = [], []
|
| 315 |
-
prev_gray = cv2.cvtColor(frames[0], cv2.COLOR_RGB2GRAY)
|
| 316 |
-
for i in range(1, len(frames)):
|
| 317 |
-
current_gray = cv2.cvtColor(frames[i], cv2.COLOR_RGB2GRAY)
|
| 318 |
-
flow = cv2.calcOpticalFlowFarneback(prev_gray, current_gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
|
| 319 |
-
magnitude, angle = cv2.cartToPolar(flow[...,0], flow[...,1])
|
| 320 |
-
magnitude_scores.append(np.mean(magnitude))
|
| 321 |
-
orientation_variance_scores.append(np.var(angle))
|
| 322 |
-
prev_gray = current_gray
|
| 323 |
-
return magnitude_scores, orientation_variance_scores
|
| 324 |
-
|
| 325 |
-
def analisar_estabilidade_foco(frames):
|
| 326 |
-
ssim_foco_scores, jitter_foco_scores = [], []
|
| 327 |
-
last_roi_center = None
|
| 328 |
-
for i in range(len(frames) - 1):
|
| 329 |
-
frame1, frame2 = frames[i], frames[i+1]
|
| 330 |
-
try:
|
| 331 |
-
_, saliencyMap1 = saliency_detector.computeSaliency(frame1)
|
| 332 |
-
_, saliencyMap2 = saliency_detector.computeSaliency(frame2)
|
| 333 |
-
saliencyMap1_8bit, saliencyMap2_8bit = (saliencyMap1 * 255).astype("uint8"), (saliencyMap2 * 255).astype("uint8")
|
| 334 |
-
_, thresh1, _, thresh2 = cv2.threshold(saliencyMap1_8bit, 0, 255, cv2.THRESH_OTSU), cv2.threshold(saliencyMap2_8bit, 0, 255, cv2.THRESH_OTSU)
|
| 335 |
-
contours1, _ = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 336 |
-
contours2, _ = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 337 |
-
|
| 338 |
-
if contours1 and contours2:
|
| 339 |
-
x1, y1, w1, h1 = cv2.boundingRect(max(contours1, key=cv2.contourArea))
|
| 340 |
-
x2, y2, w2, h2 = cv2.boundingRect(max(contours2, key=cv2.contourArea))
|
| 341 |
-
roi1, roi2 = frame1[y1:y1+h1, x1:x1+w1], frame2[y2:y2+h2, x2:x2+w2]
|
| 342 |
-
roi1_gray, roi2_gray = cv2.cvtColor(roi1, cv2.COLOR_RGB2GRAY), cv2.cvtColor(roi2, cv2.COLOR_RGB2GRAY)
|
| 343 |
-
roi2_gray_resized = cv2.resize(roi2_gray, (roi1_gray.shape[1], roi1_gray.shape[0]))
|
| 344 |
-
|
| 345 |
-
ssim_foco, _ = ssim(roi1_gray, roi2_gray_resized, full=True, data_range=255) if min(roi1_gray.shape) > 7 else (0, None)
|
| 346 |
-
ssim_foco_scores.append(ssim_foco)
|
| 347 |
-
|
| 348 |
-
center = (x1 + w1/2, y1 + h1/2)
|
| 349 |
-
jitter_foco_scores.append(np.linalg.norm(np.array(center) - np.array(last_roi_center)) if last_roi_center else 0)
|
| 350 |
-
last_roi_center = center
|
| 351 |
-
else:
|
| 352 |
-
ssim_foco_scores.append(0); jitter_foco_scores.append(0)
|
| 353 |
-
except:
|
| 354 |
-
ssim_foco_scores.append(0); jitter_foco_scores.append(0)
|
| 355 |
-
return ssim_foco_scores, jitter_foco_scores
|
| 356 |
-
|
| 357 |
-
def executar_teste_semantico(phash_distances, descriptions_text):
|
| 358 |
-
# (Fun莽茫o como definida anteriormente)
|
| 359 |
-
return None, "Fun莽茫o ainda n茫o implementada completamente no template"
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
# --- FUN脟脮ES DE PLOTAGEM ---
|
| 363 |
-
# (Todas as suas fun莽玫es `gerar_grafico_...` devem estar aqui)
|
| 364 |
-
def gerar_grafico_fidelidade(ssim, phash, num_frames, fps):
|
| 365 |
-
path = "fidelidade.png"
|
| 366 |
-
# ... l贸gica de plotagem ...
|
| 367 |
-
plt.figure(); plt.plot(ssim); plt.savefig(path); plt.close()
|
| 368 |
-
return path
|
| 369 |
-
# ... e assim por diante para todas as outras fun莽玫es de plotagem ...
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
# --- FUN脟脙O DE CALLBACK PRINCIPAL ---
|
| 373 |
-
def run_full_analysis(video_path, descriptions_text, progress=gr.Progress):
|
| 374 |
-
if video_path is None: raise gr.Error("Fa莽a o upload de um v铆deo.")
|
| 375 |
-
|
| 376 |
-
progress(0, desc="Analisando fidelidade...")
|
| 377 |
-
frames, fps, ssim_scores, phash_distances = analisar_fidelidade(video_path)
|
| 378 |
-
|
| 379 |
-
progress(0.2, desc="Gerando gr谩fico de fidelidade...")
|
| 380 |
-
fidelidade_plot_path = gerar_grafico_fidelidade(ssim_scores, phash_distances, len(frames), fps)
|
| 381 |
-
|
| 382 |
-
progress(0.3, desc="Analisando cor e ilumina莽茫o...")
|
| 383 |
-
lum_scores, color_scores = analisar_cor_iluminacao(frames)
|
| 384 |
-
cor_plot_path = "cor.png" # Placeholder para a fun莽茫o de plotagem
|
| 385 |
-
|
| 386 |
-
progress(0.4, desc="Analisando glitches de movimento...")
|
| 387 |
-
mag_scores, var_scores = analisar_anomalias_movimento(frames)
|
| 388 |
-
anomalias_plot_path = "anomalias.png" # Placeholder
|
| 389 |
-
|
| 390 |
-
foco_plot_path = None
|
| 391 |
-
if SALIENCY_AVAILABLE:
|
| 392 |
-
progress(0.6, desc="Analisando foco m贸vel...")
|
| 393 |
-
ssim_foco, jitter_foco = analisar_estabilidade_foco(frames)
|
| 394 |
-
foco_plot_path = "foco.png" # Placeholder
|
| 395 |
-
|
| 396 |
-
semantico_path = None
|
| 397 |
-
if CLIP_AVAILABLE and descriptions_text.strip():
|
| 398 |
-
progress(0.8, desc="Executando teste sem芒ntico...")
|
| 399 |
-
semantico_path, error_msg = executar_teste_semantico(phash_distances, descriptions_text)
|
| 400 |
-
if error_msg: gr.Warning(error_msg)
|
| 401 |
-
|
| 402 |
-
return fidelidade_plot_path, cor_plot_path, foco_plot_path, semantico_path, anomalias_plot_path
|
| 403 |
-
|
| 404 |
-
# --- INTERFACE GRADIO ---
|
| 405 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 406 |
-
gr.Markdown("# Su铆te de Valida莽茫o Completa para Gera莽茫o de V铆deo (ADUC-SDR)")
|
| 407 |
-
with gr.Row():
|
| 408 |
-
with gr.Column(scale=1):
|
| 409 |
-
video_input = gr.Video(label="1. Upload do v铆deo")
|
| 410 |
-
descriptions_input = gr.Textbox(lines=5, label="2. Descri莽玫es (Opcional)", placeholder="Uma descri莽茫o por cena...")
|
| 411 |
-
analyze_button = gr.Button("3. Executar An谩lise Completa", variant="primary")
|
| 412 |
-
with gr.Tabs():
|
| 413 |
-
with gr.TabItem("1. Fidelidade e Coer锚ncia"):
|
| 414 |
-
plot_fidelidade = gr.Image(label="Gr谩fico de An谩lise de Fidelidade (SSIM e pHash)")
|
| 415 |
-
with gr.TabItem("2. Cor e Ilumina莽茫o"):
|
| 416 |
-
plot_cor = gr.Image(label="Gr谩fico de An谩lise de Cor e Lumin芒ncia")
|
| 417 |
-
with gr.TabItem("3. Foco (V铆deo M贸vel)"):
|
| 418 |
-
plot_foco = gr.Image(label="Gr谩fico de An谩lise de Foco e Jitter")
|
| 419 |
-
with gr.TabItem("4. Glitches de Movimento"):
|
| 420 |
-
plot_anomalias = gr.Image(label="Gr谩fico do Detector de Anomalias de Movimento")
|
| 421 |
-
with gr.TabItem("5. Intelig锚ncia Adaptativa"):
|
| 422 |
-
plot_semantico = gr.Image(label="Gr谩fico de Estresse Sem芒ntico")
|
| 423 |
-
|
| 424 |
-
analyze_button.click(
|
| 425 |
-
fn=run_full_analysis,
|
| 426 |
-
inputs=[video_input, descriptions_input],
|
| 427 |
-
outputs=[plot_fidelidade, plot_cor, plot_foco, plot_semantico, plot_anomalias]
|
| 428 |
-
)
|
| 429 |
-
|
| 430 |
if __name__ == "__main__":
|
| 431 |
demo.queue().launch()
|
|
|
|
| 232 |
outputs=[plot_fidelidade, plot_cor, plot_foco, plot_semantico, plot_anomalias]
|
| 233 |
)
|
| 234 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
if __name__ == "__main__":
|
| 236 |
demo.queue().launch()
|