pull down to refresh

It crashed.

It wrote this python script tho:

#!/usr/bin/env python3
"""
Detailed glyph-level comparison.
Render specific phrases in each candidate font, blur to match scan softness,
resize to original dimensions, compute per-pixel MSE, and produce a side-by-side grid.
"""
from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageChops, ImageOps
import os, math

orig = Image.open("/home/user/uploads/scan.png").convert("L")
# Crop the text region roughly (with some margin) - exclude off-white paper background edges
ORIG_CROP = orig.crop((10, 5, 855, 365))
W,H = ORIG_CROP.size
print("Original crop size:", W, H)

# 7 lines, each ~52px tall
LINES = [
    "At the very outset of the investigation telegrams",
    "went to all field offices of the Bureau instructing the",
    "Special Agents in Charge to take personal supervision of",
    "the investigation, to check out all leads in 24 hours, and",
    "noting that they would be held personally responsible.",
    "(HQ 44-38861-153). The files we reviewed show that this",
    "directive was conscientiously followed. The Bureau sought",
]

FONTS = [
    ("Courier New Reg", "/home/user/fonts/cour.ttf"),
    ("Courier New Bold", "/home/user/fonts/courbd.ttf"),
    ("Courier Prime Reg", "/home/user/fonts/CourierPrime.ttf"),
    ("Courier Prime Bold", "/home/user/fonts/CourierPrime-Bold.ttf"),
    ("Special Elite", "/home/user/fonts/SpecialElite.ttf"),
    ("IBM Plex Mono", "/home/user/fonts/IBMPlexMono.ttf"),
    ("1942 Report", "/home/user/fonts/1942.ttf"),
    ("Cutive Mono", "/home/user/fonts/CutiveMono.ttf"),
    ("Old Typewriter 2.0", "/home/user/fonts/old_tw_dir/Old Typewriter2.0.ttf"),
    ("Ubuntu Mono Bold", "/home/user/fonts/UbuntuMono-B.ttf"),
    ("Nimbus Mono Reg", "/home/user/fonts/NimbusMono-Regular.otf"),
    ("Nimbus Mono Bold", "/home/user/fonts/NimbusMono-Bold.otf"),
    ("DejaVu Sans Mono", "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"),
    ("DejaVu Sans Mono Bd", "/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf"),
]

def render_font(path, size, leading=6, margin_left=20, margin_top=15, inkspread=0, blur=0.0):
    try:
        font = ImageFont.truetype(path, size)
    except Exception as e:
        return None
    # measure line heights
    img_tmp = Image.new("L",(10,10),255)
    d = ImageDraw.Draw(img_tmp)
    heights=[]
    widths=[]
    for ln in LINES:
        bb = d.textbbox((0,0), ln, font=font)
        heights.append(bb[3]-bb[1])
        widths.append(bb[2]-bb[0])
    line_h = heights[0]
    w = max(widths)+margin_left*2
    h = line_h*7 + leading*6 + margin_top*2
    img = Image.new("L",(w,h),255)
    d = ImageDraw.Draw(img)
    y = margin_top
    for i,ln in enumerate(LINES):
        d.text((margin_left, y), ln, font=font, fill=0)
        y += line_h + leading
    # ink spread (dilate)
    for _ in range(inkspread):
        img = img.filter(ImageFilter.MaxFilter(3))
    if blur > 0:
        img = img.filter(ImageFilter.GaussianBlur(radius=blur))
    return img

def mse(a,b):
    # both same size
    import numpy as np
    aa = np.asarray(a, dtype=np.float32)
    bb = np.asarray(b, dtype=np.float32)
    diff = (aa-bb)/255.0
    return float((diff*diff).mean())

# Search for best parameters per font
results = []
for name, path in FONTS:
    if not os.path.exists(path):
        continue
    best = None
    for size in range(20, 38):
        for leading in range(0, 12, 2):
            for ink in range(0, 3):
                for blur in [0.6, 0.9, 1.2, 1.5]:
                    im = render_font(path, size, leading=leading, inkspread=ink, blur=blur)
                    if im is None: continue
                    im2 = im.resize((W,H), Image.LANCZOS)
                    e = mse(im2, ORIG_CROP)
                    if best is None or e < best[0]:
                        best = (e, size, leading, ink, blur, im2)
    results.append((best[0], name, best[1:]))
    print(f"{name:28s}  MSE={best[0]:.4f}  size={best[1]} leading={best[2]} ink={best[3]} blur={best[4]}")

results.sort()
print("\n=== Ranking (lower MSE = better match) ===")
for e, name, _ in results:
    print(f"  {name:28s}  MSE={e:.4f}")

# Build side-by-side comparison of the top 6 + original
TOP_N = 8
strips = []
lab_h = 30
# Add original
strip = Image.new("RGB",(W*2+6, H+lab_h+8),(220,220,220))
d = ImageDraw.Draw(strip)
d.text((10,5), "ORIGINAL", fill=(0,0,180))
strip.paste(Image.merge("RGB",(ORIG_CROP,ORIG_CROP,ORIG_CROP)),(2,lab_h+4))
strips.append(("ORIGINAL", strip))

for e, name, (size, leading, ink, blur, im2) in results[:TOP_N]:
    strip = Image.new("RGB",(W*2+6, H+lab_h+8),(220,220,220))
    d = ImageDraw.Draw(strip)
    d.text((10,5), f"{name}   sz={size} lead={leading} ink={ink} blur={blur}  MSE={e:.4f}", fill=(150,0,0))
    # Left: rendered; Right: side-by-side diff overlay
    rrgb = Image.merge("RGB",(im2,im2,im2))
    strip.paste(rrgb,(2,lab_h+4))
    # diff
    diff = ImageChops.difference(im2, ORIG_CROP)
    # colorize diff: red channel where diff
    diff_rgb = Image.merge("RGB",(diff, Image.new("L",diff.size,255), Image.new("L",diff.size,255)))
    strip.paste(diff_rgb,(W+4,lab_h+4))
    strips.append((name, strip))

WW = W*2+6
HH = sum(s.height+6 for _,s in strips)
out = Image.new("RGB",(WW,HH),(180,180,180))
y=0
for _,s in strips:
    out.paste(s,(0,y)); y+=s.height+6
out.save("/home/user/comparison3.png")
print("Saved comparison3.png", out.size)

# Also save best match image separately
best_err, best_name, best_params = results[0]
best_size, best_lead, best_ink, best_blur, best_im = best_params
print(f"\n==> Best match: {best_name} (MSE={best_err:.4f})")

GIving that to the next agent will probably speed it up... iterations... ugh

shouldn't it be something NOT complicated?

reply

Depends. If you want it to lie to you, you ask "whats this" and it will say something random. If you tell it to do a little bit more work, it will go all out forensics and get to the bottom of it.

I personally prefer to be sure of things.

reply

I used the font the agent suggested, it's actually not bad! I'm going to print the doc out to see how it goes. 😂 almost feel like doing detective work.

reply

Exactly! Mine is rebooting itself every 10 minutes but each time it gets a little further lol

reply

yet people said they are using AI to build whatever? really? it sounds like building a castle in sand. 😂

reply

Hmm no I am just being curious if it ever ends. I could also just take the last python script, fix it myself and run it and I'll know. All the hard work has already been done but it is trying to build me an image with definite proof haha

reply

Not bad, for a bot given the impossible task to match computer fonts to a scan of typewriter text from the 1960s

reply