### Production Setup Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Example of a production-grade form preparation with error handling, using a high-accuracy model with strict confidence. ```python def prepare_form_production(input_pdf: str, output_pdf: str): """Production-grade form preparation with error handling.""" from commonforms import prepare_form from commonforms.exceptions import EncryptedPdfError import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) try: # Use high-accuracy model with strict confidence prepare_form( input_pdf, output_pdf, model_or_path="FFDetr", confidence=0.5, image_size=1600, device="cuda:0" if torch.cuda.is_available() else "cpu", keep_existing_fields=False, use_signature_fields=True, signature_label_terms=("signature", "authorized", "sign") ) logger.info(f"Successfully processed {input_pdf}") return True except EncryptedPdfError: logger.error("PDF is encrypted") return False except Exception as e: logger.exception(f"Error processing PDF: {e}") return False ``` -------------------------------- ### Usage After Installation Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Examples of using commonforms from the command line and within Python scripts. ```bash # CLI commonforms input.pdf output.pdf # Python from commonforms import prepare_form prepare_form("input.pdf", "output.pdf") ``` -------------------------------- ### Widget Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Example of creating and using a Widget instance. ```python from commonforms.utils import Widget, BoundingBox widget = Widget( widget_type="TextBox", bounding_box=BoundingBox(x0=0.1, y0=0.2, x1=0.5, y1=0.25), page=0 ) print(f"Found {widget.widget_type} on page {widget.page}") print(f"Location: {widget.bounding_box}") ``` -------------------------------- ### TextFragment Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Example of creating and using a TextFragment instance. ```python from commonforms.utils import TextFragment fragment = TextFragment(text="Signature", x0=0.37, y0=0.61) print(f"'{fragment.text}' found at ({fragment.x0:.2f}, {fragment.y0:.2f})") ``` -------------------------------- ### Constructor Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/form_creator.md Example of initializing PyPdfFormCreator and adding a text box. ```python creator = PyPdfFormCreator("input.pdf") try: creator.add_text_box("name_field", page=0, bounding_box=...) creator.save("output.pdf") finally: creator.close() ``` -------------------------------- ### CLI Configuration Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Example of configuring CommonForms via the command-line interface, mapping directly to prepare_form() parameters. ```bash commonforms input.pdf output.pdf \ --model FFDNet-L \ --device cuda:0 \ --image-size 1600 \ --confidence 0.4 \ --use-signature-fields \ --multiline ``` -------------------------------- ### GPU Acceleration Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example demonstrating how to configure GPU acceleration for form preparation, falling back to CPU if GPU is not available. ```python from commonforms import prepare_form import torch # Check if GPU available if torch.cuda.is_available(): device = "cuda:0" # First GPU else: device = "cpu" prepare_form("input.pdf", "output.pdf", device=device) ``` -------------------------------- ### Installation Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Commands to install the commonforms package using pip or uv. ```bash pip install commonforms # or uv pip install commonforms ``` -------------------------------- ### Multiple GPU Support Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Examples showing how to specify a particular GPU for processing using its index or name. ```python from commonforms import prepare_form # Use second GPU prepare_form("input.pdf", "output.pdf", device="cuda:1") # Or using integer index prepare_form("input.pdf", "output.pdf", device=1) ``` -------------------------------- ### Profile Different Configurations Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This example profiles the performance of the prepare_form function with different model configurations (model, image size, confidence). ```python import time from commonforms import prepare_form configs = [ {"model": "FFDNet-S", "size": 512, "confidence": 0.5}, {"model": "FFDNet-L", "size": 1024, "confidence": 0.4}, {"model": "FFDNet-L", "size": 1600, "confidence": 0.3}, {"model": "FFDetr", "size": 1024, "confidence": 0.4}, ] for config in configs: start = time.time() try: prepare_form( "input.pdf", f"output_{config['model']}.pdf", model_or_path=config['model'], image_size=config['size'], confidence=config['confidence'] ) elapsed = time.time() - start print(f"{config['model']:10} {config['size']:4} {elapsed:6.2f}s") except Exception as e: print(f"{config['model']:10} {config['size']:4} ERROR: {e}") ``` -------------------------------- ### Use Custom Model File Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of using a custom, fine-tuned model file for form preparation. ```python from commonforms import prepare_form prepare_form( "input.pdf", "output.pdf", model_or_path="/path/to/my_fine_tuned_model.pt" ) ``` -------------------------------- ### Using FFDNetDetector Directly Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of directly using the FFDNetDetector for inference and rendering a PDF. ```python from commonforms.inference import FFDNetDetector, render_pdf from commonforms.form_creator import PyPdfFormCreator # Render PDF pages = render_pdf("input.pdf") ``` -------------------------------- ### CPU-Only Inference Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example explicitly setting the device to CPU for inference. ```python from commonforms import prepare_form prepare_form("input.pdf", "output.pdf", device="cpu") ``` -------------------------------- ### Replace All Fields Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example showing how to clear all pre-existing fields in a PDF and create only new ones. ```python from commonforms import prepare_form # Clear pre-existing fields and create new ones prepare_form( "old_form.pdf", "output.pdf", keep_existing_fields=False # Remove old fields ) ``` -------------------------------- ### BoundingBox from_yolo Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Example of using the from_yolo classmethod. ```python from commonforms.utils import BoundingBox # YOLO output: center (0.5, 0.6), width 0.2, height 0.1box = BoundingBox.from_yolo(cx=0.5, cy=0.6, w=0.2, h=0.1) # Result: BoundingBox(x0=0.4, y0=0.55, x1=0.6, y1=0.65) ``` -------------------------------- ### Installation with uv Source: https://github.com/jbarrow/commonforms/blob/main/README.md Installs the commonforms package using the uv package manager. ```sh uv pip install commonforms ``` -------------------------------- ### Custom Model Path Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Provide absolute path to custom model files. ```python prepare_form( "input.pdf", "output.pdf", model_or_path="/path/to/custom_model.pt" ) ``` -------------------------------- ### Installation with pip Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/README.md Install the commonforms library using pip. ```bash pip install commonforms ``` -------------------------------- ### Full Example Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md A comprehensive example demonstrating the workflow from rendering a PDF and extracting text to detecting form fields and creating a new PDF with form fields. ```python from commonforms.utils import BoundingBox, Widget, TextFragment, Page from commonforms.inference import FFDNetDetector, render_pdf from commonforms.form_creator import PyPdfFormCreator # Render PDF and extract text pages: list[Page] = render_pdf("input.pdf") # Detect form fields detector = FFDNetDetector("FFDNet-L") widgets_by_page: dict[int, list[Widget]] = detector.extract_widgets(pages) # Create form with detected fields creator = PyPdfFormCreator("input.pdf") for page_idx, widgets in widgets_by_page.items(): for widget in widgets: if widget.widget_type == "TextBox": creator.add_text_box( name=f"field_{page_idx}_{widgets.index(widget)}", page=page_idx, bounding_box=widget.bounding_box ) creator.save("output.pdf") creator.close() ``` -------------------------------- ### Save Form Data Programmatically Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This example demonstrates how to programmatically prepare a form, extract metadata about detected fields, save the metadata to a JSON file, and then create the actual form. ```python from commonforms import prepare_form import json def prepare_and_extract_metadata(input_pdf: str, output_pdf: str): """Prepare form and save metadata about detected fields.""" from commonforms.inference import render_pdf, FFDNetDetector pages = render_pdf(input_pdf) detector = FFDNetDetector("FFDNet-L") widgets = detector.extract_widgets(pages) # Save metadata metadata = { "input": input_pdf, "output": output_pdf, "total_pages": len(pages), "fields_by_page": {} } for page_idx, page_widgets in widgets.items(): metadata["fields_by_page"][page_idx] = [ { "type": w.widget_type, "bbox": { "x0": w.bounding_box.x0, "y0": w.bounding_box.y0, "x1": w.bounding_box.x1, "y1": w.bounding_box.y1, } } for w in page_widgets ] with open(output_pdf.replace(".pdf", "_metadata.json"), "w") as f: json.dump(metadata, f, indent=2) # Create actual form prepare_form(input_pdf, output_pdf) return metadata metadata = prepare_and_extract_metadata("form.pdf", "form_out.pdf") print(json.dumps(metadata, indent=2)) ``` -------------------------------- ### Example: Catching Model Loading Errors Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Example demonstrating how to catch general exceptions during model loading. ```python from commonforms import prepare_form try: prepare_form("input.pdf", "output.pdf", model_or_path="NonExistentModel") except Exception as e: print(f"Model loading error: {e}") ``` -------------------------------- ### Detect and Promote Signatures Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of detecting signature fields and promoting them to PDF signature widgets, using specified label terms for identification. ```python from commonforms import prepare_form prepare_form( "contract.pdf", "output.pdf", use_signature_fields=True, # Use PDF signature widget type signature_label_terms=("signature", "authorized by", "witness") ) ``` -------------------------------- ### Add to Existing Form Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example demonstrating how to append newly detected fields to any pre-existing fields in a PDF. ```python from commonforms import prepare_form # Append detected fields to pre-existing ones prepare_form( "partially_filled_form.pdf", "output.pdf", keep_existing_fields=True ) ``` -------------------------------- ### Signature as Text Field Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example showing how to store detected signature fields as regular text fields instead of PDF signature widgets. ```python from commonforms import prepare_form # Signature fields rendered as regular textboxes (default) prepare_form( "contract.pdf", "output.pdf", use_signature_fields=False # Store signatures as text ) ``` -------------------------------- ### Example: Catching FileNotFoundError for input PDF Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Example demonstrating how to catch FileNotFoundError if the input PDF does not exist. ```python from commonforms import prepare_form try: prepare_form("nonexistent.pdf", "output.pdf") except FileNotFoundError as e: print(f"Input file not found: {e}") ``` -------------------------------- ### Use Smaller Model for Speed Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of using a smaller and faster model (FFDNet-S) for quicker form processing. ```python from commonforms import prepare_form prepare_form( "simple_form.pdf", "output.pdf", model_or_path="FFDNet-S", # Smallest and fastest confidence=0.5 ) ``` -------------------------------- ### Add Signature Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/form_creator.md Example of adding a signature field to a PDF page. ```python from commonforms.utils import BoundingBox creator = PyPdfFormCreator("form.pdf")box = BoundingBox(x0=0.1, y0=0.7, x1=0.6, y1=0.8) creator.add_signature("witness_signature", page=0, bounding_box=bbox) creator.save("form_with_signature.pdf") ``` -------------------------------- ### Using FFDetrDetector Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This example demonstrates using the transformer-based FFDetrDetector to extract widgets from a PDF, with options for confidence and batch size. ```python from commonforms.inference import FFDetrDetector, render_pdf pages = render_pdf("input.pdf") # Use transformer-based detector detector = FFDetrDetector("FFDetr", device="cuda") widgets = detector.extract_widgets( pages, confidence=0.3, batch_size=8 # Process 8 pages at a time ) for page_idx, page_widgets in widgets.items(): print(f"Page {page_idx}: {len(page_widgets)} fields detected") ``` -------------------------------- ### Single-Line Text Input Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example configuring form fields to restrict input to a single line. ```python from commonforms import prepare_form prepare_form( "form.pdf", "output.pdf", multiline=False # Restrict to single line ) ``` -------------------------------- ### Batch Size for Widget Extraction Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Examples showing how to adjust the batch size for extracting widgets, with 'Balanced' and 'Aggressive' profiles. ```python detector.extract_widgets(pages, batch_size=4) ``` ```python detector.extract_widgets(pages, batch_size=16) ``` -------------------------------- ### Example: Catching Local Model File Not Found Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Example demonstrating how to catch FileNotFoundError when a custom model path is invalid. ```python from commonforms import prepare_form try: prepare_form("input.pdf", "output.pdf", model_or_path="/path/to/missing_model.pt") except FileNotFoundError: print("Custom model file not found") except Exception as e: print(f"Model initialization error: {e}") ``` -------------------------------- ### Inspect Detected Fields Before Creating Form Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This advanced example shows how to inspect detected fields, print their types and bounding boxes, and then prompt the user before creating the form. ```python from commonforms.inference import render_pdf, FFDNetDetector from commonforms.form_creator import PyPdfFormCreator # Render and detect pages = render_pdf("input.pdf") detector = FFDNetDetector("FFDNet-L") widgets_by_page = detector.extract_widgets(pages, confidence=0.4) # Inspect and filter print("Detected fields:") for page_idx, widgets in widgets_by_page.items(): print(f"\nPage {page_idx}:") for i, widget in enumerate(widgets): print(f" {i}: {widget.widget_type} at {widget.bounding_box}") # Create form with user confirmation response = input("Proceed with form creation? (y/n): ") if response.lower() == 'y': creator = PyPdfFormCreator("input.pdf") for page_idx, widgets in widgets_by_page.items(): for i, widget in enumerate(widgets): name = f"{widget.widget_type}_{page_idx}_{i}" if widget.widget_type == "TextBox": creator.add_text_box(name, page_idx, widget.bounding_box) # ... handle other types creator.save("output.pdf") creator.close() print("Form saved to output.pdf") else: print("Cancelled") ``` -------------------------------- ### CPU Inference Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Example of configuring CPU for inference. ```python prepare_form("input.pdf", "output.pdf", device="cpu") ``` -------------------------------- ### Add Checkbox Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/form_creator.md Example of adding a checkbox field to a PDF page. ```python from commonforms.utils import BoundingBox creator = PyPdfFormCreator("form.pdf")box = BoundingBox(x0=0.1, y0=0.3, x1=0.15, y1=0.35) creator.add_checkbox("agree_terms", page=0, bounding_box=bbox) creator.save("form_with_checkbox.pdf") ``` -------------------------------- ### Multiline Text Input Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example configuring form fields to accept multiline text input, suitable for paragraph-style entries. ```python from commonforms import prepare_form prepare_form( "form.pdf", "output.pdf", multiline=True # Allow paragraph input ) ``` -------------------------------- ### Parallel Processing (with concurrent.futures) Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Demonstrates parallel processing of PDF files using `concurrent.futures.ThreadPoolExecutor` for improved performance. ```python from pathlib import Path from commonforms import prepare_form from concurrent.futures import ThreadPoolExecutor import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def prepare_single_pdf(input_file: str, output_dir: str) -> tuple[str, bool]: """Prepare single PDF, return (filename, success).""" output_file = Path(output_dir) / Path(input_file).name try: prepare_form(input_file, str(output_file)) return (Path(input_file).name, True) except Exception as e: logger.error(f"{Path(input_file).name}: {e}") return (Path(input_file).name, False) def batch_process_pdfs_parallel(input_dir: str, output_dir: str, max_workers: int = 4): """Process PDFs in parallel.""" input_path = Path(input_dir) output_path = Path(output_dir) output_path.mkdir(parents=True, exist_ok=True) pdf_files = [str(f) for f in input_path.glob("*.pdf")] logger.info(f"Processing {len(pdf_files)} PDFs with {max_workers} workers") results = [] with ThreadPoolExecutor(max_workers=max_workers) as executor: for filename, success in executor.map( lambda f: prepare_single_pdf(f, str(output_path)), pdf_files ): results.append((filename, success)) status = "\u2713" if success else "\u2717" logger.info(f" {status} {filename}") successful = sum(1 for _, success in results if success) logger.info(f"Results: {successful}/{len(pdf_files)} successful") batch_process_pdfs_parallel("./input_forms", "./output_forms", max_workers=4) ``` -------------------------------- ### Simplest Form Preparation Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Convert PDF to fillable form with all defaults. Uses FFDetr model by default, runs on CPU, saves filled form to output file, and returns None on success. ```python from commonforms import prepare_form # Convert PDF to fillable form with all defaults prepare_form("input.pdf", "output.pdf") ``` -------------------------------- ### Batch Processing Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Example for processing all PDFs in a directory using batch processing. ```python from pathlib import Path from commonforms import prepare_form def batch_process_pdfs(input_dir: str, output_dir: str): """Process all PDFs in directory.""" input_path = Path(input_dir) output_path = Path(output_dir) output_path.mkdir(exist_ok=True) for pdf_file in input_path.glob("*.pdf"): output_file = output_path / pdf_file.name print(f"Processing {pdf_file.name}...") try: prepare_form( str(pdf_file), str(output_file), model_or_path="FFDNet-L", confidence=0.45, device="cuda:0" ) except Exception as e: print(f" Error: {e}") ``` -------------------------------- ### pypdf ArrayObject Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Example of creating an ArrayObject from the pypdf library to represent rectangle coordinates. ```python from pypdf.generic import ArrayObject, NumberObject rect = ArrayObject([ NumberObject(100), # x0 NumberObject(200), # y0 NumberObject(400), # x1 NumberObject(300), # y1 ]) ``` -------------------------------- ### Add Text Box Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/form_creator.md Example of adding a text input field to a PDF page. ```python from commonforms.utils import BoundingBox creator = PyPdfFormCreator("form.pdf")box = BoundingBox(x0=0.1, y0=0.2, x1=0.4, y1=0.25) creator.add_text_box("applicant_name", page=0, bounding_box=bbox, multiline=False) creator.save("form_with_fields.pdf") ``` -------------------------------- ### Custom Widget Filtering Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This example demonstrates filtering detected widgets based on custom criteria, such as minimum width and height, before creating the form. ```python from commonforms.inference import render_pdf, FFDNetDetector from commonforms.form_creator import PyPdfFormCreator pages = render_pdf("input.pdf") detector = FFDNetDetector("FFDNet-L") all_widgets = detector.extract_widgets(pages) # Filter to only high-confidence regions (larger boxes) min_width = 0.05 min_height = 0.01 filtered_widgets = { page_idx: [ w for w in widgets if (w.bounding_box.x1 - w.bounding_box.x0) >= min_width and (w.bounding_box.y1 - w.bounding_box.y0) >= min_height ] for page_idx, widgets in all_widgets.items() } print(f"Filtered from {sum(len(w) for w in all_widgets.values())} " f"to {sum(len(w) for w in filtered_widgets.values())} widgets") # Create form with filtered widgets creator = PyPdfFormCreator("input.pdf") for page_idx, widgets in filtered_widgets.items(): for i, widget in enumerate(widgets): name = f"{widget.widget_type}_{page_idx}_{i}" if widget.widget_type == "TextBox": creator.add_text_box(name, page_idx, widget.bounding_box) creator.save("output.pdf") creator.close() ``` -------------------------------- ### Batch Size Configuration Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Example of configuring batch size for FFDetr model. ```python # Conservative: 1 image at a time detector.extract_widgets(pages, batch_size=1) ``` -------------------------------- ### Page Example Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Demonstrates how to render a PDF, iterate through its pages, and access page properties like dimensions and text fragments. ```python from commonforms.utils import Page from commonforms.inference import render_pdf pages = render_pdf("form.pdf") for page_idx, page in enumerate(pages): print(f"Page {page_idx}: {page.width}x{page.height} pixels") print(f" Contains {len(page.text_fragments)} text fragments") # Access PIL image directly page.image.save(f"page_{page_idx}.png") ``` -------------------------------- ### FFDetrDetector Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/inference.md Demonstrates how to instantiate FFDetrDetector. ```python from commonforms.inference import FFDetrDetector detector = FFDetrDetector("FFDetr", device="cuda:0") ``` -------------------------------- ### pypdf NameObject Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Example of creating a NameObject from the pypdf library for PDF dictionary keys or field type identifiers. ```python from pypdf.generic import NameObject field_type = NameObject("/Tx") # Text field ``` -------------------------------- ### GPU Inference Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Examples of configuring GPU for inference. ```python prepare_form("input.pdf", "output.pdf", device="cuda") # Default CUDA device ``` ```python prepare_form("input.pdf", "output.pdf", device="cuda:0") # Specific GPU ``` ```python prepare_form("input.pdf", "output.pdf", device=0) # Integer shorthand ``` -------------------------------- ### Clear Existing Fields Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/form_creator.md Example of clearing all existing form fields and adding a new text box. ```python creator = PyPdfFormCreator("input.pdf") creator.clear_existing_fields() # Remove pre-existing form fields creator.add_text_box("new_field", page=0, bounding_box=...) ``` -------------------------------- ### Comprehensive Error Handling Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Shows how to handle various exceptions that might occur during form preparation, such as encrypted PDFs, file not found, and permission errors. ```python from commonforms import prepare_form from commonforms.exceptions import EncryptedPdfError import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def safe_prepare_form(input_pdf: str, output_pdf: str) -> bool: """Prepare form with detailed error reporting.""" try: prepare_form(input_pdf, output_pdf) logger.info(f"Successfully prepared {input_pdf}") return True except EncryptedPdfError: logger.error(f"{input_pdf} is encrypted. Provide unencrypted copy.") return False except FileNotFoundError: logger.error(f"Input file not found: {input_pdf}") return False except PermissionError: logger.error(f"Permission denied. Check file permissions for {input_pdf}") return False except Exception as e: logger.error(f"Unexpected error processing {input_pdf}: {e}") return False success = safe_prepare_form("form.pdf", "form_filled.pdf") ``` -------------------------------- ### Run detection and create form manually Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This snippet shows how to use FFDNetDetector to extract widgets and then manually create a PDF form using PyPdfFormCreator. ```python from commonforms.inference import FFDNetDetector from commonforms.form_creator import PyPdfFormCreator # Assuming 'pages' is already loaded # pages = detector.render_pdf("input.pdf") detector = FFDNetDetector("FFDNet-L", device="cuda:0") widgets_by_page = detector.extract_widgets(pages, confidence=0.4) # Create form manually creator = PyPdfFormCreator("input.pdf") for page_idx, widgets in widgets_by_page.items(): for i, widget in enumerate(widgets): field_name = f"{widget.widget_type}_{page_idx}_{i}" if widget.widget_type == "TextBox": creator.add_text_box(field_name, page_idx, widget.bounding_box) elif widget.widget_type == "ChoiceButton": creator.add_checkbox(field_name, page_idx, widget.bounding_box) elif widget.widget_type == "Signature": creator.add_signature(field_name, page_idx, widget.bounding_box) creator.save("output.pdf") creator.close() ``` -------------------------------- ### Use Larger Model for Better Accuracy Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of using a larger model (FFDetr) for potentially better accuracy in form processing. ```python from commonforms import prepare_form prepare_form( "complex_form.pdf", "output.pdf", model_or_path="FFDetr", # Highest accuracy confidence=0.3 ) ``` -------------------------------- ### Basic Error Handling Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of implementing basic error handling for common issues like encrypted PDFs or file not found errors during form preparation. ```python from commonforms import prepare_form from commonforms.exceptions import EncryptedPdfError try: prepare_form("input.pdf", "output.pdf") except EncryptedPdfError: print("Error: PDF is encrypted. Decrypt it first.") except FileNotFoundError as e: print(f"Error: {e}") except Exception as e: print(f"Unexpected error: {e}") ``` -------------------------------- ### CLI Interface Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Example command-line interface usage for the commonforms package. ```bash commonforms input.pdf output.pdf \ --model FFDNet-L \ --confidence 0.4 \ --device cuda:0 \ --image-size 1600 \ --keep-existing-fields \ --use-signature-fields \ --multiline \ --fast ``` -------------------------------- ### High Recall (More Detections) Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of tuning the confidence threshold to a lower value to increase recall, capturing more potential detections. ```python from commonforms import prepare_form prepare_form( "input.pdf", "output.pdf", confidence=0.2 # Even uncertain detections ) ``` -------------------------------- ### Handling CUDA Device Not Available Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Example of checking CUDA availability and falling back to CPU. ```python # Check CUDA availability import torch if not torch.cuda.is_available(): device = "cpu" else: device = "cuda:0" prepare_form("input.pdf", "output.pdf", device=device) ``` -------------------------------- ### FFDNetDetector Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/inference.md Demonstrates how to instantiate FFDNetDetector using built-in models, custom paths, and the fast inference option. ```python from commonforms.inference import FFDNetDetector # Using built-in model detector = FFDNetDetector("FFDNet-L", device="cuda:0") # Using custom model detector = FFDNetDetector("/path/to/custom_model.pt", device="cpu") # Fast inference on CPU detector = FFDNetDetector("FFDNet-S", device="cpu", fast=True) ``` -------------------------------- ### Retry with Fallback Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Implements a retry mechanism with exponential backoff for form preparation to handle transient errors. ```python from commonforms import prepare_form import time def prepare_form_with_retry(input_pdf: str, output_pdf: str, max_retries: int = 3): """Retry form preparation with exponential backoff.""" for attempt in range(max_retries): try: prepare_form(input_pdf, output_pdf) print(f"Success on attempt {attempt + 1}") return True except Exception as e: if attempt < max_retries - 1: wait_time = 2 ** attempt # Exponential backoff print(f"Attempt {attempt + 1} failed, retrying in {wait_time}s: {e}") time.sleep(wait_time) else: print(f"All {max_retries} attempts failed") raise return False prepare_form_with_retry("input.pdf", "output.pdf") ``` -------------------------------- ### commonforms.utils Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Example imports for data types from commonforms.utils. ```python from commonforms.utils import BoundingBox, Widget, Page, TextFragment ``` -------------------------------- ### High Precision (Fewer False Positives) Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md Example of tuning the confidence threshold to a higher value for increased precision, reducing false positives. ```python from commonforms import prepare_form prepare_form( "input.pdf", "output.pdf", confidence=0.7 # Only very confident detections ) ``` -------------------------------- ### Comprehensive Error Handling Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md A robust try-except block demonstrating handling of various common exceptions. ```python from commonforms import prepare_form from commonforms.exceptions import EncryptedPdfError import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) try: prepare_form( "input.pdf", "output.pdf", device="cuda" if torch.cuda.is_available() else "cpu", confidence=0.4 ) logger.info("PDF form preparation successful") except EncryptedPdfError: logger.error("Input PDF is encrypted. Please decrypt first.") except FileNotFoundError as e: logger.error(f"File not found: {e}") except PermissionError as e: logger.error(f"Permission denied: {e}") except Exception as e: logger.exception(f"Unexpected error during form preparation: {e}") ``` -------------------------------- ### commonforms.exceptions Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Example of how to catch EncryptedPdfError. ```python from commonforms.exceptions import EncryptedPdfError try: prepare_form("input.pdf", "output.pdf") except EncryptedPdfError: print("PDF is encrypted") ``` -------------------------------- ### How to Catch EncryptedPdfError Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Example demonstrating how to catch EncryptedPdfError when processing a PDF. ```python from commonforms import prepare_form from commonforms.exceptions import EncryptedPdfError try: prepare_form("input.pdf", "output.pdf") except EncryptedPdfError: print("Error: PDF is encrypted. Please provide an unencrypted copy.") except Exception as e: print(f"Unexpected error: {e}") ``` -------------------------------- ### Measure Processing Time Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md This snippet shows how to measure the time it takes to process a PDF using the prepare_form function. ```python import time from commonforms import prepare_form start = time.time() prepare_form("input.pdf", "output.pdf", model_or_path="FFDNet-L") elapsed = time.time() - start print(f"Processing time: {elapsed:.2f} seconds") ``` -------------------------------- ### Workaround: Remove encryption using pypdf Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Example demonstrating how to remove PDF encryption using the pypdf library. ```python from pypdf import PdfReader, PdfWriter # If password is known reader = PdfReader("encrypted.pdf", password="your_password") writer = PdfWriter() for page in reader.pages: writer.add_page(page) with open("unencrypted.pdf", "wb") as f: writer.write(f) # Then process unencrypted version prepare_form("unencrypted.pdf", "output.pdf") ``` -------------------------------- ### Retryable Errors Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Implementing a retry mechanism for network errors during model download. ```python import time from commonforms import prepare_form max_retries = 3 retry_delay = 5 # seconds for attempt in range(max_retries): try: prepare_form("input.pdf", "output.pdf") break except Exception as e: if attempt < max_retries - 1: logger.warning(f"Attempt {attempt+1} failed, retrying in {retry_delay}s: {e}") time.sleep(retry_delay) else: logger.error(f"All {max_retries} attempts failed") raise ``` -------------------------------- ### Process Directory of PDFs Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md A function to batch process all PDF files within a specified input directory and save the results to an output directory. ```python from pathlib import Path from commonforms import prepare_form import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def batch_process_pdfs(input_dir: str, output_dir: str): """Process all PDFs in input directory.""" input_path = Path(input_dir) output_path = Path(output_dir) # Create output directory if needed output_path.mkdir(parents=True, exist_ok=True) pdf_files = list(input_path.glob("*.pdf")) logger.info(f"Found {len(pdf_files)} PDF files") success_count = 0 for pdf_file in pdf_files: output_file = output_path / pdf_file.name try: logger.info(f"Processing {pdf_file.name}...") prepare_form(str(pdf_file), str(output_file)) success_count += 1 logger.info(f" \u2713 Saved to {output_file.name}") except Exception as e: logger.error(f" \u2717 Error: {e}") logger.info(f"Completed: {success_count}/{len(pdf_files)} successful") batch_process_pdfs("./input_forms", "./output_forms") ``` -------------------------------- ### Basic Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/prepare_form.md Demonstrates simple usage of the prepare_form function with default settings and how to specify a model and device. ```python from commonforms import prepare_form # Simple usage with defaults prepare_form("input.pdf", "output.pdf") # Specify model and device prepare_form( "input.pdf", "output.pdf", model_or_path="FFDNet-L", device="cuda:0" ) ``` -------------------------------- ### FFDNetDetector extract_widgets Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/inference.md Shows how to use the extract_widgets method to detect form fields and process the results. ```python from commonforms.inference import FFDNetDetector from commonforms.utils import Page # Assume `pages` is a list of Page objects detector = FFDNetDetector("FFDNet-L", device="cuda") widgets_by_page = detector.extract_widgets(pages, confidence=0.4, image_size=1600) # Results: {0: [Widget(...), Widget(...)], 1: [Widget(...)], ...} for page_idx, widgets in widgets_by_page.items(): print(f"Page {page_idx}: {len(widgets)} fields detected") ``` -------------------------------- ### CPU with Speed Trade-off Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/prepare_form.md Shows how to use an ONNX model for faster inference on CPU, including adjusting the confidence threshold. ```python # Use ONNX model for ~50% faster inference on CPU prepare_form( "input.pdf", "output.pdf", model_or_path="FFDNet-S", device="cpu", fast=True, confidence=0.35 # Slightly lower threshold for FFDNet-S ) ``` -------------------------------- ### Main Entry Point Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/README.md The `prepare_form` function signature and its parameters. ```python prepare_form( input_path: str | Path, output_path: str | Path, *, model_or_path: str = "FFDetr", device: str | int = "cpu", confidence: float = 0.4, image_size: int = 1024, fast: bool = False, multiline: bool = False, keep_existing_fields: bool = False, use_signature_fields: bool = False, batch_size: int = 4, signature_label_terms: tuple = ("signature",) ) -> None ``` -------------------------------- ### PyPdfFormCreator Initialization and Field Addition Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Demonstrates initializing PyPdfFormCreator and adding various form fields (textbox, checkbox, signature) with normalized coordinates. ```python from commonforms.form_creator import PyPdfFormCreator from commonforms.utils import BoundingBox # Initialize with input PDF creator = PyPdfFormCreator("input.pdf") # Optionally clear existing fields creator.clear_existing_fields() # Add fields with normalized coordinatesbox = BoundingBox(x0=0.1, y0=0.2, x1=0.5, y1=0.25) # Single-line textbox creator.add_text_box("name", page=0, bounding_box=bbox, multiline=False) # Multiline textbox creator.add_text_box("address", page=0, bounding_box=bbox, multiline=True) # Checkbox creator.add_checkbox("agree", page=0, bounding_box=bbox) # Signature creator.add_signature("sign", page=0, bounding_box=bbox) ``` -------------------------------- ### Custom Signature Detection Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/prepare_form.md Illustrates how to enable custom signature detection by specifying relevant label terms. ```python # Detect fields labeled "signature", "sign here", or "authorized by" prepare_form( "input.pdf", "output.pdf", use_signature_fields=True, signature_label_terms=("signature", "sign here", "authorized by") ) ``` -------------------------------- ### commonforms.inference Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Example usage of the inference module, both high-level and low-level APIs. ```python from commonforms.inference import prepare_form, FFDNetDetector, FFDetrDetector from commonforms.utils import Page # High-level API prepare_form("input.pdf", "output.pdf") # Low-level API detector = FFDNetDetector("FFDNet-L", device="cuda") pages: list[Page] = ... # Render pages separately widgets = detector.extract_widgets(pages, confidence=0.4) ``` -------------------------------- ### Image Size Configuration - Low Resolution Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Using a lower image size for faster inference. ```python prepare_form("input.pdf", "output.pdf", image_size=512) ``` -------------------------------- ### Mitigation for Out of Memory Error Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/errors.md Examples of reducing memory usage to mitigate Out of Memory errors. ```python # Reduce batch size to use less memory detector.extract_widgets(pages, batch_size=1) # Or use smaller model prepare_form("input.pdf", "output.pdf", model_or_path="FFDNet-S") # Or reduce image size prepare_form("input.pdf", "output.pdf", image_size=1024) ``` -------------------------------- ### Image Size Configuration - Default Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Using the default image size for inference. ```python prepare_form("input.pdf", "output.pdf", image_size=1024) ``` -------------------------------- ### CommonForms API Usage Source: https://github.com/jbarrow/commonforms/blob/main/README.md Example of using the prepare_form function from the commonforms API to convert a PDF. ```python from commonforms import prepare_form prepare_form( "path/to/input.pdf", "path/to/output.pdf" ) ``` -------------------------------- ### Fast (CPU-friendly) Performance Profile Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Configuration for quick processing on CPU, with expected performance metrics. ```python prepare_form( "input.pdf", "output.pdf", model_or_path="FFDNet-S", confidence=0.5, image_size=512, device="cpu", fast=True ) ``` -------------------------------- ### commonforms.form_creator Usage Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Example of using the form_creator module to add a text box to a PDF. ```python from commonforms.form_creator import PyPdfFormCreator from commonforms.utils import BoundingBox creator = PyPdfFormCreator("input.pdf")box = BoundingBox(x0=0.1, y0=0.2, x1=0.5, y1=0.25) creator.add_text_box("field_name", page=0, bounding_box=bbox) creator.save("output.pdf") creator.close() ``` -------------------------------- ### High Confidence Threshold Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/prepare_form.md Shows how to set a high confidence threshold for detecting only very confident field locations and increasing image size for more detail. ```python # Only detect very confident field locations prepare_form( "input.pdf", "output.pdf", confidence=0.7, # Higher = fewer detections image_size=1600 # Larger image for more detail ) ``` -------------------------------- ### Convert a PDF to a fillable form Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/README.md Start with `prepare_form` to convert a PDF to a fillable form. ```python from commonforms import prepare_form prepare_form("input.pdf", "output.pdf") ``` -------------------------------- ### Form Creation Pipeline Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Explains the workflow of the PyPdfFormCreator, from initialization and adding form fields to saving and closing the PDF. ```text PyPdfFormCreator ├─→ __init__(input_path) │ ├─→ PdfReader (lazy-loaded) │ ├─→ PdfWriter (cloned from reader) │ └─→ Font resources setup ├─→ add_text_box / add_checkbox / add_signature │ ├─→ rect_for() ───→ Coordinate conversion │ ├─→ Create annotation object │ └─→ writer.add_annotation() ├─→ save(output_path) │ ├─→ reattach_fields() │ └─→ Write to disk └─→ close() ``` -------------------------------- ### High-Level Flow Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Illustrates the overall process from input PDF to output PDF with form fields, including key function calls and component interactions. ```text Input PDF ↓ prepare_form() ├─→ render_pdf() ────→ [Page] (images + text) ├─→ Select detector │ ├─→ FFDNetDetector.extract_widgets() (if FFDNET in model name) │ └─→ FFDetrDetector.extract_widgets() (otherwise) │ ↓ │ sort_widgets() ├─→ promote_signature_widgets() (if use_signature_fields=True) ├─→ PyPdfFormCreator(input_path) │ ├─→ clear_existing_fields() (if keep_existing_fields=False) │ ├─→ add_text_box() / add_checkbox() / add_signature() │ ├─→ save(output_path) │ └─→ close() ↓ Output PDF (with form fields) ``` -------------------------------- ### Preserve Existing Fields Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/api-reference/prepare_form.md Demonstrates how to keep pre-existing form fields in the output PDF. ```python # Keep pre-existing form fields, add detected ones prepare_form( "input.pdf", "output.pdf", keep_existing_fields=True ) ``` -------------------------------- ### Image Size Configuration - High Resolution Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Using a higher image size for better accuracy. ```python prepare_form("input.pdf", "output.pdf", image_size=1600) ``` -------------------------------- ### Speed Priority (GPU) Performance Profile Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Configuration for the fastest possible inference on GPU, with expected performance metrics. ```python prepare_form( "input.pdf", "output.pdf", model_or_path="FFDNet-S", confidence=0.6, image_size=1024, device="cuda:0" ) ``` -------------------------------- ### Adaptive Threshold Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/code-examples.md A function that attempts to process a PDF with decreasing confidence thresholds until successful, demonstrating adaptive error handling. ```python from commonforms import prepare_form def auto_prepare_form(pdf_path: str, output_path: str): """Try with different confidence thresholds.""" for confidence in [0.5, 0.4, 0.3]: try: prepare_form( pdf_path, output_path, confidence=confidence ) print(f"Success with confidence={confidence}") return except Exception as e: print(f"Failed with confidence={confidence}: {e}") raise RuntimeError("Could not process PDF with any confidence level") auto_prepare_form("input.pdf", "output.pdf") ``` -------------------------------- ### Balanced Performance Profile Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Configuration for typical forms, balancing accuracy and speed, with expected performance metrics. ```python prepare_form( "input.pdf", "output.pdf", model_or_path="FFDNet-L", confidence=0.45, image_size=1024, device="cuda:0" ) ``` -------------------------------- ### Literal Types Example Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/types.md Illustrates the use of Python's Literal type for widget type discrimination, enabling type checkers to understand allowed values. ```python widget_type: Literal["TextBox", "ChoiceButton", "Signature"] ``` -------------------------------- ### Python Package Entry Point Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Defines the command-line entry point for the commonforms package. ```toml [project.scripts] commonforms = "commonforms:main" ``` -------------------------------- ### Signature as Text Field (Default) Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Renders detected signature fields as regular text fields for compatibility. ```python prepare_form("input.pdf", "output.pdf", use_signature_fields=False) ``` -------------------------------- ### Keep Existing Fields Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Preserves pre-existing fields and adds detected ones alongside. ```python prepare_form("input.pdf", "output.pdf", keep_existing_fields=True) ``` -------------------------------- ### Signature as PDF Signature Widget Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Uses the actual PDF signature field type, requiring signature software to sign. ```python prepare_form( "input.pdf", "output.pdf", use_signature_fields=True, signature_label_terms=("signature", "sign here", "authorized by") ) ``` -------------------------------- ### CLI Usage with Options Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/README.md Command-line interface usage with various options. ```bash # With options commonforms input.pdf output.pdf \ --model FFDNet-L \ --device cuda:0 \ --confidence 0.4 \ --image-size 1600 ``` -------------------------------- ### Single-line Text Field Configuration Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Configures the form preparation to use single-line text fields. ```python prepare_form("input.pdf", "output.pdf", multiline=False) ``` -------------------------------- ### Custom Signature Label Terms Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Specifies custom terms for matching and promoting signature fields. ```python prepare_form( "input.pdf", "output.pdf", use_signature_fields=True, signature_label_terms=( "signature", "sign here", "authorized by", "witness", "consent" ) ) ``` -------------------------------- ### Recommended Imports (Public API) Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/module-structure.md Shows the recommended import statements for users interacting with the public API of the commonforms library. ```python # Main API from commonforms import prepare_form, main # Exceptions from commonforms.exceptions import EncryptedPdfError # Data types from commonforms.utils import BoundingBox, Widget, TextFragment, Page # Advanced: Direct detector usage from commonforms.inference import FFDNetDetector, FFDetrDetector, render_pdf # Advanced: Form creation from commonforms.form_creator import PyPdfFormCreator ``` -------------------------------- ### Default Signature Label Terms Source: https://github.com/jbarrow/commonforms/blob/main/_autodocs/configuration.md Uses the default label term 'signature' for promoting textbox fields to signature fields. ```python prepare_form( "input.pdf", "output.pdf", use_signature_fields=True # Default signature_label_terms=("signature",) ) ```