Team Ai
Datasetpublic

ibm-research/cif-dataset

Cracks in the Foundation A civil-infrastructure visual inspection dataset for instance segmentation with 6 defect/condition categories: Algae · Crack · Net-Crack · Crack with Precipitation · Rust · Spalling Each sample is either a full-resolution inspection image or a 1024×1024 tile derived from one. Tiled samples carry extra fields (tile_row, tile_col, file_name_original, …) that are None for full-resolution samples. Splits Each split is its own parquet shard… See the full description on the dataset page: https://huggingface.co/datasets/ibm-research/cif-dataset.

sourceHugging Facecdla-permissive-2.0updated 5mo agoView on Hugging Face
8likes2.5kdownloads
Dataset Card

Cracks in the Foundation

A civil-infrastructure visual inspection dataset for instance segmentation with 6 defect/condition categories: Algae · Crack · Net-Crack · Crack with Precipitation · Rust · Spalling

Each sample is either a full-resolution inspection image or a 1024×1024 tile derived from one. Tiled samples carry extra fields (tile_row, tile_col, file_name_original, …) that are None for full-resolution samples.


Splits

Each split is its own parquet shard and its own dataset config. load_dataset(repo) returns all six in a DatasetDict. Naming a config — load_dataset(repo, "train_tiled", split="train") — is a true selective download, fetching only that shard.

SplitContents
train_fullfull-resolution training images
val_fullfull-resolution validation images
test_fullfull-resolution test images
train_tiled1024×1024 tiles, training
val_tiled1024×1024 tiles, validation
test_tiled1024×1024 tiles, test

Load

python
from datasets import load_dataset

# Load all six splits at once (single DatasetDict):
all_splits = load_dataset("ibm-research/cif-dataset")

# Selective: download only the tiled training shard.
# Each split is also exposed as its own config — naming a config
# downloads only its parquet files.
ds = load_dataset("ibm-research/cif-dataset", "train_tiled", split="train")

Schema

Every sample has the same fields regardless of split:

python
sample = ds[0]

sample["image_id"]           # int   — unique image identifier
sample["image"]              # PIL.Image
sample["file_name"]          # str   — original filename
sample["width"]              # int   — image width in pixels
sample["height"]             # int   — image height in pixels

# Tiled-only fields (None for full-resolution samples):
sample["tile_row"]           # int | None  — top-left row of the tile in the original image
sample["tile_col"]           # int | None  — top-left column
sample["file_name_original"] # str | None  — filename of the parent image
sample["width_original"]     # int | None  — parent image width
sample["height_original"]    # int | None  — parent image height

# Annotations (COCO convention):
obj = sample["objects"]
obj["id"]            # List[int]
obj["category_id"]   # List[int]   — 1=Algae 2=Crack 3=Crack(net) 4=Crack+precip 5=Rust 6=Spalling
obj["bbox"]          # List[[x, y, w, h]]   — pixels, COCO origin (top-left)
obj["area"]          # List[float]
obj["iscrowd"]       # List[int]
obj["segmentation"]  # List[List[List[float]]]  — polygons as flat [x1,y1,x2,y2,...] lists

Distinguish sample type at runtime:

python
is_tile = sample["tile_row"] is not None

Visualize

bash
pip install datasets fiftyone
python
import tempfile
from pathlib import Path

import fiftyone as fo
from datasets import load_dataset

CATS = {1: "Algae", 2: "Crack", 3: "Crack (net-crack)",
        4: "Crack with precipitation", 5: "Rust", 6: "Spalling"}

ds = load_dataset("ibm-research/cif-dataset", split="test_full")

tmp = Path(tempfile.mkdtemp())
fo_ds = fo.Dataset("cif_test_full", overwrite=True)

for s in ds:
    img_path = tmp / Path(s["file_name"]).name
    s["image"].save(img_path)
    W, H = s["width"], s["height"]
    dets, polys = [], []
    obj = s["objects"]
    for i, cid in enumerate(obj["category_id"]):
        label = CATS.get(cid, str(cid))
        x, y, w, h = obj["bbox"][i]
        dets.append(fo.Detection(label=label, bounding_box=[x/W, y/H, w/W, h/H]))
        for poly in obj["segmentation"][i]:
            if len(poly) < 6:
                continue
            pts = [[poly[j]/W, poly[j+1]/H] for j in range(0, len(poly), 2)]
            polys.append(fo.Polyline(label=label, points=[pts], filled=True, closed=True))
    fo_ds.add_sample(fo.Sample(
        filepath=str(img_path),
        detections=fo.Detections(detections=dets),
        segmentations=fo.Polylines(polylines=polys),
    ))

session = fo.launch_app(fo_ds)
session.wait()

Opens the FiftyOne app at http://localhost:5151 with bounding boxes and segmentation overlays.


Acknowledgment

We would like to sincerely thank Finn Bormlund and Svend Gjerding (Sund & Baelt), Jens Häggström (Trafikverket), Raphael von Thiessen (Innovation-Sandbox for AI, Office for Economy, Kanton Zürich), and the Dübendorf Air Base for granting us the opportunity to collect, analyze, and disseminate the images and defect data included in this publication.


Citation

bibtex
@dataset{cracks_in_the_foundation,
  author    = {},
  title     = {Cracks in the Foundation},
  year      = {2025},
  publisher = {HuggingFace},
  url       = {https://huggingface.co/datasets/ibm-research/cif-dataset},
}