creek

The AI Image Editor of 2030

typography.py (2468B)


"""
Typography
Original file: https://colab.research.google.com/drive/11sdpsNaYwetetOotIX3GKtxgaQOt7S0Y
"""

!pip install easyocr -q

import numpy as np
from PIL import Image
import easyocr
import pickle
import os
import json
from tensorflow.keras.models import model_from_json, Model
from tensorflow.keras.utils import get_custom_objects

TEST_IMAGE_PATH = "test image.png"
MODEL_JSON = "fannet.json"
MODEL_WEIGHTS = "fannet_weights.h5"
FONT_DB_PKL = "font_database.pkl"

if os.path.exists(FONT_DB_PKL) and os.path.exists(MODEL_JSON):
    with open(FONT_DB_PKL, "rb") as f:
        font_db = pickle.load(f)

    get_custom_objects()["Model"] = Model

    with open(MODEL_JSON, "r") as f:
        model_json_content = f.read()

    fannet_model = model_from_json(model_json_content)
    fannet_model.load_weights(MODEL_WEIGHTS)

    encoder = Model(
        inputs=fannet_model.input, outputs=fannet_model.get_layer("dense_1").output
    )
    reader = easyocr.Reader(["en"], gpu=True)

    img_pil = Image.open(TEST_IMAGE_PATH)
    detections = reader.readtext(TEST_IMAGE_PATH)

    print(f"{'TEXT':<20} | {'PREDICTED FONT':<25} | {'CONFIDENCE'}")
    print("-" * 65)

    for bbox, text, conf in detections:
        tl, tr, br, bl = bbox
        x_min = max(0, int(min(tl[0], bl[0])))
        y_min = max(0, int(min(tl[1], tr[1])))
        x_max = min(img_pil.width, int(max(tr[0], br[0])))
        y_max = min(img_pil.height, int(max(bl[1], br[1])))

        if x_max - x_min > 5 and y_max - y_min > 5:
            crop = img_pil.crop((x_min, y_min, x_max, y_max))

            img = crop.convert("L").resize((64, 64), Image.LANCZOS)
            arr = np.array(img, dtype=np.float32)
            arr = (arr < np.mean(arr)).astype(np.float32)
            processed = np.expand_dims(arr, axis=(0, -1))

            dummy_char = np.zeros((1, 26, 1))
            features = encoder.predict([processed, dummy_char], verbose=0)[0]

            best_font = "Unknown"
            min_dist = float("inf")

            for name, db_feat in font_db.items():
                dist = np.linalg.norm(features - db_feat)
                if dist < min_dist:
                    min_dist = dist
                    best_font = name

            font_conf = 1.0 / (1.0 + min_dist)
            print(f"{text:<20} | {best_font:<25} | {font_conf:.4f}")
else:
    print(
        "Files not found. Please upload test image.png, fannet.json, fannet_weights.h5, and font_database.pkl"
    )