Update app.py
Browse files
app.py
CHANGED
|
@@ -637,13 +637,16 @@ def process_photos_quality_selection(job_id, upload_dir, quality_mode, similarit
|
|
| 637 |
stat['categories'] = cat_breakdown
|
| 638 |
|
| 639 |
# Step 6: Build rejected list (photos not selected)
|
|
|
|
| 640 |
selected_filenames = {p['filename'] for p in selected_photos}
|
| 641 |
rejected_photos = []
|
| 642 |
|
| 643 |
for month, photos in photos_by_month.items():
|
| 644 |
for photo in photos:
|
| 645 |
if photo['filename'] not in selected_filenames:
|
| 646 |
-
|
|
|
|
|
|
|
| 647 |
rejected_photos.append(photo)
|
| 648 |
|
| 649 |
# Create thumbnails directory
|
|
@@ -756,9 +759,21 @@ def process_photos_quality_selection(job_id, upload_dir, quality_mode, similarit
|
|
| 756 |
if thumbnails_created % 10 == 0 or thumbnails_created == total_thumbnails:
|
| 757 |
processing_jobs[job_id]['message'] = f'Creating thumbnails: {thumbnails_created}/{total_thumbnails}'
|
| 758 |
|
| 759 |
-
#
|
| 760 |
-
|
| 761 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 762 |
|
| 763 |
# Get embedding for this photo (convert to list for JSON serialization)
|
| 764 |
photo_embedding = embeddings.get(filename)
|
|
@@ -785,7 +800,8 @@ def process_photos_quality_selection(job_id, upload_dir, quality_mode, similarit
|
|
| 785 |
'event_id': photo.get('event_id', -1),
|
| 786 |
'max_similarity': float(photo.get('max_similarity', 0)),
|
| 787 |
'embedding': embedding_list,
|
| 788 |
-
'
|
|
|
|
| 789 |
'reason_detail': f"Category: {photo.get('category', 'unknown')}"
|
| 790 |
})
|
| 791 |
|
|
@@ -814,11 +830,11 @@ def process_photos_quality_selection(job_id, upload_dir, quality_mode, similarit
|
|
| 814 |
print(f" {stat['month']}: {stat['selected']}/{stat['total_photos']} ({stat['category_summary']})")
|
| 815 |
print(f"{'='*60}\n")
|
| 816 |
|
| 817 |
-
# Auto-save
|
| 818 |
-
output_folder = save_photos_by_month(job_id, upload_dir, selected_photos, rejected_photos, month_stats)
|
| 819 |
-
if output_folder:
|
| 820 |
-
|
| 821 |
-
|
| 822 |
|
| 823 |
except Exception as e:
|
| 824 |
print(f"[Job {job_id}] EXCEPTION: {str(e)}")
|
|
@@ -3271,6 +3287,7 @@ def finish_chunked_upload(dataset_name):
|
|
| 3271 |
@app.route('/process_reupload/<dataset_name>', methods=['POST'])
|
| 3272 |
def process_reupload(dataset_name):
|
| 3273 |
"""Process re-uploaded photos using saved face results from Supabase."""
|
|
|
|
| 3274 |
try:
|
| 3275 |
print(f"[Reupload] Starting reupload for dataset '{dataset_name}'")
|
| 3276 |
|
|
@@ -3427,6 +3444,9 @@ def process_reupload(dataset_name):
|
|
| 3427 |
'redirect_url': f'/step3_review/{job_id}'
|
| 3428 |
})
|
| 3429 |
|
|
|
|
|
|
|
|
|
|
| 3430 |
except Exception as e:
|
| 3431 |
import traceback
|
| 3432 |
traceback.print_exc()
|
|
@@ -3448,4 +3468,4 @@ if __name__ == '__main__':
|
|
| 3448 |
# Use port 7860 for Hugging Face Spaces, 5000 for local
|
| 3449 |
import os
|
| 3450 |
port = int(os.environ.get('PORT', 7860))
|
| 3451 |
-
app.run(debug=False, host='0.0.0.0', port=port)
|
|
|
|
| 637 |
stat['categories'] = cat_breakdown
|
| 638 |
|
| 639 |
# Step 6: Build rejected list (photos not selected)
|
| 640 |
+
# Note: rejection_reason is already set by monthly_selector.py
|
| 641 |
selected_filenames = {p['filename'] for p in selected_photos}
|
| 642 |
rejected_photos = []
|
| 643 |
|
| 644 |
for month, photos in photos_by_month.items():
|
| 645 |
for photo in photos:
|
| 646 |
if photo['filename'] not in selected_filenames:
|
| 647 |
+
# Keep existing rejection_reason from monthly_selector, or set default
|
| 648 |
+
if not photo.get('rejection_reason'):
|
| 649 |
+
photo['rejection_reason'] = 'Not selected for month quota'
|
| 650 |
rejected_photos.append(photo)
|
| 651 |
|
| 652 |
# Create thumbnails directory
|
|
|
|
| 759 |
if thumbnails_created % 10 == 0 or thumbnails_created == total_thumbnails:
|
| 760 |
processing_jobs[job_id]['message'] = f'Creating thumbnails: {thumbnails_created}/{total_thumbnails}'
|
| 761 |
|
| 762 |
+
# Use actual rejection reason from monthly_selector
|
| 763 |
+
rejection_reason = photo.get('rejection_reason', 'Better photos selected')
|
| 764 |
+
|
| 765 |
+
# Categorize rejection reasons for breakdown chart
|
| 766 |
+
if 'Event' in rejection_reason:
|
| 767 |
+
breakdown_category = "Same event"
|
| 768 |
+
elif 'Cluster' in rejection_reason:
|
| 769 |
+
breakdown_category = "Same cluster"
|
| 770 |
+
elif 'similar' in rejection_reason.lower():
|
| 771 |
+
breakdown_category = "Too similar"
|
| 772 |
+
elif 'Target' in rejection_reason:
|
| 773 |
+
breakdown_category = "Target reached"
|
| 774 |
+
else:
|
| 775 |
+
breakdown_category = "Other"
|
| 776 |
+
rejection_counts[breakdown_category] += 1
|
| 777 |
|
| 778 |
# Get embedding for this photo (convert to list for JSON serialization)
|
| 779 |
photo_embedding = embeddings.get(filename)
|
|
|
|
| 800 |
'event_id': photo.get('event_id', -1),
|
| 801 |
'max_similarity': float(photo.get('max_similarity', 0)),
|
| 802 |
'embedding': embedding_list,
|
| 803 |
+
'rejection_reason': rejection_reason,
|
| 804 |
+
'reason': rejection_reason,
|
| 805 |
'reason_detail': f"Category: {photo.get('category', 'unknown')}"
|
| 806 |
})
|
| 807 |
|
|
|
|
| 830 |
print(f" {stat['month']}: {stat['selected']}/{stat['total_photos']} ({stat['category_summary']})")
|
| 831 |
print(f"{'='*60}\n")
|
| 832 |
|
| 833 |
+
# Auto-save disabled - uncomment below to re-enable
|
| 834 |
+
# output_folder = save_photos_by_month(job_id, upload_dir, selected_photos, rejected_photos, month_stats)
|
| 835 |
+
# if output_folder:
|
| 836 |
+
# processing_jobs[job_id]['output_folder'] = output_folder
|
| 837 |
+
# print(f"[Job {job_id}] Photos auto-saved to: {output_folder}")
|
| 838 |
|
| 839 |
except Exception as e:
|
| 840 |
print(f"[Job {job_id}] EXCEPTION: {str(e)}")
|
|
|
|
| 3287 |
@app.route('/process_reupload/<dataset_name>', methods=['POST'])
|
| 3288 |
def process_reupload(dataset_name):
|
| 3289 |
"""Process re-uploaded photos using saved face results from Supabase."""
|
| 3290 |
+
from werkzeug.exceptions import ClientDisconnected
|
| 3291 |
try:
|
| 3292 |
print(f"[Reupload] Starting reupload for dataset '{dataset_name}'")
|
| 3293 |
|
|
|
|
| 3444 |
'redirect_url': f'/step3_review/{job_id}'
|
| 3445 |
})
|
| 3446 |
|
| 3447 |
+
except ClientDisconnected:
|
| 3448 |
+
print(f"[Reupload] Client disconnected during upload (timeout)")
|
| 3449 |
+
return jsonify({'error': 'Connection timeout - please retry with smaller batch or better connection'}), 408
|
| 3450 |
except Exception as e:
|
| 3451 |
import traceback
|
| 3452 |
traceback.print_exc()
|
|
|
|
| 3468 |
# Use port 7860 for Hugging Face Spaces, 5000 for local
|
| 3469 |
import os
|
| 3470 |
port = int(os.environ.get('PORT', 7860))
|
| 3471 |
+
app.run(debug=False, host='0.0.0.0', port=port)
|