Refactor of all annotating things.
This commit is contained in:
+10
-92
@@ -136,11 +136,7 @@ def detect_checks_and_notes(output_dir):
|
||||
|
||||
notes.putalpha(Image.fromarray(final_alpha))
|
||||
|
||||
# Debuging : Issues
|
||||
# - The artifacts increase as we go lower in the image
|
||||
# - Tous les rectangles sont présents
|
||||
# -
|
||||
notes.show()
|
||||
# notes.show()
|
||||
|
||||
return actions, notes
|
||||
|
||||
@@ -172,7 +168,6 @@ def apply_actions_and_regenerate(root_dir, data, student_id, actions, notes_laye
|
||||
actions_by_label[l].append(a)
|
||||
|
||||
for label, acts in sorted(actions_by_label.items(), key=lambda x: natural_key(x[0])):
|
||||
# print(label)
|
||||
if label not in labels: continue
|
||||
|
||||
content = labels[label]
|
||||
@@ -222,91 +217,22 @@ def apply_actions_and_regenerate(root_dir, data, student_id, actions, notes_laye
|
||||
# We use a temporary modified dictionary
|
||||
temp_data = {student_id: labels}
|
||||
|
||||
# Run the original process (but we need to intercept it to not save, or just let it save)
|
||||
|
||||
# Hijack the output dir in logic or copy code?
|
||||
# Let's just implement the rendering loop here to be safe and clean,
|
||||
# overlaying the notes at the end.
|
||||
|
||||
output_dir = os.path.join(root_dir, "Bnot", f"Copie{student_id}")
|
||||
|
||||
# ... (Reuse rendering logic from annotating.py exactly) ...
|
||||
# See below for condensed integration
|
||||
|
||||
final_concats = []
|
||||
|
||||
for label, content in sorted(labels.items(), key=lambda x: natural_key(x[0])):
|
||||
sorted_labels = sorted(labels.items(), key=lambda x: natural_key(x[0]))
|
||||
for label, content in sorted_labels:
|
||||
# ... [PDF to Image Conversion] ...
|
||||
copie_folder = f"Copie{student_id}"
|
||||
pdf_path = os.path.join(root_dir, copie_folder, f"{label}.pdf")
|
||||
if not os.path.exists(pdf_path): continue
|
||||
|
||||
(base_img, total_h, max_w) = annotating.make_base_image(pdf_path)
|
||||
(base_img, _total_h, _max_w) = annotating.make_base_image(pdf_path)
|
||||
img = annotating.compose_label_image(
|
||||
base_img, label, content['result'], content['coordinates'][0]
|
||||
)
|
||||
|
||||
# ... [Draw Header/Margin (Clean)] ...
|
||||
margin_left = MARGIN_LEFT
|
||||
result = content['result']
|
||||
coordinates = content.get('coordinates', (0,0))
|
||||
hmin = coordinates[0]
|
||||
|
||||
score_text = f"{label} ; Note : {result.get('score', 0)}"
|
||||
if result.get('error') and result.get('error') != "null": score_text += f" | Error: {result.get('error')}"
|
||||
|
||||
header_imgs = [(annotating.render_latex_text(score_text, base_img.width, fontsize=18), True)]
|
||||
|
||||
feedbacks = result.get('feedback', [])
|
||||
# Separate again (now cleaned)
|
||||
global_fb = [f for f in feedbacks if not f.get('box_2d')]
|
||||
local_fb = [f for f in feedbacks if f.get('box_2d')]
|
||||
local_fb.sort(key=lambda x: x['box_2d'][0])
|
||||
|
||||
for fb in global_fb:
|
||||
render = annotating.render_latex_text(fb['text'], base_img.width)
|
||||
header_imgs.append((render, "to_delete" not in fb))
|
||||
|
||||
total_h = base_img.height + sum(i.height for (i,_) in header_imgs)
|
||||
label_img = Image.new("RGB", (base_img.width + margin_left, total_h), "white")
|
||||
|
||||
cy = 0
|
||||
for (i, keep) in header_imgs:
|
||||
if keep:
|
||||
label_img.paste(i, (0, cy))
|
||||
else:
|
||||
blank = Image.new("RGB", (i.width, i.height), "white")
|
||||
label_img.paste(blank, (0, cy))
|
||||
cy+=i.height
|
||||
img_offset_y = cy
|
||||
label_img.paste(base_img, (margin_left, img_offset_y))
|
||||
|
||||
draw = ImageDraw.Draw(label_img, "RGBA")
|
||||
last_bot = 0
|
||||
for fb in local_fb:
|
||||
box = fb['box_2d']
|
||||
|
||||
ymin, xmin, ymax, xmax = box
|
||||
t_ymin = (ymin - hmin) + img_offset_y
|
||||
t_ymax = (ymax - hmin) + img_offset_y
|
||||
if "norectangle" not in fb:
|
||||
draw.rectangle([xmin+margin_left, t_ymin, xmax+margin_left, t_ymax],
|
||||
outline="red", width=3)
|
||||
|
||||
txt = annotating.render_latex_text(fb['text'], ANNOT_WIDTH,
|
||||
(255,200,200,180), max_lines=3)
|
||||
py = max((t_ymin+t_ymax)/2 - txt.height/2, img_offset_y)
|
||||
if py < last_bot:
|
||||
py = last_bot + 5
|
||||
|
||||
if py + txt.height + 20 > label_img.height:
|
||||
new_l = Image.new("RGB", (label_img.width, int(py+txt.height+20)), "white")
|
||||
new_l.paste(label_img, (0,0))
|
||||
label_img = new_l
|
||||
draw = ImageDraw.Draw(label_img, "RGBA")
|
||||
|
||||
if not "to_delete" in fb:
|
||||
label_img.paste(txt, (10, int(py)), mask=txt)
|
||||
last_bot = py + txt.height
|
||||
|
||||
final_concats.append(label_img)
|
||||
final_concats.append(img)
|
||||
|
||||
# Concatenate Labels
|
||||
if not final_concats: return
|
||||
@@ -321,19 +247,11 @@ def apply_actions_and_regenerate(root_dir, data, student_id, actions, notes_laye
|
||||
|
||||
# 3. Overlay Manual Notes
|
||||
if notes_layer:
|
||||
# Notes layer might be different size if regenerated image size changed (e.g. deleted comments reduced height)
|
||||
# However, usually reducing content reduces height, so we align top-left.
|
||||
# But `notes_layer` is based on the "Reference.png" which had boxes.
|
||||
# The new `full_clean_img` does NOT have boxes. The dimensions should be identical
|
||||
# unless removing a feedback at the very bottom shrinks the image.
|
||||
|
||||
# We paste notes_layer on top.
|
||||
full_clean_img.paste(notes_layer, (0,0), mask=notes_layer)
|
||||
|
||||
# Save final Concat.jpg
|
||||
final_path = os.path.join(output_dir, "Concat.jpg")
|
||||
full_clean_img.save(final_path)
|
||||
print(f"Saved regenerated: {final_path}")
|
||||
full_clean_img.save(os.path.join(output_dir, "Concat.jpg"))
|
||||
print(f"Saved regenerated: {os.path.join(output_dir, 'Concat.jpg')}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
|
||||
Reference in New Issue
Block a user