Team Ai
Apppublic

PitGlobal/PDF_Layout_Inspector

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
predict_pdf.py120 linesDownload Raw Back to overlap_embedding_pipeline
1from __future__ import annotations2 3import argparse4import csv5import json6from pathlib import Path7import sys8 9 10LOCAL_DEPS = Path(__file__).resolve().parent / ".deps"11 12try:13    import cv214    import numpy as np15except ImportError:16    if LOCAL_DEPS.exists():17        sys.path.insert(0, str(LOCAL_DEPS))18    import cv219    import numpy as np20 21from box_source import draw_boxes, extract_boxes_from_pdf22from features import crop_box, preprocess_text_mask_fine, structural_embedding23from model import SimilarityModel, load_model_artifact24 25INPUT_PDF_PATH = Path(r"C:\Users\39334\Desktop\George!\2_Milestone\altri_file_da_testare\book3.pdf")26 27ROOT_DIR = Path(__file__).resolve().parent28ARTIFACTS_DIR = ROOT_DIR / "artifacts"29MODEL_INPUT = ARTIFACTS_DIR / "dataset" / "embeddings_dataset.npz"30MODEL_ARTIFACT = ARTIFACTS_DIR / "models" / "logistic_regression_model.npz"31PRED_DIR = ARTIFACTS_DIR / "predictions"32 33 34def load_model(npz_path: Path, model_path: Path | None = None):35    if model_path and model_path.exists():36        return load_model_artifact(model_path)37 38    data = np.load(npz_path, allow_pickle=True)39    embeddings = data["embeddings"].astype(np.float32)40    labels = data["labels"].astype(np.int32)41    return SimilarityModel.from_arrays(embeddings, labels)42 43 44def predict_pdf(pdf_path: str | Path, out_dir: str | Path | None = None):45    pdf_path = Path(pdf_path)46    out_dir = Path(out_dir) if out_dir else (PRED_DIR / pdf_path.stem)47    out_dir.mkdir(parents=True, exist_ok=True)48 49    image, _mask, boxes = extract_boxes_from_pdf(pdf_path)50    fine_mask = preprocess_text_mask_fine(image)51    model = load_model(MODEL_INPUT, MODEL_ARTIFACT)52 53    predictions = []54    bad_ids: set[int] = set()55 56    for idx, box in enumerate(boxes, start=1):57        mask_crop = crop_box(fine_mask, box, pad=2)58        embedding, debug = structural_embedding(mask_crop)59        scores = model.predict_scores(embedding)60 61        if scores["label"] == "bad_overlap":62            bad_ids.add(idx)63 64        x1, y1, x2, y2 = box65        predictions.append(66            {67                "line_id": idx,68                "x1": x1,69                "y1": y1,70                "x2": x2,71                "y2": y2,72                "w": x2 - x1,73                "h": y2 - y1,74                "predicted_label": scores["label"],75                "score_good": round(float(scores["score_good"]), 6),76                "score_bad": round(float(scores["score_bad"]), 6),77                "margin": round(float(scores["margin"]), 6),78                "band_count": round(float(debug["band_count"]), 4),79                "band_gap": round(float(debug["band_gap"]), 4),80                "char_count": round(float(debug["char_count"]), 4),81                "tall_char_count": round(float(debug["tall_char_count"]), 4),82                "wide_char_count": round(float(debug["wide_char_count"]), 4),83                "max_cy_gap": round(float(debug["max_cy_gap"]), 4),84            }85        )86 87    result = draw_boxes(image, boxes, bad_ids=bad_ids)88    cv2.imwrite(str(out_dir / f"{pdf_path.stem}_prediction.png"), result)89 90    with open(out_dir / f"{pdf_path.stem}_prediction.json", "w", encoding="utf-8") as f:91        json.dump(predictions, f, indent=2)92 93    with open(out_dir / f"{pdf_path.stem}_prediction.csv", "w", newline="", encoding="utf-8") as f:94        writer = csv.DictWriter(f, fieldnames=list(predictions[0].keys()) if predictions else ["line_id"])95        writer.writeheader()96        writer.writerows(predictions)97 98    print(f"[OK] PDF: {pdf_path}")99    print(f"[OK] Box totali: {len(boxes)}")100    print(f"[OK] Box predetti bad_overlap: {sorted(bad_ids)}")101    print(f"[OK] Output dir: {out_dir}")102    return predictions103 104 105def main():106    parser = argparse.ArgumentParser(description="Predice i box con sovrapposizione su un PDF.")107    parser.add_argument(108        "pdf_path",109        nargs="?",110        default=str(INPUT_PDF_PATH),111        help=f"Percorso del PDF da analizzare (default: {INPUT_PDF_PATH})",112    )113    parser.add_argument("--out-dir", default=None, help="Cartella di output")114    args = parser.parse_args()115    predict_pdf(args.pdf_path, args.out_dir)116 117 118if __name__ == "__main__":119    main()120