Make reading grouped annotations faster.
parent
a658cb72e0
commit
d288daecd1
|
|
@ -42,7 +42,7 @@ def process_images(base_dir):
|
|||
print(f"Error: Directory '{search_path}' not found.")
|
||||
sys.exit(1)
|
||||
|
||||
for img_path in search_path.glob("*/*.jpg"):
|
||||
for img_path in sorted(search_path.glob("*/*.jpg")):
|
||||
student_name = img_path.stem # Filename without extension
|
||||
|
||||
# 4. Find Score
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import sys
|
|||
import os
|
||||
import json
|
||||
import collections
|
||||
import concurrent.futures
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
|
||||
|
|
@ -14,7 +15,9 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
|||
Modifies data based on actions, pastes label-specific note crops,
|
||||
regenerates label images for consistency, saves dirty ones,
|
||||
and generates Concat.jpg in the BGnot/Copie{id} directory.
|
||||
Returns a string of accumulated log messages.
|
||||
"""
|
||||
logs = [f"\nProcessing compilation for: Copie{student_id}"]
|
||||
output_dir = os.path.join(root_dir, "BGnot", f"Copie{student_id}")
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
|
|
@ -44,23 +47,23 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
|||
if act['type'] == 'score':
|
||||
result['score'] = act['value']
|
||||
dirty_labels.add(label)
|
||||
print(f" > Updated score for {label} to {act['value']}")
|
||||
logs.append(f" > Updated score for {label} to {act['value']}")
|
||||
|
||||
elif act['type'] == 'del_global':
|
||||
if act['index'] < len(global_fb):
|
||||
global_fb[act['index']]["to_delete"] = True
|
||||
dirty_labels.add(label)
|
||||
print(f" > Deleted global feedback in {label}")
|
||||
logs.append(f" > Deleted global feedback in {label}")
|
||||
|
||||
elif act['type'] in ('del_local', 'del_local_rect'):
|
||||
if act['index'] < len(local_fb):
|
||||
target = local_fb[act['index']]
|
||||
if act['type'] == 'del_local':
|
||||
target["to_delete"] = True
|
||||
print(f" > Deleted local feedback in {label}")
|
||||
logs.append(f" > Deleted local feedback in {label}")
|
||||
else:
|
||||
target["norectangle"] = True
|
||||
print(f" > Deleted rect in {label}")
|
||||
logs.append(f" > Deleted rect in {label}")
|
||||
dirty_labels.add(label)
|
||||
|
||||
# --- 2. Process Images (Regenerate & Concatenate) ---
|
||||
|
|
@ -113,7 +116,7 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
|||
if (label in dirty_labels) or has_notes:
|
||||
save_path = os.path.join(output_dir, f"{label}.jpg")
|
||||
final_img.save(save_path)
|
||||
print(f" Saved dirty image: {label}.jpg")
|
||||
logs.append(f" Saved dirty image: {label}.jpg")
|
||||
|
||||
concat_list.append(final_img)
|
||||
|
||||
|
|
@ -126,11 +129,10 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
|||
if not perfect_no_comment:
|
||||
concat_list_F.append(final_img)
|
||||
|
||||
|
||||
# --- 3. Save Final Outputs ---
|
||||
with open(score_path, "w") as f:
|
||||
json.dump(d_notes, f, indent=4)
|
||||
print(f" Saved {score_path}")
|
||||
logs.append(f" Saved {score_path}")
|
||||
|
||||
if concat_list:
|
||||
max_w = max(i.width for i in concat_list)
|
||||
|
|
@ -143,7 +145,8 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
|||
y += img.height
|
||||
|
||||
full_img.save(os.path.join(output_dir, "Concat.jpg"))
|
||||
print(f" Saved regenerated Concat.jpg")
|
||||
logs.append(f" Saved regenerated Concat.jpg")
|
||||
|
||||
if concat_list_F:
|
||||
max_w = max(i.width for i in concat_list_F)
|
||||
total_h = sum(i.height for i in concat_list_F)
|
||||
|
|
@ -155,7 +158,9 @@ def apply_actions_and_regenerate_grouped(root_dir, data, student_id, actions, la
|
|||
y += img.height
|
||||
|
||||
full_img.save(os.path.join(output_dir, "Concat_F.jpg"))
|
||||
print(f" Saved regenerated Concat_F.jpg")
|
||||
logs.append(f" Saved regenerated Concat_F.jpg")
|
||||
|
||||
return "\n".join(logs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
@ -223,20 +228,10 @@ if __name__ == "__main__":
|
|||
'old_header_h': img_info.get("header_height", 0)
|
||||
}
|
||||
|
||||
# --- 2. Dispatch data back to students and regenerate ---
|
||||
# affected_students = set(actions_by_student.keys()).union(set(notes_by_student.keys()))
|
||||
|
||||
# if not affected_students:
|
||||
# print("\nNo changes detected in any grouped annotations.")
|
||||
# sys.exit(0)
|
||||
|
||||
# for sid in sorted(affected_students, key=natural_key):
|
||||
for sid in sorted(original_data.keys(), key=natural_key):
|
||||
def process_student(sid):
|
||||
if sid not in original_data:
|
||||
continue
|
||||
|
||||
print(f"\nProcessing compilation for: Copie{sid}")
|
||||
apply_actions_and_regenerate_grouped(
|
||||
return ""
|
||||
return apply_actions_and_regenerate_grouped(
|
||||
root_dir,
|
||||
original_data,
|
||||
sid,
|
||||
|
|
@ -244,3 +239,12 @@ if __name__ == "__main__":
|
|||
notes_by_student[sid],
|
||||
all_labels
|
||||
)
|
||||
|
||||
# --- 2. Process each student concurrently using 4 threads ---
|
||||
sids = sorted(original_data.keys(), key=natural_key)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
|
||||
futures = {executor.submit(process_student, sid): sid for sid in sids}
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
output = future.result()
|
||||
if output:
|
||||
print(output)
|
||||
|
|
|
|||
Loading…
Reference in New Issue