Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -349,7 +349,7 @@ def normalize_scores(scores):
|
|
| 349 |
return ((scores - min_score) / (max_score - min_score)) * 100
|
| 350 |
|
| 351 |
|
| 352 |
-
def plot_anomaly_scores(df, anomaly_scores, top_indices, title):
|
| 353 |
plt.figure(figsize=(16, 8), dpi=400)
|
| 354 |
fig, ax = plt.subplots(figsize=(16, 8))
|
| 355 |
|
|
@@ -363,12 +363,19 @@ def plot_anomaly_scores(df, anomaly_scores, top_indices, title):
|
|
| 363 |
seconds = df['Seconds'].values[1:]
|
| 364 |
scores = normalized_scores[1:]
|
| 365 |
|
| 366 |
-
# Create
|
| 367 |
-
ax.
|
| 368 |
|
| 369 |
# Highlight top anomalies (excluding the first data point)
|
| 370 |
top_indices = [idx for idx in top_indices if idx > 0]
|
| 371 |
-
ax.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
|
| 373 |
max_seconds = df['Seconds'].max()
|
| 374 |
ax.set_xlim(0, max_seconds)
|
|
@@ -385,8 +392,7 @@ def plot_anomaly_scores(df, anomaly_scores, top_indices, title):
|
|
| 385 |
plt.tight_layout()
|
| 386 |
return fig
|
| 387 |
|
| 388 |
-
|
| 389 |
-
def plot_emotion(df, emotion, anomaly_scores, top_indices, num_anomalies, color):
|
| 390 |
plt.figure(figsize=(16, 8), dpi=400)
|
| 391 |
fig, ax = plt.subplots(figsize=(16, 8))
|
| 392 |
|
|
@@ -397,12 +403,19 @@ def plot_emotion(df, emotion, anomaly_scores, top_indices, num_anomalies, color)
|
|
| 397 |
seconds = df['Seconds'].values[1:]
|
| 398 |
scores = anomaly_scores[1:]
|
| 399 |
|
| 400 |
-
# Create
|
| 401 |
-
ax.
|
| 402 |
|
| 403 |
# Highlight top anomalies (excluding the first data point)
|
| 404 |
top_indices = [idx for idx in top_indices if idx > 0]
|
| 405 |
-
ax.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
|
| 407 |
max_seconds = df['Seconds'].max()
|
| 408 |
ax.set_xlim(0, max_seconds)
|
|
@@ -419,7 +432,6 @@ def plot_emotion(df, emotion, anomaly_scores, top_indices, num_anomalies, color)
|
|
| 419 |
plt.tight_layout()
|
| 420 |
return fig
|
| 421 |
|
| 422 |
-
|
| 423 |
def get_random_face_samples(organized_faces_folder, output_folder):
|
| 424 |
face_samples = []
|
| 425 |
for cluster_folder in os.listdir(organized_faces_folder):
|
|
@@ -432,7 +444,7 @@ def get_random_face_samples(organized_faces_folder, output_folder):
|
|
| 432 |
output_path = os.path.join(output_folder, f"face_sample_{cluster_folder}.jpg")
|
| 433 |
face_img = cv2.imread(face_path)
|
| 434 |
if face_img is not None:
|
| 435 |
-
small_face = cv2.resize(face_img, (
|
| 436 |
cv2.imwrite(output_path, small_face)
|
| 437 |
face_samples.append(output_path)
|
| 438 |
return face_samples
|
|
@@ -514,11 +526,17 @@ def process_video(video_path, num_anomalies, num_components, desired_fps, batch_
|
|
| 514 |
|
| 515 |
progress(0.95, "Generating plots")
|
| 516 |
try:
|
| 517 |
-
anomaly_plot_all = plot_anomaly_scores(df, anomaly_scores_all, top_indices_all, "All Features"
|
| 518 |
-
|
|
|
|
|
|
|
| 519 |
emotion_plots = [
|
| 520 |
-
plot_emotion(df, emotion,
|
| 521 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 522 |
for emotion, color in zip(['fear', 'sad', 'angry', 'happy', 'surprise', 'neutral'],
|
| 523 |
['purple', 'green', 'orange', 'darkblue', 'gold', 'grey'])
|
| 524 |
]
|
|
@@ -530,11 +548,11 @@ def process_video(video_path, num_anomalies, num_components, desired_fps, batch_
|
|
| 530 |
results += f"Breakdown of persons/clusters:\n"
|
| 531 |
for cluster_id in range(num_clusters):
|
| 532 |
results += f"Person/Cluster {cluster_id + 1}: {len([c for c in clusters if c == cluster_id])} frames\n"
|
| 533 |
-
results += f"\nTop {num_anomalies} anomalies (
|
| 534 |
results += "\n".join([f"{score:.2f} at {timecode}" for score, timecode in
|
| 535 |
zip(anomaly_scores_all[top_indices_all[1:]],
|
| 536 |
df['Timecode'].iloc[top_indices_all[1:]].values)])
|
| 537 |
-
results += f"\n\nTop {num_anomalies} anomalies (
|
| 538 |
results += "\n".join([f"{score:.2f} at {timecode}" for score, timecode in
|
| 539 |
zip(anomaly_scores_comp[top_indices_comp[1:]],
|
| 540 |
df['Timecode'].iloc[top_indices_comp[1:]].values)])
|
|
|
|
| 349 |
return ((scores - min_score) / (max_score - min_score)) * 100
|
| 350 |
|
| 351 |
|
| 352 |
+
def plot_anomaly_scores(df, anomaly_scores, top_indices, title, timecodes):
|
| 353 |
plt.figure(figsize=(16, 8), dpi=400)
|
| 354 |
fig, ax = plt.subplots(figsize=(16, 8))
|
| 355 |
|
|
|
|
| 363 |
seconds = df['Seconds'].values[1:]
|
| 364 |
scores = normalized_scores[1:]
|
| 365 |
|
| 366 |
+
# Create scatter plot
|
| 367 |
+
ax.scatter(seconds, scores, color='blue', alpha=0.7, s=10)
|
| 368 |
|
| 369 |
# Highlight top anomalies (excluding the first data point)
|
| 370 |
top_indices = [idx for idx in top_indices if idx > 0]
|
| 371 |
+
ax.scatter(df['Seconds'].iloc[top_indices], normalized_scores[top_indices], color='red', s=50, zorder=5)
|
| 372 |
+
|
| 373 |
+
# Add timecode annotations
|
| 374 |
+
for idx, timecode in zip(top_indices, timecodes):
|
| 375 |
+
ax.annotate(timecode,
|
| 376 |
+
(df['Seconds'].iloc[idx], normalized_scores[idx]),
|
| 377 |
+
xytext=(5, 5), textcoords='offset points',
|
| 378 |
+
fontsize=6, color='red')
|
| 379 |
|
| 380 |
max_seconds = df['Seconds'].max()
|
| 381 |
ax.set_xlim(0, max_seconds)
|
|
|
|
| 392 |
plt.tight_layout()
|
| 393 |
return fig
|
| 394 |
|
| 395 |
+
def plot_emotion(df, emotion, anomaly_scores, top_indices, num_anomalies, color, timecodes):
|
|
|
|
| 396 |
plt.figure(figsize=(16, 8), dpi=400)
|
| 397 |
fig, ax = plt.subplots(figsize=(16, 8))
|
| 398 |
|
|
|
|
| 403 |
seconds = df['Seconds'].values[1:]
|
| 404 |
scores = anomaly_scores[1:]
|
| 405 |
|
| 406 |
+
# Create scatter plot
|
| 407 |
+
ax.scatter(seconds, scores, color=color, alpha=0.7, s=10)
|
| 408 |
|
| 409 |
# Highlight top anomalies (excluding the first data point)
|
| 410 |
top_indices = [idx for idx in top_indices if idx > 0]
|
| 411 |
+
ax.scatter(df['Seconds'].iloc[top_indices], anomaly_scores[top_indices], color='red', s=50, zorder=5)
|
| 412 |
+
|
| 413 |
+
# Add timecode annotations
|
| 414 |
+
for idx, timecode in zip(top_indices, timecodes):
|
| 415 |
+
ax.annotate(timecode,
|
| 416 |
+
(df['Seconds'].iloc[idx], anomaly_scores[idx]),
|
| 417 |
+
xytext=(5, 5), textcoords='offset points',
|
| 418 |
+
fontsize=6, color='red')
|
| 419 |
|
| 420 |
max_seconds = df['Seconds'].max()
|
| 421 |
ax.set_xlim(0, max_seconds)
|
|
|
|
| 432 |
plt.tight_layout()
|
| 433 |
return fig
|
| 434 |
|
|
|
|
| 435 |
def get_random_face_samples(organized_faces_folder, output_folder):
|
| 436 |
face_samples = []
|
| 437 |
for cluster_folder in os.listdir(organized_faces_folder):
|
|
|
|
| 444 |
output_path = os.path.join(output_folder, f"face_sample_{cluster_folder}.jpg")
|
| 445 |
face_img = cv2.imread(face_path)
|
| 446 |
if face_img is not None:
|
| 447 |
+
small_face = cv2.resize(face_img, (224, 224))
|
| 448 |
cv2.imwrite(output_path, small_face)
|
| 449 |
face_samples.append(output_path)
|
| 450 |
return face_samples
|
|
|
|
| 526 |
|
| 527 |
progress(0.95, "Generating plots")
|
| 528 |
try:
|
| 529 |
+
anomaly_plot_all = plot_anomaly_scores(df, anomaly_scores_all, top_indices_all, "All Features",
|
| 530 |
+
df['Timecode'].iloc[top_indices_all].values)
|
| 531 |
+
anomaly_plot_comp = plot_anomaly_scores(df, anomaly_scores_comp, top_indices_comp, "Components Only",
|
| 532 |
+
df['Timecode'].iloc[top_indices_comp].values)
|
| 533 |
emotion_plots = [
|
| 534 |
+
plot_emotion(df, emotion,
|
| 535 |
+
emotion_anomalies[emotion]['scores'],
|
| 536 |
+
emotion_anomalies[emotion]['indices'],
|
| 537 |
+
num_anomalies,
|
| 538 |
+
color,
|
| 539 |
+
df['Timecode'].iloc[emotion_anomalies[emotion]['indices']].values)
|
| 540 |
for emotion, color in zip(['fear', 'sad', 'angry', 'happy', 'surprise', 'neutral'],
|
| 541 |
['purple', 'green', 'orange', 'darkblue', 'gold', 'grey'])
|
| 542 |
]
|
|
|
|
| 548 |
results += f"Breakdown of persons/clusters:\n"
|
| 549 |
for cluster_id in range(num_clusters):
|
| 550 |
results += f"Person/Cluster {cluster_id + 1}: {len([c for c in clusters if c == cluster_id])} frames\n"
|
| 551 |
+
results += f"\nTop {num_anomalies} anomalies (Facial Features + Emotions):\n"
|
| 552 |
results += "\n".join([f"{score:.2f} at {timecode}" for score, timecode in
|
| 553 |
zip(anomaly_scores_all[top_indices_all[1:]],
|
| 554 |
df['Timecode'].iloc[top_indices_all[1:]].values)])
|
| 555 |
+
results += f"\n\nTop {num_anomalies} anomalies (Facial Features):\n"
|
| 556 |
results += "\n".join([f"{score:.2f} at {timecode}" for score, timecode in
|
| 557 |
zip(anomaly_scores_comp[top_indices_comp[1:]],
|
| 558 |
df['Timecode'].iloc[top_indices_comp[1:]].values)])
|