Skip to content

Latest commit

Β 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Concrete Crack Segmentation with UNet

AI-powered deep learning for automatic crack detection in concrete structures

License: MIT PyTorch Python 3.9+ Status


πŸ”— Navigation

🌐 Live Demo πŸ“¦ Model Info πŸš€ Quick Start πŸ“Š Results
view view view view

πŸ“‹ Overview

A high-performance UNet-based deep learning model for detecting and segmenting cracks in concrete images. Trained on 800 annotated images with 25 epochs, achieving exceptional accuracy metrics.

Perfect for: Infrastructure inspection, bridge monitoring, building assessment, quality control.


πŸ“Š Results

Metric Score
Dice Score 99.77%
IoU Score 99.54%
F1 Score 99.77%
Precision 99.54%
Recall 100.00%
Training Loss 0.0162
Validation Loss 0.0139

🎯 Key Features

βœ… High-Performance UNet - 4-level encoder-decoder with BatchNorm and Dropout
βœ… Automatic Mask Inversion - Detects and handles inverted masks automatically
βœ… 8-Type Data Augmentation - Robust training with diverse transformations
βœ… Combined Loss Function - 60% Dice + 40% BCE for optimal segmentation
βœ… Production Ready - Easy inference with single function call
βœ… Comprehensive Metrics - Dice, IoU, F1, Precision, Recall validation
βœ… Well Documented - Complete notebook + inference script + model card


🌐 Live Demo

Try the interactive Gradio web interface: πŸ‘‰ Launch Demo on Hugging Face Spaces)

  • Upload any concrete image
  • Get instant segmentation results
  • Adjust detection threshold
  • No installation required!

πŸš€ Quick Start

Installation

# Clone the repository
git clone https://github.com/samir-m0hamed/concrete-crack-segmentation.git
cd concrete-crack-segmentation

# Install dependencies
pip install -r requirements.txt

Basic Usage

import torch
from PIL import Image
from inference import CrackSegmentationModel

# Initialize model
model = CrackSegmentationModel('unet_model_weights.pth')

# Make prediction on single image
prediction = model.predict('image.jpg', threshold=0.5)

# Access results
segmentation_mask = prediction['mask']          # Binary mask
probability_map = prediction['probability']    # Soft predictions
crack_percentage = prediction['crack_pct']     # Crack coverage %

Load from Hugging Face Hub

from huggingface_hub import hf_hub_download
import torch

# Download model from HF
model_path = hf_hub_download(
    repo_id="samir-mohamed/concrete-crack-segmentation",
    filename="unet_model_weights.pth"
)

# Load weights
model = torch.load(model_path)

Batch Processing

from torch.utils.data import DataLoader
from dataset import CrackDataset

# Load dataset
dataset = CrackDataset(
    images_path='path/to/images',
    masks_path='path/to/masks'
)
loader = DataLoader(dataset, batch_size=32)

# Process batch
for images, masks in loader:
    with torch.no_grad():
        predictions = model(images)

πŸ“ˆ Model Architecture

ImprovedUNet Structure

Input (3, 256, 256)
    ↓
Encoder Block 1: Conv(64) β†’ BatchNorm β†’ ReLU β†’ Dropout β†’ MaxPool
    ↓
Encoder Block 2: Conv(128) β†’ BatchNorm β†’ ReLU β†’ Dropout β†’ MaxPool
    ↓
Encoder Block 3: Conv(256) β†’ BatchNorm β†’ ReLU β†’ Dropout β†’ MaxPool
    ↓
Encoder Block 4: Conv(512) β†’ BatchNorm β†’ ReLU β†’ Dropout β†’ MaxPool
    ↓
Bottleneck: Conv(1024) β†’ Conv(1024)
    ↓
Decoder Block 1: UpConv(512) + Skip Connection β†’ Conv(512)
    ↓
Decoder Block 2: UpConv(256) + Skip Connection β†’ Conv(256)
    ↓
Decoder Block 3: UpConv(128) + Skip Connection β†’ Conv(128)
    ↓
Decoder Block 4: UpConv(64) + Skip Connection β†’ Conv(64)
    ↓
Output Conv (1, 256, 256) β†’ Sigmoid
    ↓
Output (1, 256, 256)

Architecture Details

Component Specification
Framework PyTorch 2.0+
Input Shape (3, 256, 256) RGB images
Output Shape (1, 256, 256) binary masks
Total Parameters ~7.8M
Model Size ~30 MB
Encoder Filters [64, 128, 256, 512]
Bottleneck Filters 1024
Activation ReLU (intermediate), Sigmoid (output)
Normalization BatchNorm2d
Regularization Dropout2d (p=0.2-0.3)
Inference Time ~50-100ms per image (GPU)

πŸŽ“ Training Details

Hyperparameters

optimizer = AdamW(
    lr=2e-3,
    weight_decay=1e-5
)

scheduler = CosineAnnealingLR(
    T_max=50,
    eta_min=1e-6
)

loss = CombinedLoss(
    bce_weight=0.4,
    dice_weight=0.6
)

training_config = {
    'batch_size': 16,
    'epochs': 25,
    'train_val_split': 0.8,
    'early_stopping_patience': 15,
    'image_size': (256, 256)
}

Data Augmentation Pipeline

Applied to training set only:

  • Random Flip: Horizontal & Vertical (p=0.5)
  • Random Rotation: Β±15 degrees
  • Random Affine: Translate Β±10%, Scale 0.8-1.2
  • Color Jitter: Brightness, contrast, saturation Β±0.2
  • Gaussian Blur: Οƒ: 0.1-2.0
  • Normalization: ImageNet statistics

Training Environment

GPU: NVIDIA CUDA-compatible (T4, A100, etc.)
VRAM: 6GB+
CPU: Intel i7 / AMD Ryzen
RAM: 16GB+
Runtime: ~17 minutes (25 epochs)

πŸ” Dataset Information

Concrete Crack Dataset

Property Value
Total Images 800
Image Format RGB JPG (256Γ—256)
Mask Format Binary PNG (256Γ—256)
Train/Val Split 80/20 (640/160 images)
Mask Values {0.6549 (cracks), 1.0 (background)}
Average Crack Area 0-3% per image
Special Feature 100% automatic mask inversion detection

Dataset Preprocessing

  1. Automatic Inversion Detection: Detects if masks are black=cracks or white=cracks
  2. Stratified Split: Maintains balanced distribution in train/val
  3. Image Normalization: ImageNet mean/std standardization
  4. Mask Format: Converted to normalized [0, 1] range

πŸ’» System Requirements

Minimum

  • Python 3.9+
  • 8GB RAM
  • CPU-capable machine
  • ~500MB disk space

Recommended

  • Python 3.10+
  • 16GB RAM
  • NVIDIA GPU with 6GB+ VRAM
  • CUDA 11.8+
  • ~1GB disk space (with model)

πŸ“¦ Dependencies

torch==2.0.0
torchvision==0.15.0
Pillow==9.5.0
numpy==1.24.3
opencv-python==4.8.0.74
matplotlib==3.7.2
tqdm==4.66.1
huggingface-hub>=0.17.0

Install all with:

pip install -r requirements.txt

πŸ“ Project Structure

concrete-crack-segmentation/
β”œβ”€β”€ Concreate_Crack_Segmentation.ipynb    # Main training notebook
β”œβ”€β”€ Dataset/
β”‚   β”œβ”€β”€ images/                           # 800 concrete images (256x256)
β”‚   └── masks/                            # Corresponding crack masks
β”œβ”€β”€ unet_model_weights.pth                # Trained model weights (118MB)
β”œβ”€β”€ requirements.txt                      # Python dependencies
β”œβ”€β”€ .gitattributes
└── README.md                             

πŸ”„ How It Works

Inference Pipeline

Input Image (any size)
    ↓
Resize to 256Γ—256
    ↓
Convert to tensor
    ↓
Normalize (ImageNet stats)
    ↓
Model forward pass
    ↓
Apply sigmoid activation
    ↓
Threshold at 0.5 (adjustable)
    ↓
Output: Binary segmentation mask

Example Prediction

import torch
from PIL import Image
import torchvision.transforms as transforms

# Load and preprocess
image = Image.open('concrete.jpg').convert('RGB')
image = transforms.Resize((256, 256))(image)

# Normalize with ImageNet stats
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=mean, std=std)
])

# Predict
image_tensor = transform(image).unsqueeze(0)
with torch.no_grad():
    logits = model(image_tensor)
    prediction = torch.sigmoid(logits)
    binary_mask = (prediction > 0.5).float()

# Get statistics
crack_pixels = binary_mask.sum().item()
crack_percentage = (crack_pixels / (256 * 256)) * 100

βš™οΈ Advanced Configuration

Adjusting Detection Sensitivity

# Lower threshold = more sensitive (catches smaller cracks)
# Higher threshold = less sensitive (only major cracks)

threshold = 0.3  # More sensitive
mask_sensitive = (prediction > threshold).float()

threshold = 0.7  # Less sensitive  
mask_strict = (prediction > threshold).float()

Custom Training

To retrain on your own dataset:

# Modify in notebook:
BATCH_SIZE = 32              # Increase for more data
NUM_EPOCHS = 50              # More epochs for convergence
LEARNING_RATE = 1e-3         # Adjust learning rate
IMG_SIZE = (512, 512)        # Different image size

Transfer Learning

# Load pre-trained weights
model = ImprovedUNet(...)
model.load_state_dict(torch.load('unet_model_weights.pth'))

# Freeze encoder for transfer learning
for param in model.encoder.parameters():
    param.requires_grad = False

# Train only decoder
optimizer = torch.optim.Adam(
    filter(lambda p: p.requires_grad, model.parameters()),
    lr=1e-4
)

πŸ› Troubleshooting

Issue: "DataLoader worker exited unexpectedly" (Windows/Jupyter)

Solution: Set num_workers=0 in DataLoader

loader = DataLoader(dataset, batch_size=16, num_workers=0)

Issue: CUDA out of memory (OOM)

Solution: Reduce batch size

BATCH_SIZE = 8  # Instead of 16
loader = DataLoader(dataset, batch_size=BATCH_SIZE)

Issue: Loss stays high / Model not converging

Solution: Check mask format

# Verify masks are normalized to [0, 1]
print(mask_tensor.min(), mask_tensor.max())  # Should be [0, 1]

# Verify mask format matches dataset
print((mask_tensor == 0).sum() / mask_tensor.numel() * 100, "% background")

Issue: Model gives all zeros/ones predictions

Solution: Check input normalization

# Verify ImageNet normalization applied
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
transform = transforms.Normalize(mean=mean, std=std)

πŸ“– Documentation

  • MODEL_CARD.md - Detailed model information & performance metrics
  • Concreate_Crack_Segmentation.ipynb - Complete training notebook with explanations

πŸš€ Deployment

Existing Space: https://huggingface.co/spaces/samir-mohamed/concrete-crack-segmentation


πŸ“ˆ Performance Comparison

Metrics Over Training

Epoch 1:   Dice: 45.23%, Loss: 0.1298
Epoch 5:   Dice: 92.15%, Loss: 0.0456
Epoch 10:  Dice: 97.63%, Loss: 0.0234
Epoch 15:  Dice: 99.21%, Loss: 0.0168
Epoch 20:  Dice: 99.68%, Loss: 0.0152
Epoch 25:  Dice: 99.77%, Loss: 0.0139  βœ“ Final

Model converges quickly and stabilizes by epoch 7.


🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“ Citation

If you use this model in your research, please cite:

@software{concrete_crack_segmentation_2026,
  title={Concrete Crack Segmentation with UNet},
  author={samir-m0hamed},
  year={2026},
  url={https://github.com/samir-m0hamed/concrete-crack-segmentation}
}

πŸ“„ License

MIT License .

This project is open source and available for educational and commercial use.


πŸ™ Acknowledgments

  • Architecture: Based on UNet by Ronneberger et al. (2015)
  • Loss Function: Dice Loss by Milletari et al. (2016)
  • Dataset: Concrete Crack Dataset (800 annotated images)
  • Framework: PyTorch, TorchVision

πŸ“§ Support & Contact


Made for infrastructure inspection & structural health monitoring

Last Updated: March 28, 2026 | Status: βœ… Production Done

About

AI-powered crack detection in concrete using UNet. Achieves 99.77% Dice score with automatic mask inversion and data augmentation. Includes Gradio web interface for easy deployment. Production-ready with PyTorch for infrastructure inspection and structural monitoring.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages