Datasets & Benchmarks

DTU MVS

The DTU Robot Image Data multi-view stereo set, objects photographed by a robot arm from 49 or 64 positions under seven lightings with structured-light reference scans; its accuracy and completeness protocol as the official MATLAB code computes it, the scene lists used by learned methods, and its terms.

intermediate

DTU MVS is the multi-view stereo data set of the DTU Robot Image Data collection at the Technical University of Denmark: small scenes of objects on a table, photographed by a camera on an industrial robot arm from 49 or 64 calibrated positions under seven lighting conditions, with a structured-light scan from every position as reference geometry. The data were captured in 2013 and published at CVPR 2014 by Jensen, Dahl, Vogiatzis, Tola and Aanæs, and the extended journal version by Aanæs et al. appeared in the International Journal of Computer Vision in 2016. The benchmark scores a reconstruction by its accuracy and completeness, the two one-sided nearest-neighbour distances that the Chamfer distance averages, restricted by an observability mask and a ground plane and summarized by a mean and a median. Learned methods, from SurfaceNet (Ji et al., 2017) and MVSNet (Yao et al., 2018) on, also made it a training set, and the scan lists SurfaceNet defined and MVSNet adopted became what pixelNeRF’s authors call the standard split introduced in MVSNet.

Purpose

The benchmarks before it, the Middlebury multi-view evaluation of Seitz et al. (2006) and the outdoor building scenes of Strecha et al. (2008), had few scenes, mostly well-textured and close to diffuse. Jensen et al. (2014) changed the question. Where earlier benchmarks asked which algorithm works best on a given scene, they asked which kinds of scene a given algorithm handles and which scene properties make reconstruction fail. That needs many scenes with controlled variation in texture, reflectance, geometry and lighting, all imaged from the same viewpoints. The 2016 version adds an analysis of variance over the 80 evaluated scenes to show that differences between methods, meshing and lighting are statistically significant, which the authors present as a main contribution. The authors call the scans “reference data” rather than ground truth, because they are physical measurements too.

Dataset Size

Item Count or value Source
Scenes published 124 Official page (as of October 2026)
Scenes in the papers’ evaluation 80 Both papers, official page
Camera positions 49 in 59 of the 80 scenes, 64 in 21 Both papers
Lighting conditions per position 7 IJCV 2016 §3.5, official page
Image size 1600 × 1200, 8-bit RGB Official page; the papers write 1200 × 1600
Reference points per scene 13.4 million on average; the released stl files are already thinned to 0.2 mm Both papers; comment in PointCompareMain.m
Scene-type groups 16 model houses, 7 groceries, 11 vegetables, 6 building materials, 7 stuffed animals IJCV 2016 Table 2 (the §3.1 text differs)

The official page says that the 44 scenes beyond the 80 are mainly objects rotated and scanned four times at 90° intervals, which allow 360° models, and that a few scenes were left out of the evaluation for low quality. The ReadMe in the download lists eight such rotation groups (scans 55–58, 65–68, 69–73, 106–109, 110–113, 114–117, 118–121 and 122–125; the third spans five scan numbers). Scan numbers run from 1 to 128: the archive’s file index has observability masks for scans 1–77 and 82–128, 124 in all. The IJCV text (§3.1) and its Table 2 disagree on three scene-type groups: the text lists 11 groceries, 6 fruit and vegetables and 7 building materials, against 7, 11 and 6 in the table. IJCV section and table numbers in this article follow the authors’ manuscript linked from the official publications page.

The downloads are split into SampleSet (6.3 GB: ReadMe, calibration, projection matrices, observability masks, evaluation code, and all data for scans 1 and 6), Points (6.3 GB, the reference point clouds), Points_MVS (45 GB, the point clouds of the three baseline methods), Surfaces (28 GB, their Poisson meshes), Cleaned (136 GB, images corrected for dead pixels and dark current) and Rectified (123 GB, the cleaned images corrected for radial distortion).

Capture

A six-axis industrial robot, enclosed in a black box against stray light (official home page), carried a structured-light head of two cameras and a projector; the images come from one of the two cameras. The positions lie on a sphere of radius 50 cm, about 35 cm from the scene surfaces; the 64-position scenes add 15 positions on a concentric sphere of radius 65 cm to study scale change (IJCV §3.2). Camera parameters were estimated with Bouguet’s Camera Calibration Toolbox for MATLAB from a checkerboard, and the reported positions are the calibrated ones, not those commanded to the robot. The ReadMe says that 94 positions were calibrated, of which the first 49 or 64 were used. Over ten calibrations in the two months of capture, the reprojection error was 0.067 pixels in both papers. The two papers give different standard deviations for the camera positions, 0.0031 mm (CVPR) and 0.0552 mm (IJCV).

Lighting comes from LEDs in the ceiling of the box, switched in groups to give seven conditions from directional to near-diffuse. The CVPR paper counts 18 LEDs and used only the images with all of them on; the IJCV paper counts 16, gives their azimuth and elevation (Table 1), and calls pattern 4, with all LEDs on, an emulation of diffuse light. In a few extreme positions the robot shaded some of the LEDs. Image files are numbered 0–6 by lighting; the ReadMe says the most diffuse is the one marked “3”, which in our reading is pattern 4 counted from zero.

The reference scans used binary stripe encoding (CVPR) or binary Gray code (IJCV), one scan from each camera position, merged per scene. Scanning a bowling ball gave a standard deviation of 0.17 mm for the estimated sphere centre and 0.14 mm for surface points, about 0.6 pixels. The scans cover only the front of each object and have holes from self-occlusion and from regions where the structured-light images were badly underexposed. Very thin structures were left out because the authors doubted that the scanner would measure them well (IJCV §3.1).

Annotation Types

  • Reference point clouds (stl###_total.ply), one per scan, in the frame of the scanner’s left camera; the colour images come from the right camera, and the supplied projection matrices map into the reference frame (ReadMe).
  • Calibration: intrinsics and extrinsics from the toolbox and a 3 × 4 projection matrix per position.
  • Observability masks (ObsMask<scan>_10.mat): a voxel grid, its bounding box and resolution, one per scan.
  • Ground planes (Plane<scan>.mat): a manually placed plane for each of the 80 evaluated scans, separating the object from the table.
  • Baseline reconstructions: point clouds from Campbell et al. (2008), Furukawa and Ponce (2010) and Tola et al. (2012), and Poisson meshes of them at depth 11, trimmed below depth 8 (IJCV §5; ReadMe).

There are no depth maps, meshes of the reference, or object masks in the official release. Learned methods derive them: MVSNet renders depth maps from screened Poisson meshes of the reference (depth 11, trimming factor 9.5), and IDR annotated object masks for 12 of its 15 scans, taking the other three from DVR.

Splits

The official code defines two evaluation sets. GetUsedSets.m lists the 80 scans of the general experiment (1–6, 9–19, 21–25, 28–51, 55, 59–65, 69, 74–77, 83, 84, 93–100, 102, 103, 105, 106, 110, 114, 118, 122, 126–128), the same 80 that have ground planes. GetUsedLightSets.m lists the ten of the lighting experiment (10, 25, 28, 30, 39, 75, 94, 99, 103 and 106). The release defines no training split; the papers ran the baseline methods with their original parameters, without tuning them on the data (IJCV §5). From each four-scan rotation group only one scan is evaluated, to avoid biasing the results (IJCV §4.2, footnote).

Learned methods use the split of SurfaceNet (Ji et al., 2017), which MVSNet adopted and printed: 79 training scans, 18 validation scans (3, 5, 17, 21, 28, 35, 37, 38, 40, 43, 56, 59, 66, 67, 82, 86, 106, 117) and 22 evaluation scans (1, 4, 9, 10, 11, 12, 13, 15, 23, 24, 29, 32, 33, 34, 48, 49, 62, 75, 77, 110, 114, 118). MVSNet counted 27,097 training samples, one per image used as reference: 79 scans × 49 images × 7 lightings. Comparing the lists with the official files shows three properties that MVSNet’s paper does not state:

  • The 22 evaluation scans all belong to the official 80, but so do 45 training and 12 validation scans; a method trained on this split has seen most of the scenes of the original benchmark.
  • 119 scan numbers are assigned; scans 25, 26, 27, 54 and 73, which exist, are in none of the three lists, and scan 25 is in both official evaluation sets.
  • Rotated copies cross the split: evaluation scans 110, 114 and 118 have their other three views of the same objects (111–113, 115–116 with 117 in validation, 119–121) in training.

Yu et al. (2021) found that the MVSNet split shares scenes between training and test, and for pixelNeRF they used 88 training and 15 test scenes with no shared or highly similar scenes. Neural surface reconstruction uses a third convention, 15 scans chosen by IDR (Yariv et al., 2020): 24, 37, 40, 55, 63, 65, 69, 83, 97, 105, 106, 110, 114, 118 and 122, each optimized on its own images.

Tasks

  • Multi-view stereo, evaluated on point clouds or meshes, the purpose of the data set.
  • Learned depth estimation, as training and test data for networks such as MVSNet, with depth maps rendered from the reference.
  • Surface reconstruction from images with neural implicit representations, on the 15 IDR scans, scored with the official distances.
  • Sparse-view novel view synthesis, where pixelNeRF and its successors train across scenes and render held-out views from three inputs.

Evaluation

The protocol in the papers

Accuracy is the distance from each reconstructed point to the nearest reference point, completeness the distance from each reference point to the nearest reconstructed point, the two directions of Seitz et al. (2006). Middlebury reported a high percentile of the accuracy distances; DTU reports the mean and the median, after discarding distances above 20 mm so that a few gross outliers do not dominate, and keeps the median as a robust statistic that shows the effect of the smaller outliers that remain (IJCV §4.1).

Two changes deal with what the reference does not contain. Middlebury filled holes in the reference surface and ignored reconstructed points whose nearest reference point lay on a filled region; DTU’s scenes are too complex for hole filling, so it records where the scanner could see instead (IJCV §4.2). For every reference point, all 1 mm voxels on the ray to the camera that recorded it are marked as observed, and the ray is extended 10 mm behind the point so that reconstructions slightly behind the reference still count. The table is removed by discarding reference points below a manually placed plane (§3.3). Uneven sampling is handled by thinning: points are visited in random order and a point is kept only if no point kept before it lies within 0.2 mm, a conservative estimate of the scanner’s accuracy (§4.3). Meshes are sampled into points and thinned the same way.

The authors checked the sensitivity of these choices. Changing the 0.2 mm thinning distance, the 20 mm cut-off or the 10 mm ray extension by ±10% moved the mean results by about a hundredth of a millimetre, and thinning the reference in a different random order changed the averages over scenes by 0.0631 mm for the mean and 0.0301 mm for the median (IJCV §4.3–4.4).

What the official code computes

The MATLAB code is part of SampleSet.zip on the official page; the version read here is the archive last modified on 14 February 2018, with script files dated September 2015. It needs MATLAB’s Statistics and Machine Learning Toolbox (KDTreeSearcher, knnsearch, rangesearch), so it was read line by line rather than run. For one scan and one reconstruction:

  1. Sampling. A mesh is sampled by MeshSupSamp (a compiled MEX file with C++ source), which places a regular grid of points on each triangle with spacing set from the 0.2 mm threshold and the triangle’s shape, and adds them to the vertices.
  2. Thinning. reducePts_haa.m thins the reconstruction to 0.2 mm in a random order (randperm, so repeated runs differ slightly). The reference is not thinned again; a comment says the stl files are already reduced to 0.2 mm.
  3. Distances. MaxDistCP.m computes nearest-neighbour distances with a k-d tree, block by block in 60 mm cubes over the mask’s bounding box, searching each block’s neighbourhood enlarged by 60 mm. Points outside the grid of blocks, which covers the bounding box, keep the initial value of 60 mm. Accuracy distances go from every thinned reconstructed point to the whole reference cloud, table included; completeness distances go from every reference point to every thinned reconstructed point, masked or not.
  4. Masks. PointCompareMain.m maps each reconstructed point to a voxel, round((q−bmin⁡)/r)+1\mathrm{round}((\mathbf{q} - \mathbf{b}_{\min})/r) + 1 for bounding-box corner bmin⁡\mathbf{b}_{\min} and resolution rr, and marks it as in the mask when the voxel lies in the grid and is observed. It marks a reference point s\mathbf{s} as above the ground plane p\mathbf{p} when p⊤[s;1]>0\mathbf{p}^\top [\mathbf{s}; 1] > 0.
  5. Statistics. ComputeStat_web.m keeps the accuracy distances of points in the mask and the completeness distances of reference points above the plane, discards those of 20 mm or more (it keeps d<20d < 20), and stores the mean, median, variance and number of retained distances for each scan.

With Q\mathcal{Q} the thinned reconstruction, S\mathcal{S} the reference, MM the observed voxels and S+\mathcal{S}^{+} the reference points above the plane, the scan’s mean values are

Acc=mean⁡q∈Q∩Md(q,S)<20d(q,S),Comp=mean⁡s∈S+d(s,Q)<20d(s,Q),\mathrm{Acc} = \operatorname*{mean}_{\substack{\mathbf{q} \in \mathcal{Q} \cap M \\ d(\mathbf{q}, \mathcal{S}) < 20}} d(\mathbf{q}, \mathcal{S}), \qquad \mathrm{Comp} = \operatorname*{mean}_{\substack{\mathbf{s} \in \mathcal{S}^{+} \\ d(\mathbf{s}, \mathcal{Q}) < 20}} d(\mathbf{s}, \mathcal{Q}),

in millimetres, lower is better; the medians replace the mean by the median over the same sets.

Read against the papers, the code settles four details. The observability mask restricts only accuracy; completeness is restricted by the plane alone. This matches the CVPR paper and the IJCV outline (§4.4), but IJCV §4.2 says the mask is used to ignore accuracy or completeness. Reconstructed points outside the mask’s bounding box are excluded from accuracy, which the papers do not mention. Reference points below the plane are dropped from completeness but remain targets for accuracy, so reconstructed table points inside the mask are scored against the scanned table. And distances are discarded, as the papers say, not clipped: a reference point more than 20 mm from every reconstructed point simply leaves the average, and only the stored count of retained distances shows it. The two shipped scripts also disagree on their default lighting (l7, randomly drawn lightings, in BaseEvalMain_web.m; l3, all lights on, in ComputeStat_web.m), so a user must set them consistently.

Conventions of later papers

MVSNet introduced the overall score, the average of mean accuracy and mean completeness, as a single number comparable to an F-score, and computed the percentage metric of Tanks and Temples (the share of points within 1 mm and 2 mm) with its own code. IDR reports a single “Chamfer distance” computed with the official script, and NeuS measures it the same way as IDR and UNISURF. A widely used Python port (jzhangbs, DTUeval-python, commit 45b4fec), a third-party copy not hosted by the dataset’s authors, follows the same steps but reports only the two means and their average, and computes completeness against reconstructed points inside an enlarged bounding box rather than all of them. Its README reports agreement with the MATLAB code within 0.15% on meshes of 15 scans.

Example

The script below builds a scene in millimetres with known errors: a sphere of radius 40 mm on a table, scanned from 49 positions on a sphere of radius 50 cm, with a patch of 12° angular radius that the scanner missed. It builds the observability mask by marking voxels along each reference point’s ray, and generates a reconstruction with 0.25 mm noise, a textureless hole on the sphere, 3% outliers floating up to 40 mm toward the cameras, and an unseen back side closed 1.5 mm too large, as meshing might. It then scores the reconstruction as the official code does and with one rule changed at a time. The point cloud and Chamfer distance articles cover the k-d tree and the effect of sampling density; this example concerns the masks and the cut-off.

import numpy as np
from scipy.spatial import cKDTree

C, R = np.array([0.0, 0.0, 40.0]), 40.0           # sphere of radius 40 mm on a table (z = 0), in mm
az, el = np.meshgrid(np.radians(np.linspace(-60, 60, 7)), np.radians(np.linspace(25, 65, 7)))
CAMS = 500 * np.stack([np.cos(el) * np.sin(az), -np.cos(el) * np.cos(az), np.sin(el)], -1).reshape(-1, 3)

def sphere_pts(n, rng):
    v = rng.normal(size=(n, 3)); v /= np.linalg.norm(v, axis=1, keepdims=True)
    return C + R * v, v

def surface(n, half, rng):
    """Sphere and table points with normals; the table is the square |x|, |y| < half."""
    ps, ns = sphere_pts(n, rng)
    pt = np.c_[rng.uniform(-half, half, (n, 2)), np.zeros(n)]
    return np.r_[ps, pt], np.r_[ns, np.tile([0.0, 0.0, 1.0], (n, 1))]

def visible(p, nrm, cams):
    """(points x cameras): the camera is in front of the surface and the sphere does not block the ray."""
    d = cams[None] - p[:, None]
    f = p[:, None] - C
    a, b = (d * d).sum(-1), 2 * (f * d).sum(-1)
    disc = b**2 - 4 * a * ((f * f).sum(-1) - R**2)
    t = (-b - np.sqrt(np.maximum(disc, 0))) / (2 * a)            # first hit along p + t d
    return ((nrm[:, None] * d).sum(-1) > 0) & ~((disc > 0) & (t > 1e-6) & (t <= 1))

def reduce_pts(p, dst, rng):
    """As reducePts_haa.m: visit points in random order; keep a point, drop its neighbours within dst."""
    order = rng.permutation(len(p))
    keep = np.ones(len(p), bool)
    for i, idx in zip(order, cKDTree(p).query_ball_point(p[order], dst)):
        if keep[i]:
            keep[idx] = False; keep[i] = True
    return p[keep]

# Reference scan: points seen by at least one of 49 scanner positions, minus a patch the scanner missed.
rng = np.random.default_rng(0)
P, N = surface(60_000, 60, rng)
vis = visible(P, N, CAMS)
u = np.array([0.6, -0.6, 0.53]) / np.linalg.norm([0.6, -0.6, 0.53])
missed = (P[:, 2] > 0) & ((P - C) @ u > R * np.cos(np.radians(12)))
stl, vis = P[vis.any(1) & ~missed], vis[vis.any(1) & ~missed]
cam_of = np.array([rng.choice(np.flatnonzero(r)) for r in vis])    # the position that recorded each point

# Observability mask: 1 mm voxels on every ray from a reference point to its camera, extended 10 mm behind it.
BB, RES = np.array([[-75.0, -75.0, -15.0], [75.0, 75.0, 125.0]]), 1.0
shape = tuple(np.floor((BB[1] - BB[0]) / RES + 0.5).astype(int) + 1)
obs = np.zeros(shape, bool)
for s in range(0, len(stl), 4000):
    p = stl[s:s + 4000]
    d = CAMS[cam_of[s:s + 4000]] - p
    d /= np.linalg.norm(d, axis=1, keepdims=True)
    for t in np.arange(-10.0, 260.0, RES / 2):
        v = np.floor((p + t * d - BB[0]) / RES + 0.5).astype(int)
        ok = np.all((v >= 0) & (v < shape), axis=1)
        obs[tuple(v[ok].T)] = True
plane = np.array([0.0, 0.0, 1.0, -2.0])                            # "manually placed": object where z > 2 mm

def reconstruct(hole_deg, rng, out_frac=0.03):
    """Synthetic MVS points: seen by >= 2 cameras, 0.25 mm noise, a textureless hole of hole_deg
    on the sphere, outliers floating 0.5-40 mm toward a camera, and a closed back 1.5 mm too large."""
    P, N = surface(60_000, 50, rng)
    keep = (visible(P, N, CAMS).sum(1) >= 2) & (np.hypot(P[:, 0], P[:, 1]) < 50)
    top = np.array([-0.3, -0.5, 0.81]) / np.linalg.norm([-0.3, -0.5, 0.81])
    keep &= ~((P[:, 2] > 0) & ((P - C) @ top > R * np.cos(np.radians(hole_deg))))
    Q = P[keep] + rng.normal(0, 0.25, (keep.sum(), 3))
    k = rng.choice(len(Q), int(out_frac * len(Q)), replace=False)
    d = CAMS[rng.integers(0, len(CAMS), len(k))] - Q[k]
    Q[k] += rng.uniform(0.5, 40, (len(k), 1)) * d / np.linalg.norm(d, axis=1, keepdims=True)
    B, nb = sphere_pts(20_000, rng)
    back = B[~visible(B, nb, CAMS).any(1) & (B[:, 2] > 2)]
    return np.r_[Q, C + (back - C) * (R + 1.5) / R]

def evaluate(Q, use_mask=True, use_plane=True, max_dist=20.0, rng=None):
    """Accuracy and completeness as PointCompareMain.m and ComputeStat_web.m compute them."""
    Q = reduce_pts(Q, 0.2, rng)                                    # the STL points count as already reduced
    d_data = np.minimum(cKDTree(stl).query(Q, distance_upper_bound=60)[0], 60)   # MaxDistCP: 60 mm cap
    d_stl = np.minimum(cKDTree(Q).query(stl, distance_upper_bound=60)[0], 60)
    v = np.floor((Q - BB[0]) / RES + 0.5).astype(int)
    inside = np.all((v >= 0) & (v < shape), axis=1)
    in_mask = np.zeros(len(Q), bool)
    in_mask[inside] = obs[tuple(v[inside].T)]
    above = stl @ plane[:3] + plane[3] > 0
    acc = d_data[in_mask] if use_mask else d_data                  # data -> STL, data points in the mask
    comp = d_stl[above] if use_plane else d_stl                    # STL above the plane -> all data points
    acc, comp = acc[acc < max_dist], comp[comp < max_dist]         # discard outliers
    return dict(n_acc=len(acc), acc=acc.mean(), acc_med=np.median(acc), n_comp=len(comp),
                comp=comp.mean(), comp_med=np.median(comp), overall=(acc.mean() + comp.mean()) / 2)

Q = reconstruct(15, np.random.default_rng(1))
print(f"reference {len(stl)} points, {(stl[:, 2] > 2).sum()} above the plane; reconstruction {len(Q)} points")
print(f"{'setting':22s}{'n acc':>7s}{'acc mean':>9s}{'median':>7s}{'n comp':>8s}{'comp mean':>10s}"
      f"{'median':>7s}{'overall':>8s}")
for name, kw in [("official", {}), ("no observability mask", dict(use_mask=False)),
                 ("no ground plane", dict(use_plane=False)), ("outlier cut 5 mm", dict(max_dist=5)),
                 ("outlier cut 10 mm", dict(max_dist=10)), ("outlier cut 60 mm", dict(max_dist=60))]:
    r = evaluate(Q, rng=np.random.default_rng(2), **kw)
    print(f"{name:22s}{r['n_acc']:7d}{r['acc']:9.3f}{r['acc_med']:7.3f}{r['n_comp']:8d}{r['comp']:10.3f}"
          f"{r['comp_med']:7.3f}{r['overall']:8.3f}")

rows = [list(evaluate(reconstruct(15, np.random.default_rng(s)), rng=np.random.default_rng(100 + s)).values())
        for s in range(1, 6)]
lo, hi = np.min(rows, 0), np.max(rows, 0)
print("official, reconstruction seeds 1-5: " + ", ".join(
    f"{k} {a:.3f}-{b:.3f}" for k, a, b in zip(["acc", "acc_med", "comp", "comp_med", "overall"],
                                             lo[[1, 2, 4, 5, 6]], hi[[1, 2, 4, 5, 6]])))

Output (NumPy 2.3.5, SciPy 1.16.3):

reference 105084 points, 47587 above the plane; reconstruction 91565 points
setting                 n acc acc mean median  n comp comp mean median overall
official                82711    0.617  0.358   47587     0.442  0.361   0.530
no observability mask   84932    0.844  0.364   47587     0.442  0.361   0.643
no ground plane         82711    0.617  0.358  102945     2.395  0.386   1.506
outlier cut 5 mm        80940    0.420  0.354   47469     0.429  0.361   0.424
outlier cut 10 mm       82076    0.515  0.357   47587     0.442  0.361   0.479
outlier cut 60 mm       82933    0.684  0.359   47587     0.442  0.361   0.563
official, reconstruction seeds 1-5: acc 0.602-0.617, acc_med 0.357-0.360, comp 0.439-0.447, comp_med 0.358-0.363, overall 0.523-0.530

The medians barely move in any row: they are set by the 0.25 mm noise and the point spacing, which is what Aanæs et al. kept them for. The means carry everything else. Dropping the observability mask adds about 2,200 points that the reference cannot judge, mostly the reconstructed surface in the patch the scanner missed and the closed back of the sphere, plausible geometry rather than errors, together with outliers outside the mask, and raises mean accuracy by more than a third. Dropping the ground plane makes completeness count the scanned table beyond the 50 mm disc the reconstruction covers and raises the mean more than fivefold: without the plane, a benchmark of objects would mostly score tables. The cut-off decides how much the floating outliers cost. Raising it from 20 to 60 mm admits only 222 more points, while the 5 mm cut removes 1,771: most outliers end up within 20 mm of some reference point, on the sphere or the table, so the official cut removes only the farthest, and the 5 mm cut also removes back-side points that the mask admits but the reference does not cover. Between cuts of 5 and 60 mm, mean accuracy rises from 0.42 to 0.68 mm, so the 20 mm value is part of what the numbers mean. Over five reconstruction seeds the official overall score stays between 0.523 and 0.530.

The second block, continuing the script, widens the textureless hole and reports completeness with and without the outliers, together with the share of reference points above the plane whose distance was discarded.

n_above = (stl @ plane[:3] + plane[3] > 0).sum()
print(f"{'hole':>5s}{'radius':>8s}   {'comp mean / median / discarded':32s}{'same, no outliers'}")
for deg in [0, 15, 30, 45, 60, 75]:
    cells = []
    for out_frac in [0.03, 0.0]:
        r = evaluate(reconstruct(deg, np.random.default_rng(1), out_frac), rng=np.random.default_rng(2))
        cells.append(f"{r['comp']:6.3f} {r['comp_med']:6.3f} {100 * (1 - r['n_comp'] / n_above):6.1f}%")
    print(f"{deg:4d}°{np.radians(deg) * R:7.1f} mm   {cells[0]:32s}{cells[1]}")
 hole  radius   comp mean / median / discarded  same, no outliers
   0°    0.0 mm    0.389  0.355    0.0%            0.387  0.351    0.0%
  15°   10.5 mm    0.442  0.361    0.0%            0.454  0.357    0.0%
  30°   20.9 mm    0.706  0.374    0.0%            0.956  0.370    0.0%
  45°   31.4 mm    1.187  0.403    0.0%            1.781  0.392    2.3%
  60°   41.9 mm    1.907  0.454    0.0%            2.555  0.417    9.1%
  75°   52.4 mm    2.795  0.621    0.3%            3.351  0.467   19.3%

Without outliers, the largest hole leaves a fifth of the object’s reference points more than 20 mm from any reconstructed point, and they drop out of the mean, which therefore understates the hole; the median stays below 0.5 mm, because most of the object is still covered. With outliers the holes look smaller: points floating above the sphere are within 20 mm of the hole’s interior, which lowers mean completeness by up to a third and leaves almost nothing discarded. Outliers outside the mask never pay for this in accuracy. In our reading, the per-scan counts of retained distances, which the code stores but papers rarely print, are needed to tell a complete reconstruction from one whose missing parts were discarded.

License

As of October 2026, the official home page, the MVS data set page and the ReadMe describe the data as freely available “citeware”: users are asked to cite the related work, the CVPR 2014 paper or its IJCV extension. Neither page names a licence, says whether commercial use or redistribution is allowed, or gives separate terms for the images, the reference scans and the evaluation code. The terms are therefore unclear beyond the citation request. The evaluation code includes plyread.m, which the ReadMe credits to Pascal Getreuer rather than to the dataset’s authors.

Limitations and Bias

  • Controlled capture. LED lighting in a closed box, long exposures with the scene in focus and no motion blur; the authors note that this does not cover hand-held photography, typical user behaviour or sunlight. Every scene is a tabletop object seen from one side.
  • Incomplete reference. The scans miss backs, self-occluded parts and underexposed regions. The observability mask stops those regions from penalizing accuracy, but completeness has only the plane, so the reference defines what “complete” means. IDR’s authors describe the reference as noisy, not watertight and often missing notable parts.
  • One camera layout. All scenes share the same 49 or 64 camera positions on one or two spheres, so learned methods see the same layout in training and test; MVSNet, for example, samples depth hypotheses from 425 to 935 mm in training, a range that fits this setup. MVSNet’s authors describe DTU as a well-controlled indoor environment with a fixed camera trajectory.
  • Leakage in learned splits. The MVSNet split shares objects between training and evaluation through the rotation groups, and trains on scenes of the original benchmark.
  • Summary statistics. Means after a 20 mm cut-off hide discarded regions, and averaging accuracy and completeness into one overall score hides the trade-off between them that the original study was built to show.

Common Uses

Classical and learned multi-view stereo report accuracy, completeness and overall score on the 22 evaluation scans of the MVSNet split, after training on its 79 training scans. Neural surface methods report the official distances on the 15 IDR scans, with or without object masks, and sparse-view radiance-field methods report image metrics on the pixelNeRF split. The 3D reconstruction article compares DTU with the other reconstruction benchmarks.

Historical Milestones

  • 2014, the benchmark (CVPR). Jensen et al. evaluated Campbell et al. (2008), Furukawa and Ponce (2010) and Tola et al. (2012) on all 80 scenes, as points and as Poisson meshes, under full illumination only. Tola et al.’s method was the most accurate and Campbell et al.’s the most complete (their Fig. 4), and the authors found lack of texture the main source of failure.
  • 2016, the extended study (IJCV). With the meshing parameters standardized, which the authors say explains small differences from the CVPR results, an analysis of variance over the 80 scenes gave mean accuracy of 0.408 mm for Tola et al. against 1.082 mm for Campbell et al., and mean completeness of 1.040 mm against 0.551 mm (Table 3, main effects averaged over points and meshes). In the lighting experiment on ten scenes, random lighting per image left mean accuracy unchanged at 0.576 mm and worsened mean completeness from 0.735 to 0.832 mm (Table 4). Specular surfaces and lighting changes hurt less than expected; lack of texture and meshing were the open problems.
  • 2017, a learned volumetric method (ICCV). SurfaceNet (Ji et al., 2017) trained a 3D convolutional network on DTU and defined the training, validation and evaluation scan lists.
  • 2018, MVSNet (ECCV). On the 22 evaluation scans, Yao et al. reported mean accuracy, completeness and overall score of 0.396, 0.527 and 0.462 mm for MVSNet, against 0.283, 0.873 and 0.578 mm for Gipuma (Galliani et al., 2015) and 0.450, 1.04 and 0.745 mm for SurfaceNet (Table 1). Gipuma remained the most accurate method in the table; MVSNet had the best completeness and overall score. The table’s values for Campbell, Furukawa and Tola differ from the IJCV ones, which are ANOVA effects over 80 scans averaged over points and meshes.
  • 2020–2021, neural surfaces. IDR (Yariv et al., 2020) reported a mean Chamfer distance of 0.90 over its 15 scans with object masks and fixed cameras, against 0.65 for trimmed and 1.36 for watertight COLMAP meshes (Table 1). NeuS (Wang et al., 2021) reported 0.77 with masks and 0.84 without (Table 1).
  • 2021, sparse views. pixelNeRF (Yu et al., 2021) replaced the MVSNet split with one without shared scenes for view synthesis from three images.
  • Middlebury multi-view stereo (Seitz et al., 2006): two small objects with laser-scanned ground truth; the protocol DTU extended. It is separate from the two-view Middlebury benchmarks.
  • Strecha et al. (2008): high-resolution outdoor scenes of historical buildings; the CVPR paper counts twelve scenes and the IJCV paper six.
  • Tanks and Temples: large indoor and outdoor scenes from video with laser-scanned ground truth, scored by an F-score at a per-scene threshold; MVSNet tested its DTU-trained model on it without fine-tuning.
  • ETH3D: high-resolution and low-resolution multi-view benchmarks registered to laser scans, scored at several tolerances.
  • BlendedMVS: NeuS’s second benchmark, seven scenes of its low-resolution set with masks.
  • DTU point-feature data set (Aanæs et al., 2012): an earlier set from the same robot setup, for evaluating interest points.

Resources

  • DTU Robot Image Data home page: the setup, calibration and the list of data sets.
  • MVS data set page: description, citation, and downloads of SampleSet (with the ReadMe and MATLAB evaluation code), reference points, baseline reconstructions and images.
  • Publications page: the authors’ copies of the CVPR 2014 paper and of the IJCV manuscript.
  • DTUeval-python: a third-party Python port of the evaluation (commit 45b4fec).

There is no official leaderboard; results are reported in papers.

Related

  • 3D Reconstruction

    Recovering the 3D shape of objects and scenes from images, depth maps, or range scans, as point clouds, meshes, volumes, or implicit and radiance fields, and measuring how accurate and complete the result is.

  • Point Cloud

    A set of 3D points sampled from the surfaces of a scene, possibly with color, intensity, or normals per point, and the most direct output of 3D sensors and reconstruction.

  • Poisson Surface Reconstruction

    A method that turns an oriented point cloud into a watertight mesh by finding the indicator function whose gradient best matches the point normals, which reduces to solving a Poisson equation.

  • Neural Implicit Representations

    Coordinate-based networks that store a shape, an image or another field in their weights, answering a query at any continuous point; how they are conditioned, trained from 3D data, raw points or images, why plain ReLU networks blur detail, and how surfaces are extracted from them.

  • Novel View Synthesis

    Rendering a scene from a camera that took no picture of it, given images and usually their camera poses; the variants of the problem, the families of methods from image warping to radiance fields and diffusion models, the benchmarks, and why the results are hard to measure.

  • Benchmarks and Leaderboards

    What a computer vision benchmark consists of (a task, data, a protocol and a metric), how held-out and sequestered test sets, evaluation servers, submission limits, challenges and leaderboards keep its scores honest, and the ways those scores mislead.

References

  1. Jensen, R., Dahl, A., Vogiatzis, G., Tola, E. & Aanæs, H. (2014). Large Scale Multi-view Stereopsis Evaluation. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 406–413.
  2. Aanæs, H., Jensen, R. R., Vogiatzis, G., Tola, E. & Dahl, A. B. (2016). Large-Scale Data for Multiple-View Stereopsis. International Journal of Computer Vision, 120(2), 153–168.
  3. Technical University of Denmark. DTU Robot Image Data Sets (home page). (accessed October 2026)
  4. Technical University of Denmark. MVS Data Set – 2014 (page with downloads; SampleSet.zip, last modified 14 February 2018, contains the ReadMe and the MATLAB evaluation code, script files dated September 2015). (accessed October 2026)
  5. Seitz, S. M., Curless, B., Diebel, J., Scharstein, D. & Szeliski, R. (2006). A Comparison and Evaluation of Multi-View Stereo Reconstruction Algorithms. IEEE Computer Society Conference on Computer Vision and Pattern Recognition (CVPR), vol. 1, 519–528.
  6. Campbell, N. D. F., Vogiatzis, G., Hernández, C. & Cipolla, R. (2008). Using Multiple Hypotheses to Improve Depth-Maps for Multi-View Stereo. European Conference on Computer Vision (ECCV), Lecture Notes in Computer Science, 766–779.
  7. Furukawa, Y. & Ponce, J. (2010). Accurate, Dense, and Robust Multiview Stereopsis. IEEE Transactions on Pattern Analysis and Machine Intelligence, 32(8), 1362–1376.
  8. Tola, E., Strecha, C. & Fua, P. (2012). Efficient Large-Scale Multi-View Stereo for Ultra High-Resolution Image Sets. Machine Vision and Applications, 23(5), 903–920.
  9. Galliani, S., Lasinger, K. & Schindler, K. (2015). Massively Parallel Multiview Stereopsis by Surface Normal Diffusion. IEEE International Conference on Computer Vision (ICCV), 873–881.
  10. Ji, M., Gall, J., Zheng, H., Liu, Y. & Fang, L. (2017). SurfaceNet: An End-to-End 3D Neural Network for Multiview Stereopsis. IEEE International Conference on Computer Vision (ICCV), 2326–2334.
  11. Yao, Y., Luo, Z., Li, S., Fang, T. & Quan, L. (2018). MVSNet: Depth Inference for Unstructured Multi-view Stereo. European Conference on Computer Vision (ECCV), Lecture Notes in Computer Science, 785–801.
  12. Yariv, L., Kasten, Y., Moran, D., Galun, M., Atzmon, M., Basri, R. & Lipman, Y. (2020). Multiview Neural Surface Reconstruction by Disentangling Geometry and Appearance. Advances in Neural Information Processing Systems 33 (NeurIPS), 2492–2502.
  13. Wang, P., Liu, L., Liu, Y., Theobalt, C., Komura, T. & Wang, W. (2021). NeuS: Learning Neural Implicit Surfaces by Volume Rendering for Multi-view Reconstruction. Advances in Neural Information Processing Systems 34 (NeurIPS), 27171–27183.
  14. Yu, A., Ye, V., Tancik, M. & Kanazawa, A. (2021). pixelNeRF: Neural Radiance Fields from One or Few Images. IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 4576–4585.
  15. jzhangbs. DTUeval-python: a Python implementation of the DTU MVS 2014 evaluation (GitHub repository, commit 45b4fec; third-party, not hosted by the dataset's authors). (accessed October 2026)