CommonForms

repository·main·Indexed 22 days ago

https://github.com/jbarrow/commonforms

A tool and Python library for automatically converting static PDF documents into fillable forms using deep learning models. It provides a CLI and a programmatic API via the prepare_form function to detect form widgets (TextBox, ChoiceButton, Signature) using models such as FFDNet-L, FFDNet-S, and FFDetr. The library includes the PyPdfFormCreator class for adding interactive elements and the FFDetrDetector and FFDNetDetector classes for widget extraction.

Tokens
4.7K
Snippets
18
Records
24
Agent score
77%

What's inside commonforms

  1. Install CommonForms

    main

    CommonForms can be installed either as a standalone CLI tool or as a library for use within an existing Python project.

    As a CLI tool (Recommended): To avoid dependency conflicts with your existing environment, it is recommended to install CommonForms in an isolated environment using uv tool or pipx. This exposes only the commonforms command.

    As a library: If you want to import CommonForms into your own Python code, install it using uv pip or pip.

    ⚠️ Warning: Because CommonForms has a large dependency footprint (including transformers, torch, rfdetr, and ultralytics) and pins specific versions, installing it into a shared or base environment may upgrade or change your existing packages like numpy, pillow, or transformers. It is highly recommended to use a dedicated virtualenv or conda environment.

    # Install as an isolated CLI tool
    uv tool install commonforms
    # or
    pipx install commonforms
    
    # Install as a library in an existing project
    uv pip install commonforms
    # or
    pip install commonforms
  2. Use the prepare_form API

    main

    If you are building a Python application, you can use the prepare_form function from the commonforms package to convert PDFs into fillable forms. All CLI arguments are available as keyword arguments to this function.

    from commonforms import prepare_form
    
    prepare_form(
        "path/to/input.pdf",
        "path/to/output.pdf"
    )
  3. CommonForms CLI Arguments Reference

    main

    The following arguments are available for the commonforms command:

    ArgumentTypeDefaultDescription
    inputPathRequiredPath to the input PDF file
    outputPathRequiredPath to save the output PDF file
    --modelstrFFDNet-LModel name (FFDNet-L/FFDNet-S) or path to custom .pt file
    --keep-existing-fieldsflagFalseKeep existing form fields in the PDF
    --use-signature-fieldsflagFalseUse signature fields instead of text fields for detected signatures
    --devicestrcpuDevice for inference (e.g., cpu, cuda, 0)
    --image-sizeint1600Image size for inference
    --confidencefloat0.3Confidence threshold for detection
    --fastflagFalseIf running on a CPU, trade off accuracy for speed (runs in ~half the time)
    --multilineflagFalseAllow detected textboxes to accept multiline inputs
  4. Handle encrypted PDF errors

    main

    When using render_pdf or prepare_form, if the input PDF is password protected or encrypted, the library will raise a commonforms.exceptions.EncryptedPdfError.

    from commonforms.exceptions import EncryptedPdfError
    from commonforms.inference import render_pdf
    
    try:
        pages = render_pdf("encrypted.pdf")
    except EncryptedPdfError:
        print("Cannot process encrypted PDF.")
  5. Use the CommonForms CLI

    main

    The CommonForms CLI allows you to automatically convert a PDF into a fillable form via the command line. The simplest usage runs inference on your CPU using default settings by providing an input path and an output path.

    commonforms <input.pdf> <output.pdf>
  6. Render PDF pages for processing

    main

    Use render_pdf(pdf_path: str) -> list[Page] to convert a PDF file into a list of Page objects. Each Page object contains a PIL image of the rendered page and a list of TextFragment objects representing the text content and its coordinates.

    This is a required step before passing pages to FFDetrDetector.extract_widgets or FFDNetDetector.extract_widgets.

    from commonforms.inference import render_pdf
    
    pages = render_pdf("my_document.pdf")
    # pages[0].image is a PIL.Image
    # pages[0].text_fragments contains text and coordinates
  7. Use PyPdfFormCreator to create PDF forms

    main

    The PyPdfFormCreator class is the primary interface for adding interactive form elements (textboxes, checkboxes, and signatures) to an existing PDF file. It uses pypdf under the hood to manage annotations.

    Workflow

    1. Initialize: Create an instance by providing the path to an existing PDF.
    2. Add Fields: Use methods like add_text_box, add_checkbox, or add_signature specifying the field name, the page index, and a BoundingBox defining the location.
    3. Save: Call save(output_path) to write the new PDF to disk.
    4. Cleanup: Call close() to release the file handles for the reader and writer.
    from commonforms.form_creator import PyPdfFormCreator
    from commonforms.utils import BoundingBox
    
    # Initialize with an existing PDF
    creator = PyPdfFormCreator("input.pdf")
    
    # Define a location using BoundingBox (coordinates are normalized 0.0 to 1.0)
    box = BoundingBox(x0=0.1, y0=0.1, x1=0.5, y1=0.2)
    
    # Add a textbox on page 0
    creator.add_text_box("user_name", page=0, bounding_box=box)
    
    # Add a checkbox on page 0
    creator.add_checkbox("agree_terms", page=0, bounding_box=box)
    
    # Save the result
    creator.save("output_form.pdf")
    creator.close()
  8. Use FFDetrDetector for widget extraction

    main

    The FFDetrDetector class uses the RFDETR model to detect form widgets (TextBox, ChoiceButton, Signature) in PDF pages. It supports downloading weights automatically from the Hugging Face Hub if a valid model name like FFDETR is provided.

    Key Methods:

    • __init__(model_or_path: str, device: int | str = "cpu"):
      • model_or_path: Use "FFDETR" to download weights automatically, or provide a local path to a .pth file.
      • device: The device to run inference on (e.g., "cpu" or an integer for GPU).
    • extract_widgets(pages: list[Page], confidence: float = 0.4, image_size: int = 1120, batch_size: int = 3) -> dict[int, list[Widget]]:
      • pages: A list of Page objects (obtained via render_pdf).
      • confidence: Detection threshold.
      • image_size: Target image size for processing.
      • batch_size: Number of pages to process in a single batch.
    from commonforms.inference import FFDetrDetector
    from commonforms.inference import render_pdf
    
    # 1. Render PDF pages
    pages = render_pdf("input.pdf")
    
    # 2. Initialize detector
    detector = FFDetrDetector(model_or_path="FFDETR", device="cpu")
    
    # 3. Extract widgets
    widgets_by_page = detector.extract_widgets(pages, confidence=0.5)
  9. Use prepare_form() for dataset preparation

    main

    The prepare_form function is the primary entrypoint for preparing datasets within the commonforms library. It is imported from commonforms.inference and is exposed at the package level for convenience.

    from commonforms import prepare_form
    
    # Use prepare_form to process your dataset
    prepare_form(...)
  10. Use the prepare_form API for programmatic form preparation

    main

    If you are integrating CommonForms into a Python application, you can call prepare_form directly from commonforms.inference.

    Signature: prepare_form(input, output, model_or_path, keep_existing_fields, use_signature_fields, device, image_size, confidence, fast, multiline)

    Parameters:

    • input (Path): Path to the input PDF.
    • output (Path): Path to save the output PDF.
    • model_or_path (str): Model name (FFDNet-L/FFDNet-S) or path to a .pt model.
    • keep_existing_fields (bool): Whether to keep existing form fields.
    • use_signature_fields (bool): Whether to use signature fields for detected signatures.
    • device (str): Inference device (e.g., cpu).
    • image_size (int): Image size for inference.
    • confidence (float): Confidence threshold for detection.
    • fast (bool): Use fast mode for CPU speedup.
    • multiline (bool): Enable multiline inputs for textboxes.
    from commonforms.inference import prepare_form
    from pathlib import Path
    
    prepare_form(
        input=Path("input.pdf"),
        output=Path("output.pdf"),
        model_or_path="FFDNet-L",
        keep_existing_fields=True,
        use_signature_fields=False,
        device="cpu",
        image_size=1600,
        confidence=0.3,
        fast=True,
        multiline=True
    )