Claude
Skills
Sign in
Back

defect-detection-ai

Included with Lifetime
$97 forever

AI-powered construction defect detection using computer vision. Identify cracks, spalling, corrosion, and other defects in concrete, steel, and building components from images and video.

Image & Video

What this skill does

# AI Defect Detection

## Overview

This skill implements deep learning-based defect detection for construction quality control. Analyze images and video to automatically identify structural and surface defects, classify severity, and generate inspection reports.

**Detectable Defects:**
- Concrete: Cracks, spalling, honeycombing, efflorescence
- Steel: Corrosion, weld defects, deformation
- Masonry: Mortar deterioration, displacement
- Finishes: Surface defects, coating failures
- MEP: Insulation damage, pipe corrosion

## Quick Start

```python
import torch
import torch.nn as nn
from torchvision import transforms, models
from PIL import Image
from dataclasses import dataclass
from typing import List, Dict, Tuple
from enum import Enum

class DefectType(Enum):
    CRACK = "crack"
    SPALLING = "spalling"
    CORROSION = "corrosion"
    HONEYCOMBING = "honeycombing"
    EFFLORESCENCE = "efflorescence"
    DEFORMATION = "deformation"
    SURFACE_DAMAGE = "surface_damage"
    NO_DEFECT = "no_defect"

class SeverityLevel(Enum):
    MINOR = "minor"
    MODERATE = "moderate"
    SEVERE = "severe"
    CRITICAL = "critical"

@dataclass
class DefectDetection:
    defect_type: DefectType
    confidence: float
    severity: SeverityLevel
    bounding_box: Tuple[int, int, int, int]  # x1, y1, x2, y2
    area_ratio: float  # Defect area as ratio of image

# Simple classifier using pretrained model
class SimpleDefectClassifier:
    def __init__(self, num_classes: int = 8):
        self.model = models.resnet18(pretrained=True)
        self.model.fc = nn.Linear(self.model.fc.in_features, num_classes)
        self.model.eval()

        self.transform = transforms.Compose([
            transforms.Resize((224, 224)),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
        ])

        self.classes = list(DefectType)

    def predict(self, image_path: str) -> DefectDetection:
        """Classify defect in image"""
        image = Image.open(image_path).convert('RGB')
        input_tensor = self.transform(image).unsqueeze(0)

        with torch.no_grad():
            outputs = self.model(input_tensor)
            probs = torch.softmax(outputs, dim=1)
            confidence, predicted = torch.max(probs, 1)

        defect_type = self.classes[predicted.item()]

        return DefectDetection(
            defect_type=defect_type,
            confidence=confidence.item(),
            severity=self._estimate_severity(confidence.item()),
            bounding_box=(0, 0, image.width, image.height),
            area_ratio=1.0
        )

    def _estimate_severity(self, confidence: float) -> SeverityLevel:
        if confidence > 0.9:
            return SeverityLevel.CRITICAL
        elif confidence > 0.7:
            return SeverityLevel.SEVERE
        elif confidence > 0.5:
            return SeverityLevel.MODERATE
        else:
            return SeverityLevel.MINOR

# Usage
classifier = SimpleDefectClassifier()
# result = classifier.predict("concrete_image.jpg")
# print(f"Defect: {result.defect_type.value}, Confidence: {result.confidence:.2%}")
```

## Comprehensive Defect Detection System

### Object Detection Model

```python
import torch
import torch.nn as nn
from torchvision import transforms
from torchvision.models.detection import fasterrcnn_resnet50_fpn
from PIL import Image
import numpy as np
from dataclasses import dataclass, field
from typing import List, Dict, Tuple, Optional
from datetime import datetime
import json

@dataclass
class BoundingBox:
    x1: int
    y1: int
    x2: int
    y2: int

    @property
    def width(self) -> int:
        return self.x2 - self.x1

    @property
    def height(self) -> int:
        return self.y2 - self.y1

    @property
    def area(self) -> int:
        return self.width * self.height

    @property
    def center(self) -> Tuple[int, int]:
        return ((self.x1 + self.x2) // 2, (self.y1 + self.y2) // 2)

@dataclass
class DetectedDefect:
    defect_id: str
    defect_type: DefectType
    confidence: float
    severity: SeverityLevel
    bounding_box: BoundingBox
    area_sqm: Optional[float] = None
    dimensions_mm: Optional[Tuple[float, float]] = None
    metadata: Dict = field(default_factory=dict)

@dataclass
class InspectionResult:
    inspection_id: str
    image_path: str
    timestamp: datetime
    location: str
    element_type: str
    defects: List[DetectedDefect]
    overall_condition: str
    recommended_actions: List[str]

class DefectDetectionModel:
    """Deep learning defect detection with object detection"""

    DEFECT_CLASSES = {
        1: DefectType.CRACK,
        2: DefectType.SPALLING,
        3: DefectType.CORROSION,
        4: DefectType.HONEYCOMBING,
        5: DefectType.EFFLORESCENCE,
        6: DefectType.DEFORMATION,
        7: DefectType.SURFACE_DAMAGE
    }

    def __init__(self, model_path: str = None, device: str = 'cpu'):
        self.device = torch.device(device)

        # Initialize Faster R-CNN
        self.model = fasterrcnn_resnet50_fpn(pretrained=True)

        # Modify for our classes
        num_classes = len(self.DEFECT_CLASSES) + 1  # +1 for background
        in_features = self.model.roi_heads.box_predictor.cls_score.in_features
        self.model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)

        if model_path:
            self.model.load_state_dict(torch.load(model_path, map_location=self.device))

        self.model.to(self.device)
        self.model.eval()

        self.transform = transforms.Compose([
            transforms.ToTensor()
        ])

    def detect(self, image_path: str, confidence_threshold: float = 0.5,
               pixels_per_mm: float = None) -> List[DetectedDefect]:
        """Detect defects in image"""
        image = Image.open(image_path).convert('RGB')
        image_tensor = self.transform(image).to(self.device)

        with torch.no_grad():
            predictions = self.model([image_tensor])

        pred = predictions[0]
        defects = []

        for i in range(len(pred['boxes'])):
            score = pred['scores'][i].item()

            if score < confidence_threshold:
                continue

            label = pred['labels'][i].item()
            box = pred['boxes'][i].cpu().numpy()

            defect_type = self.DEFECT_CLASSES.get(label, DefectType.SURFACE_DAMAGE)

            bbox = BoundingBox(
                x1=int(box[0]),
                y1=int(box[1]),
                x2=int(box[2]),
                y2=int(box[3])
            )

            # Calculate dimensions if scale provided
            dimensions_mm = None
            if pixels_per_mm:
                width_mm = bbox.width / pixels_per_mm
                height_mm = bbox.height / pixels_per_mm
                dimensions_mm = (width_mm, height_mm)

            severity = self._classify_severity(defect_type, bbox, image.size)

            defects.append(DetectedDefect(
                defect_id=f"DEF-{i:04d}",
                defect_type=defect_type,
                confidence=score,
                severity=severity,
                bounding_box=bbox,
                dimensions_mm=dimensions_mm
            ))

        return defects

    def _classify_severity(self, defect_type: DefectType,
                          bbox: BoundingBox,
                          image_size: Tuple[int, int]) -> SeverityLevel:
        """Classify defect severity based on type and size"""
        image_area = image_size[0] * image_size[1]
        defect_ratio = bbox.area / image_area

        # Severity thresholds by defect type
        thresholds = {
            DefectType.CRACK: {'critical': 0.1, 'severe': 0.05, 'moderate': 0.02},
            DefectType.SPALLING: {'critical': 0.15, 'severe': 0.08, 'moderate': 0.03},
            DefectType.CORROSION: {'critical': 0.2, 'severe': 0.1, 'moderate': 0.05},
            DefectType.HONEYCOMBING: {'critical': 0.1, 'severe': 0.05, 'moderate': 0.02},
     

Related in Image & Video