Skip to main content

A deep learning crack detection package supporting U-Net and DeepCrack models with PyTorch and ONNX backends.

Project description

findcrack

findcrack is a deep learning crack detection package designed for pixel-level segmentation on high-resolution images. It supports U-Net and DeepCrack architectures, providing an easy-to-use API for inference, model caching, and multi-backend execution (PyTorch & ONNX).


Features

  • Pre-trained Model Zoo: Fetch pre-trained model weights (e.g., Seg_UNET_CFD_actual_v1, Seg_UNET_CFD_actual_v2) dynamically on demand.
  • Unified Backend Engine: Seamlessly executes either PyTorch (.pth/.pt) or ONNX (.onnx) models using the same standard interface.
  • Sliding-Window Inference: Efficiently process ultra-high-resolution images by dividing them into overlapping patches.
  • Gaussian & Average Blending: Reconstructs the full image from patches using overlapping Gaussian blending filters to eliminate edge-seam artifacts.
  • Test-Time Augmentation (TTA): Performs multi-way augmentations (original, horizontal flip, vertical flip, and rotations) to produce highly robust prediction masks.
  • Validation Metrics: Compute standard segmentation metrics like IoU, Dice Coefficient, Precision, Recall, and Pixel Accuracy.

Installation

By default, findcrack does not require PyTorch or its related packages, keeping the installation small and lightweight for ONNX-only inference.

Base Installation (ONNX & NumPy only)

To run ONNX models without PyTorch:

# Install via pip
pip install findcrack

# Or using uv
uv add findcrack

PyTorch Support (Standard Installation)

To enable PyTorch models and training support, install the standard extra (which includes PyTorch, torchvision, and torchaudio):

# Install via pip
pip install "findcrack[standard]"

# Or using uv
uv add findcrack --extra standard

Quickstart

Here is how to load a pre-trained model and run crack detection on a large image:

import cv2
from findcrack import CrackInferencePipeline, load_model

# 1. Load a pre-trained model from the official registry (or use your own URL)
# The weights are downloaded dynamically from GitHub releases on first use.
model = load_model("Seg_UNET_CFD_actual_v1", device="cuda")

# 2. Setup the inference pipeline
pipeline = CrackInferencePipeline(
    model=model,
    device="cuda",
    patch_size=512,
    overlap_ratio=0.2,
    confidence_threshold=0.5,
    use_tta=True  # Enables multi-way Test-Time Augmentation
)

# 3. Perform inference
results = pipeline.predict("path/to/high_res_concrete.jpg")

# The results dictionary contains:
# - results["original_image"]: Original RGB image (numpy array)
# - results["confidence_map"]: Float probability map [0.0 - 1.0]
# - results["binary_mask"]: Binary segmentation mask [0 or 255]
# - results["overlay"]: Original image with a colored transparent overlay on the cracks
# - results["bounding_boxes"]: List of [xmin, ymin, xmax, ymax] coordinates for detected crack components
# - results["contours"]: List of segmentation contours for detected cracks
# - results["visualization"]: Original image with bounding boxes drawn and contours outlined

# Save the output mask, overlay, and visual bounding boxes
cv2.imwrite("detected_cracks.png", results["binary_mask"])
cv2.imwrite("detected_cracks_overlay.png", results["overlay"])
cv2.imwrite("detected_cracks_visualization.png", results["visualization"])

API Reference

Model Loading & Caching

load_model(variant: str, device: str = "cpu", force_download: bool = False, architecture = None, **kwargs)

Loads a model variant from the local registry or directly from a remote HTTP(S) URL.

  • Parameters:
    • variant: The name of a registered variant (e.g., "Seg_UNET_CFD_actual_v1") or a direct HTTP(S) URL to a weights file.
    • device: Target execution device ("cpu", "cuda", or "mps").
    • force_download: If True, re-downloads weights even if cached locally.
    • architecture: PyTorch architecture class (e.g., UNet, DeepCrack) - required only if loading a raw .pth/.pt file from a custom URL.
from findcrack import load_model, UNet

# Load custom model weights directly from an external URL
model = load_model(
    variant="https://my-domain.com/custom_unet.pth",
    architecture=UNet,
    device="cuda"
)

list_models()

Returns a list of all pre-trained models available in the built-in registry.

register_model(name: str, url: str, architecture = None, kwargs: dict = None, backend: str = "pytorch")

Registers a custom variant dynamically at runtime.


Pipeline Configuration

CrackInferencePipeline(model, device: str = "cuda", patch_size: int = 512, overlap_ratio: float = 0.2, confidence_threshold: float = 0.5, use_tta: bool = False, preprocessor = None, use_clahe: bool = True, clahe_clip_limit: float = 2.0, overlay_alpha: float = 0.4, overlay_color: tuple = (255, 0, 0), box_color: tuple = (0, 255, 0), box_thickness: int = 2, contour_color: tuple = (0, 0, 255), contour_thickness: int = 2)

Handles sliding window preprocessing, execution, TTA, and patching reconstruction. Can be configured with a custom Preprocessor or custom CLAHE parameters.

  • Parameters:
    • model: Loaded PyTorch model or ONNX wrapper model.
    • device: Device to execute on ("cpu", "cuda", etc.).
    • patch_size: Size of the sliding window patch (e.g. 512 or 256). Inputs will automatically scale to match the model's expected shape if mismatching.
    • overlap_ratio: Overlap percentage between consecutive sliding windows (e.g. 0.2).
    • confidence_threshold: Probability threshold to label a pixel as a crack.
    • use_tta: Toggle Test-Time Augmentation (flips and rotations).
    • use_clahe: Apply LAB-CLAHE contrast enhancement globally.
    • overlay_alpha: Transparency level for the output overlay mask.
    • overlay_color: RGB tuple color for the overlay mask (default red: (255, 0, 0)).
    • box_color: RGB tuple color for the bounding boxes (default green: (0, 255, 0)).
    • contour_color: RGB tuple color for the segmentation contours (default blue: (0, 0, 255)).

Image Preprocessing

Preprocessor(use_clahe: bool = True, clip_limit: float = 2.0, tile_grid_size: Tuple[int, int] = (8, 8), mean: Tuple[float, float, float] = (0.485, 0.456, 0.406), std: Tuple[float, float, float] = (0.229, 0.224, 0.225), additional_transforms: List = None)

A configuration-driven preprocessing class encapsulating LAB-CLAHE contrast enhancement and Albumentations normalization/tensorization.

from findcrack import Preprocessor

# Custom preprocessor setup
preprocessor = Preprocessor(
    use_clahe=True,
    clip_limit=3.0,
    tile_grid_size=(4, 4)
)

# Apply CLAHE to global image (reduces patch boundary mismatch)
enhanced_image = preprocessor.enhance_contrast(image)

# Normalize and convert a patch to a PyTorch tensor
patch_tensor = preprocessor.transform_patch(patch_rgb)

CLI Usage

You can run findcrack.preprocess as a script to batch apply LAB-CLAHE contrast enhancement to an image or directory:

# Process a single image
python -m findcrack.preprocess input.jpg output.jpg --clip-limit 2.0 --tile-grid-size 8 8

# Process a directory of images
python -m findcrack.preprocess path/to/input_dir path/to/output_dir

Advanced End-to-End Usage

If you need fine-grained control over patching parameters, custom preprocessing transformations, or model thresholding, you can run the pipeline manually. This is particularly useful when handling arbitrary non-square patch sizes or injecting custom Albumentations transforms.

Here is a full example of manual patch extraction, inference, and blending on an arbitrarily-sized image:

import numpy as np
import torch
from PIL import Image
import albumentations as A

from findcrack import load_model
from findcrack.preprocess import Preprocessor, PatchExtractor
from findcrack.postprocess import PatchBlender

# 1. Load pre-trained model and set to evaluation mode
device = "cuda" if torch.cuda.is_available() else "cpu"
model = load_model("Seg_UNET_CFD_actual_v1", device=device)
model.eval()

# 2. Instantiate preprocessor with custom Albumentations transforms
custom_preprocessor = Preprocessor(
    use_clahe=True,
    clip_limit=3.0,
    tile_grid_size=(4, 4),
    mean=(0.485, 0.456, 0.406),
    std=(0.229, 0.224, 0.225),
    additional_transforms=[
        A.GaussianBlur(p=0.5)  # E.g., custom blur filter
    ]
)

# 3. Read input image of any arbitrary dimensions
img_path = "large_image.jpg"
image = np.array(Image.open(img_path).convert("RGB"))
height, width, _ = image.shape

# 4. Initialize patch extractor and blender for arbitrary size
patch_size = (512, 512)  # Can be a Tuple (height, width) or an integer
overlap_ratio = 0.25      # overlap percentage between consecutive steps

extractor = PatchExtractor(patch_size=patch_size, overlap_ratio=overlap_ratio)
blender = PatchBlender(shape=(height, width))

# Preprocess image contrast globally before patching to reduce boundary artifacts
enhanced_image = custom_preprocessor.enhance_contrast(image)

# 5. Extract patches and feed to the model
with torch.no_grad():
    for patch_rgb, coordinates in extractor.extract(enhanced_image):
        # Normalize and transform patch to tensor
        patch_tensor = custom_preprocessor.transform_patch(patch_rgb).to(device)
        
        # Forward pass (adding batch dimension and squeezing logits)
        logits = model(patch_tensor.unsqueeze(0))
        pred_prob = torch.sigmoid(logits).squeeze()
        
        # Add predicted patch probabilities back to the blender
        blender.add(pred_prob.cpu().numpy(), coordinates)

# 6. Merge/blend the overlapping patch maps into the full-size confidence map
confidence_map = blender.merge()

# 7. Convert confidence map to a binary mask using custom thresholding
confidence_threshold = 0.5
binary_mask = (confidence_map > confidence_threshold).astype(np.uint8) * 255

Demos and Real-World Validation

findcrack includes a modular demo suite to quickly validate end-to-end inference using mock data or real images.

Folder Layout

demo/
├── generator.py     # Utilities for generating mock concrete test images
├── runner.py        # Handles model resolution (and fallback), pipeline runs, and output saving
└── demo.py          # Main CLI orchestration entrypoint

How to Run:

# 1. Run the default model variant on a generated mock image
uv run python demo/demo.py

# 2. Specify a model variant from the registry (e.g. your YOLOv8/v11 segmentation model)
uv run python demo/demo.py --model Det_YOLOv26n-seg_crack-dataset_v1

# 3. Process a real image file using a specific model
uv run python demo/demo.py --model Det_YOLOv26n-seg_crack-dataset_v1 --image path/to/cracks.jpg

# example running
uv run python demo/demo.py --model Det_YOLOv26n-seg_crack-dataset_v1 --image "./demo/images/CFD_001.jpg"

All predictions are saved inside the root-level output/ directory:

  • output/<image_name>_mask.png: Binary prediction mask.
  • output/<image_name>_overlay.png: Transparent overlay highlighting cracks on the original image.
  • output/<image_name>_visualization.png: Original image with bounding boxes drawn and contour boundaries outlined.

Directory Structure

demo/                    # Modular demo scripts and mock generators
src/
└── findcrack/
    ├── __init__.py          # Main API endpoints (load_model, CrackInferencePipeline, etc.)
    ├── evaluation/          # Evaluation tools and metrics package
    │   ├── __init__.py      # Evaluation module exports
    │   └── metrics.py       # Segmentation evaluation metrics (IoU, Dice, etc.)
    ├── inference/           # Inference pipeline and test-time augmentation (TTA)
    │   ├── __init__.py      # Inference exports
    │   ├── pipeline.py      # Crack Inference Pipeline wrapper
    │   └── tta.py           # Test-Time Augmentation forward pass routines
    ├── postprocess/         # Postprocessing and patch blending package
    │   ├── __init__.py      # Postprocess exports
    │   └── blending.py      # PatchBlender class for merging patches
    ├── preprocess/          # Image preprocessing & patching package
    │   ├── __init__.py      # Preprocess module exports
    │   ├── __main__.py      # CLI for running preprocessing scripts
    │   ├── clahe.py         # LAB-CLAHE contrast enhancement
    │   ├── patching.py      # Sliding window patch extraction
    │   ├── preprocessor.py  # Unified Preprocessor class wrapper
    │   └── transforms.py    # Image normalization and albumentations setup
    └── models/
        ├── __init__.py      # Model module exports
        ├── unet.py          # U-Net model definition
        ├── deepcrack.py     # DeepCrack model definition
        ├── onnx_wrapper.py  # Wrapper for running ONNX models as nn.Modules
        └── zoo.py           # Remote weight registry and cached loaders

License

This project is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

findcrack-0.1.5.tar.gz (27.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

findcrack-0.1.5-py3-none-any.whl (25.3 kB view details)

Uploaded Python 3

File details

Details for the file findcrack-0.1.5.tar.gz.

File metadata

  • Download URL: findcrack-0.1.5.tar.gz
  • Upload date:
  • Size: 27.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for findcrack-0.1.5.tar.gz
Algorithm Hash digest
SHA256 b0941f9e26cf4d56429c01efc6aaac6a0a502fc803b8abec852cd93d2da99378
MD5 b6154b98850cfe8b37fafce974e79937
BLAKE2b-256 02e33d9d1a28e62f4ffebcdd625f093c2e07da83613028efecb80d4cdd512d04

See more details on using hashes here.

Provenance

The following attestation bundles were made for findcrack-0.1.5.tar.gz:

Publisher: release.yml on StrikerEurika/findcrack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file findcrack-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: findcrack-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 25.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for findcrack-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 4d0cf9b0ca6d31048e7995cac37aa9f34f54a111c545c544fed2719f94f534d1
MD5 c63261dd31e2d536ba905963c5417ec6
BLAKE2b-256 675d399aa8d1dded86b44a6932156b9b184aae20b413bd140e329da552415b7b

See more details on using hashes here.

Provenance

The following attestation bundles were made for findcrack-0.1.5-py3-none-any.whl:

Publisher: release.yml on StrikerEurika/findcrack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page