CoolFace
Modelpublic

fredcallagan/uvdoc-grid-onnx

sourceHugging Faceapache-2.0updated 9mo agoView on Hugging Face
2likes105downloads
example.py236 linesDownload Raw Back to root
1#!/usr/bin/env python32"""3UVDoc Grid-Output Document Unwarping Example4 5This script demonstrates how to use the UVDoc ONNX model with grid output6for high-resolution document unwarping.7 8The key advantage of this grid-output model over image-output models is that9the coordinate grid can be upscaled to any resolution, preserving document10quality when applied via cv2.remap().11 12Usage:13    python example.py input_image.jpg output_image.jpg14    python example.py input_image.jpg output_image.jpg --model path/to/UVDoc_grid.onnx15 16Requirements:17    pip install onnxruntime opencv-python numpy18 19Optional (for automatic model download):20    pip install huggingface_hub21"""22 23import argparse24import sys25from pathlib import Path26 27import cv228import numpy as np29 30# Model input dimensions (fixed for UVDoc architecture)31MODEL_INPUT_HEIGHT = 72032MODEL_INPUT_WIDTH = 49633 34 35def load_model(model_path: str = None):36    """37    Load the ONNX model.38 39    Args:40        model_path: Path to the ONNX model file. If None, attempts to download41                    from HuggingFace Hub.42 43    Returns:44        ONNX Runtime InferenceSession45    """46    import onnxruntime as ort47 48    if model_path is None:49        try:50            from huggingface_hub import hf_hub_download51 52            print("Downloading model from HuggingFace Hub...")53            model_path = hf_hub_download(54                repo_id="YOUR_USERNAME/uvdoc-grid-onnx",  # Update with actual repo55                filename="UVDoc_grid.onnx"56            )57            print(f"Model downloaded to: {model_path}")58        except ImportError:59            print("Error: huggingface_hub not installed. Install it or provide --model path.")60            print("  pip install huggingface_hub")61            sys.exit(1)62 63    print(f"Loading model from: {model_path}")64    session = ort.InferenceSession(65        model_path,66        providers=['CPUExecutionProvider']67    )68 69    return session70 71 72def preprocess_image(image: np.ndarray) -> np.ndarray:73    """74    Preprocess image for UVDoc model input.75 76    Args:77        image: BGR image from cv2.imread()78 79    Returns:80        Preprocessed tensor of shape (1, 3, 720, 496)81    """82    # Convert BGR to RGB83    img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)84 85    # Resize to model input size86    resized = cv2.resize(img_rgb, (MODEL_INPUT_WIDTH, MODEL_INPUT_HEIGHT))87 88    # Normalize to [0, 1]89    normalized = resized.astype(np.float32) / 255.090 91    # Convert HWC to CHW format92    transposed = np.transpose(normalized, (2, 0, 1))93 94    # Add batch dimension95    batched = np.expand_dims(transposed, axis=0)96 97    return batched98 99 100def apply_grid_unwarping(101    image: np.ndarray,102    grid: np.ndarray,103    interpolation: int = cv2.INTER_CUBIC104) -> np.ndarray:105    """106    Apply the coordinate grid to unwarp the image.107 108    Args:109        image: Original BGR image (any resolution)110        grid: Model output grid of shape (1, 2, 45, 31)111        interpolation: OpenCV interpolation method112 113    Returns:114        Unwarped image at original resolution115    """116    h_orig, w_orig = image.shape[:2]117 118    # Remove batch dimension and transpose to (H, W, 2)119    grid_2d = np.transpose(grid[0], (1, 2, 0))  # (45, 31, 2)120 121    # Upscale grid to original image resolution122    grid_upscaled = cv2.resize(123        grid_2d,124        (w_orig, h_orig),125        interpolation=cv2.INTER_LINEAR126    )127 128    # Convert normalized coordinates [-1, 1] to pixel coordinates129    # Grid channel 0 = x (width), channel 1 = y (height)130    map_x = ((grid_upscaled[..., 0] + 1) / 2) * (w_orig - 1)131    map_y = ((grid_upscaled[..., 1] + 1) / 2) * (h_orig - 1)132 133    # Apply remapping134    unwarped = cv2.remap(135        image,136        map_x.astype(np.float32),137        map_y.astype(np.float32),138        interpolation=interpolation,139        borderMode=cv2.BORDER_REPLICATE140    )141 142    return unwarped143 144 145def unwarp_document(146    image_path: str,147    output_path: str,148    model_path: str = None149) -> None:150    """151    Main function to unwarp a document image.152 153    Args:154        image_path: Path to input warped document image155        output_path: Path to save unwarped result156        model_path: Optional path to ONNX model file157    """158    # Load image159    print(f"Loading image: {image_path}")160    image = cv2.imread(image_path)161    if image is None:162        print(f"Error: Could not load image from {image_path}")163        sys.exit(1)164 165    h, w = image.shape[:2]166    print(f"Image size: {w}x{h}")167 168    # Load model169    session = load_model(model_path)170 171    # Get input name172    input_name = session.get_inputs()[0].name173    print(f"Model input name: {input_name}")174 175    # Preprocess176    print("Preprocessing image...")177    input_tensor = preprocess_image(image)178    print(f"Input tensor shape: {input_tensor.shape}")179 180    # Run inference181    print("Running inference...")182    result = session.run(None, {input_name: input_tensor})[0]183    print(f"Output grid shape: {result.shape}")184    print(f"Output grid range: [{result.min():.4f}, {result.max():.4f}]")185 186    # Apply unwarping187    print("Applying grid-based unwarping...")188    unwarped = apply_grid_unwarping(image, result)189 190    # Save result191    print(f"Saving result to: {output_path}")192    cv2.imwrite(output_path, unwarped)193 194    print("Done!")195 196 197def main():198    parser = argparse.ArgumentParser(199        description="Unwarp document images using UVDoc grid-output ONNX model",200        formatter_class=argparse.RawDescriptionHelpFormatter,201        epilog="""202Examples:203    python example.py warped_doc.jpg unwarped_doc.jpg204    python example.py warped_doc.jpg unwarped_doc.jpg --model UVDoc_grid.onnx205        """206    )207 208    parser.add_argument(209        "input",210        help="Path to input warped document image"211    )212 213    parser.add_argument(214        "output",215        help="Path to save unwarped output image"216    )217 218    parser.add_argument(219        "--model", "-m",220        default=None,221        help="Path to UVDoc_grid.onnx model file (downloads from HuggingFace if not provided)"222    )223 224    args = parser.parse_args()225 226    # Validate input file exists227    if not Path(args.input).exists():228        print(f"Error: Input file not found: {args.input}")229        sys.exit(1)230 231    unwarp_document(args.input, args.output, args.model)232 233 234if __name__ == "__main__":235    main()236