Datasets & Benchmarks
WIDER FACE
A face detection benchmark from the Chinese University of Hong Kong, released in 2015, with 32,203 web images of 61 event classes (60 in the paper) and 393,703 labelled faces, scored by average precision on nested Easy, Medium and Hard settings computed by its official MATLAB code.
intermediate
WIDER FACE is a face detection benchmark of 32,203 images with 393,703 labelled faces, built by Shuo Yang, Ping Luo, Chen Change Loy and Xiaoou Tang at the Multimedia Laboratory of the Chinese University of Hong Kong. Version 1.0, with images, face boxes and event labels, was released on 19 November 2015, the same week as the arXiv technical report, and the paper appeared at CVPR 2016 (Yang et al., 2016; official page). Its images come from WIDER, a dataset for recognizing events in web photographs, and are organized into 61 event classes (60 by the paper’s count) such as parades, festivals, traffic and surgeons. Detectors are scored with average precision (AP) on three settings, Easy, Medium and Hard, which the paper derives from how well a generic proposal method finds the faces; the settings are nested, so Hard counts nearly every face. Most face detection methods published from 2016 on report their main results on it, where earlier detectors had reported on FDDB, the 2010 benchmark that this article also describes.
Purpose
The authors argued that the existing benchmarks no longer separated methods. They quote best results of 97.2% AP on AFW, 91.74% recall on FDDB and 92.11% AP on PASCAL Faces, with only marginal differences among the best few algorithms, and attribute the saturation to datasets of a few thousand faces with little variation in pose, scale, expression, occlusion and background clutter (Yang et al., 2016, §1–2). FDDB, built from Yahoo! News photographs, is described as biased towards celebrity faces. The earlier sets were test sets only; detectors were usually trained on AFLW, a landmark dataset that omits many small, low-resolution and heavily occluded faces and has clean backgrounds, so negatives were taken from other sources such as PASCAL VOC. WIDER FACE was meant to supply both a harder test and a training set in which every recognizable face is labelled, so that negatives can come from the same images, and attribute labels for analysing failures by scale, occlusion and pose.
Dataset Size
| Count | Value | Source |
|---|---|---|
| Images | 32,203 | Paper (§3.1) and official page |
| Labelled faces | 393,703 | Paper (§3.1, Fig. 1) and official page |
| Training and validation | 16k images, 199k faces | Paper, Table 1 (“Training”) |
| Test | 16k images, 194k faces | Paper, Table 1 (“Testing”) |
| Faces 10–50 / 50–300 / over 300 pixels tall | 50% / 43% / 7% | Paper, Table 1 |
Table 1 prints the last height column as “≤ 300 pixels”; the text defines the large scale as over 300 pixels, so the header reads as a typesetting error. By the same table, 8% of FDDB’s faces and 12% of AFW’s are 10–50 pixels tall, against half of WIDER FACE’s. The paper calls the dataset ten times larger than the largest earlier face detection set, IJB-A.
The official page records the release history: v1.0 on 19 November 2015, the pose and occlusion labels on 17 April 2016, and on 31 March 2017 a text version of the ground truth, a fix for the rounding of box coordinates and a new version of the evaluation code (as of October 2026). The counts above have not been restated after the 2017 fix. The image archives are linked from the page on Google Drive, Tencent Weiyun and Hugging Face.
Classes
There is one object class, the face. The event classes label whole images and organize the collection, its split and the per-event analysis. They are inherited from WIDER (Web Image Dataset for Event Recognition), whose CVPR 2015 paper describes 60 event classes and about 60,000 images: most categories were taken from the Large Scale Concept Ontology for Multimedia (LSCOM), which lists about 1,000 concepts for video event analysis, and students proposed further everyday activities such as car driving; 1,000 to 3,000 images per class were retrieved from Google and Bing, with query expansion, and screened by an automatic filter for cartoons and clip art and then by hand (Xiong et al., 2015, §3). The WIDER project page, as archived in November 2016, describes version 0.1 as 61 event categories and about 50,574 images.
The same discrepancy runs through WIDER FACE. Its paper says 60 event classes and its Figure 4 and the appendix tables of the arXiv version (Tables 9 and 10) name 60, from Traffic, Festival and Parade to Spa and Surgeons; the official page says 61, and the evaluation code loops over event_num = 61. The submission instructions show the directory naming, for example 0--Parade.
For WIDER FACE the authors removed images without a human face and near-duplicate images within each event class, which left the 32,203 images (§3.2). They also ranked the events by the EdgeBox detection rate of their faces at 10,000 proposals and split them into easy (the 20 with the highest rate), medium and hard events, separately for scale, occlusion and pose (§3.3; Fig. 4 shows the scale partition, Fig. 9 of the arXiv appendix, §7.2, all three). These event partitions are a tool for analysis and are distinct from the Easy, Medium and Hard evaluation settings below.
Annotation Types
- Face boxes. Every recognizable face gets a box that tightly contains the forehead, chin and cheeks; occluded faces are boxed at their estimated full extent (§3.2). Each annotation was made by one annotator and cross-checked by two others.
- Ignore flag. Following PASCAL VOC’s practice, faces that are very hard to recognize because of low resolution and small size, 10 pixels or less, carry an ignore flag (§3.2).
- Occlusion. None, partial (1–30% of the face area occluded) or heavy (over 30%). To calibrate the judgement, 10% of the faces were annotated with two boxes, the visible and the full extent, giving the occluded fraction as one minus their area ratio; annotators then assigned the other faces by comparison with these exemplars (§3.3).
- Pose. Atypical when the roll or pitch exceeds 30° or the yaw exceeds 90°, typical otherwise (§3.3).
- Blur, expression, illumination and invalid. The text ground truth added in 2017 stores, after each box
x1, y1, w, h, six integers whose meanings its readme gives: blur (clear, normal, heavy), expression (typical, exaggerated), illumination (normal, extreme), invalid, occlusion and pose. The readme glosses the invalid flag as “invalid image” although it is stored per box. The CVPR paper describes only the occlusion and pose attributes; the other labels are documented only by this readme. - Event label of each image (above).
Detections are submitted in the same layout: one text file per image, holding the image name, the number of detections and one left top width height score line per detection (official page). RetinaFace’s authors later annotated five landmarks on 84.6k training and 18.5k validation faces (Deng et al., 2020); that annotation is theirs, not part of the official release.
Splits
Within each event class the images were split at random into 40% training, 10% validation and 50% test (§3.1). Training and validation boxes are public; test boxes are withheld, as in MALF and the Caltech pedestrian benchmark, and the organizers evaluate submitted results. As of October 2026 the official page still asks authors to contact Shuo Yang by email to have test results evaluated and states that an evaluation server “will be available soon”. Two training scenarios are defined, and the results page lists methods under each:
- Scenario-Ext: a detector trained on any external data and tested on the WIDER FACE test partition.
- Scenario-Int: a detector trained on the WIDER FACE training and validation partitions and tested on the test partition.
Tasks
WIDER FACE serves one task, face detection: return a box and a confidence score for every face. The paper also used the attribute labels to evaluate detectors on subsets by scale (small 10–50, medium 50–300, large over 300 pixels), occlusion and pose, and the event labels for per-event AP (Table 3), and it tested whether training on WIDER FACE improves results on FDDB (§5.2). Landmark localization, recognition and attribute estimation are not official tasks.
Evaluation
The paper says that WIDER FACE adopts the PASCAL VOC evaluation metric (§3.1), and the results page summarizes it as a detection counting as correct when its overlap ratio with an annotated face exceeds 0.5. Everything else is defined by the evaluation code. This section describes eval_tools.zip as served on the official page in October 2026: the page dates this version of the code to 31 March 2017, the archive’s members carry the date 21 June 2022, and wider_eval.m names Shuo Yang, December 2015, as its author. The code is MATLAB; we read every evaluation file line by line and did not run it in MATLAB, and the example below follows it step by step, checked against a literal Python transliteration (a cross-check of our own).
The Easy, Medium and Hard settings
The paper defines three difficulty levels, following the principles of KITTI and MALF, “based on the detection rate of EdgeBox”: with 8,000 EdgeBox proposals per image, the average recall of the faces is 92% for Easy, 76% for Medium and 34% for Hard (§3.3, Fig. 3a). It does not say how individual faces were assigned to the levels, and the conclusion describes the easy subset only as typically having faces over 50 pixels tall. The assignment is fixed in the ground-truth files that ship with the code: read_pred.m takes the image list from wider_face_val.mat, and evaluation.m loads only the setting’s file, wider_easy_val.mat, wider_medium_val.mat or wider_hard_val.mat, which must therefore hold the validation boxes (face_bbx_list) together with, for every image, the list of faces that count in that setting (gt_list). The code reads nothing else about a face, so the ignore flag for faces of 10 pixels or less and the invalid flag of the readme enter the evaluation only through which faces these lists leave out.
The settings are therefore not three disjoint groups of faces. Each one counts its listed faces and ignores every other face in the same images. Later papers describe the lists as nested: Hu and Ramanan (2017, §5) write that the Hard set includes all faces taller than 10 pixels, and the TinaFace authors that Hard covers Medium and Easy (Zhu et al., 2020); the WIDER FACE paper does not state this. Because Hard counts the most faces, papers usually headline it. Only validation lists are public; how the organizers score the test set is not published, and test results in papers are those the organizers returned.
What the code computes
- Reading (
read_pred.m). For each image, the detections in its text file are read and sorted by decreasing score; a missing file means no detections for that image. - Score normalization (
norm_score.m). Scores are min–max normalized over all detections of all images and events together. The running maximum starts atrealmin('single'), about , so if every score is negative the code divides by the distance to that tiny positive number instead of to the true maximum, and the top detection maps below 1 (our reading). - Counting faces. For each image, the number of faces in the setting’s list is added to the total , whether or not the image has detections. An image with no annotated boxes at all, or with no detections, is then skipped, so detections in an image without annotated faces are never counted (our reading of
evaluation.m; we did not check whether the validation files contain such images). - Matching (
image_evaluationinevaluation.m). Detections are taken in score order. Each is compared with every face in the image by IoU computed as in the VOC development kit, with one pixel added to widths and heights (boxoverlap.m, taken from the deformable part model code), and only the face with the highest IoU is considered. If that IoU is at least 0.5 and the face is not in the setting’s list, the detection is removed from the count of proposals: it is neither a true nor a false positive. If the face is in the list and not yet recalled, it becomes recalled. If it was already recalled, the detection stays a proposal and so acts as a false positive. A detection whose best IoU is below 0.5 is a false positive even when it lies on an ignored face. This is the VOC rule for difficult objects and duplicates, as the average precision article describes it; there is no crowd region that can absorb several detections, as in COCO. - Thresholds (
image_pr_info). For each of 1,000 thresholds , , the code finds in each image the last detection with normalized score at least and records the number of proposals up to it, , and the number of listed faces recalled up to it, . - Curve (
dataset_pr_info). Summing over images,
- AP (
plot/VOCap.m). The 1,000 points are passed to the VOC 2010 all-point interpolation: recall 0 and 1 are appended with precision 0, precision is replaced by its running maximum from the right, and the area is summed where recall changes. At a threshold with no proposals the precision is , which MATLAB evaluates to NaN; MATLAB’smaxskips NaN, so such points do not affect the envelope.
The code applies no limit on the number of detections per image, and the tools contain an nms.m that no evaluation file calls, so submissions are expected to be suppressed already.
Where the code departs from the description
- IoU threshold. The code accepts an IoU of exactly 0.5 (
>=); the results page says “greater than 0.5”. - Sampled thresholds. PASCAL VOC’s code ranks detections individually, so its AP depends only on their order. WIDER FACE samples the curve at 1,000 evenly spaced thresholds on normalized scores, so detections whose scores fall into the same interval enter the curve together, and the result depends on how the scores are spread. It follows that a change of score scale that keeps the ranking, which leaves VOC-style AP unchanged, can change WIDER FACE AP when it crowds the scores together; the example shows a case.
Example: ignored faces, nested settings and sampled thresholds
The example builds 200 synthetic annotated images and a synthetic detector, with no pixels needed: faces are integer boxes in four tiers (Easy faces 50–200 pixels tall, Medium-only 25–50, Hard-only 11–25, and faces of 5–10 pixels that no setting counts), and the detector finds smaller faces less often, scores them lower and localizes them with noise proportional to their size, adds a duplicate for some faces and fires about three times per image on the background. Every image has at least one Easy face. The evaluation follows the official code as described above. Next to the code’s AP it prints the exact all-point AP over the same matches, counts the detections the Easy setting excuses, and changes three things in the Hard and Easy settings: scores submitted as raw logits instead of sigmoid probabilities, one extra detection with a score of −1000 in a corner of one image, and a ground truth in which the non-Easy faces were never annotated instead of being ignored. Five seeds run in about a second.
import numpy as np
TIERS = ("easy", "medium-only", "hard-only", "never counted")
SETTINGS = {"Easy": 0, "Medium": 1, "Hard": 2} # a face counts if its tier <= setting
def boxoverlap(gt, b):
"""IoU as in boxoverlap.m: corner boxes, +1 on widths and heights."""
w = np.minimum(gt[:, 2], b[2]) - np.maximum(gt[:, 0], b[0]) + 1
h = np.minimum(gt[:, 3], b[3]) - np.maximum(gt[:, 1], b[1]) + 1
inter = w * h
area = lambda z: (z[..., 2] - z[..., 0] + 1) * (z[..., 3] - z[..., 1] + 1)
with np.errstate(divide="ignore", invalid="ignore"):
o = inter / (area(gt) + area(b) - inter)
o[(w <= 0) | (h <= 0)] = 0
return o
def make_image(rng, W=1024, H=768):
"""Synthetic annotated faces (x, y, w, h, integer pixels) with a difficulty tier,
and a synthetic detector's output (x, y, w, h, logit score)."""
tiers = np.repeat(np.arange(4), rng.poisson([0.7, 2.0, 5.0, 2.0]) + [1, 0, 0, 0])
lo, hi = np.array([50, 25, 11, 5])[tiers], np.array([200, 50, 25, 10])[tiers]
h = np.round(rng.uniform(lo, hi)); w = np.round(0.8 * h)
x, y = np.floor(rng.uniform(0, W - w)), np.floor(rng.uniform(0, H - h))
gt = np.c_[x, y, w, h]
p_det = np.array([0.97, 0.85, 0.6, 0.3])[tiers] # detector misses small faces
mu = np.array([3.0, 1.5, 0.5, -0.5])[tiers] # and scores them lower
dets = []
for g, p, m in zip(gt, p_det, mu):
for k in range(1 + (rng.uniform() < 0.1)): # 10% of faces get a duplicate
if rng.uniform() < p:
s = 0.08 * (1 + k) # localization noise
c = g[:2] + g[2:] / 2 + rng.normal(0, s, 2) * g[2:]
wh = g[2:] * np.exp(rng.normal(0, s, 2))
dets.append([*np.round(c - wh / 2), *np.round(wh), m - 1.5 * k + rng.normal()])
for _ in range(rng.poisson(3)): # background false positives
sz = rng.uniform(8, 60)
dets.append([rng.uniform(0, W - sz), rng.uniform(0, H - sz), 0.8 * sz, sz, rng.normal(-1.5, 1)])
return gt, tiers, np.array(dets).reshape(-1, 5)
def match(gt, keep, dets, iou_thr=0.5):
"""image_evaluation in evaluation.m. dets sorted by decreasing score.
Returns per detection: proposal (False if it hit an ignored face) and the
number of counted faces recalled so far."""
g = np.c_[gt[:, :2], gt[:, :2] + gt[:, 2:]] # x, y, x + w, y + h, as the code does
recalled = np.zeros(len(gt), int) # 0 unseen, 1 recalled, -1 ignored hit
proposal, n_rec = np.ones(len(dets), bool), np.zeros(len(dets), int)
for k, d in enumerate(dets):
o = boxoverlap(g, np.r_[d[:2], d[:2] + d[2:4]])
j = o.argmax()
if o[j] >= iou_thr:
if not keep[j]:
recalled[j], proposal[k] = -1, False
elif recalled[j] == 0:
recalled[j] = 1
n_rec[k] = (recalled == 1).sum()
return proposal, n_rec
def voc_ap(rec, prec):
"""VOCap.m: all-point interpolated AP (fmax skips NaN as MATLAB's max does)."""
mrec, mpre = np.r_[0, rec, 1], np.r_[0, prec, 0]
for i in range(len(mpre) - 2, -1, -1):
mpre[i] = np.fmax(mpre[i], mpre[i + 1])
i = np.nonzero(mrec[1:] != mrec[:-1])[0] + 1
return np.sum((mrec[i] - mrec[i - 1]) * mpre[i])
def wider_ap(images, setting, transform=lambda s: s, extra=None, n_thr=1000):
"""Official procedure: global min-max score normalization (norm_score.m), 1,000
thresholds 1 - t/1000 (evaluation.m), then VOCap. Also returns the exact
all-point AP over the same matches, with one threshold per detection."""
dets_all = [d.copy() for _, _, d in images]
for d in dets_all:
d[:, 4] = transform(d[:, 4])
if extra is not None: # append one detection to image 0
dets_all[0] = np.r_[dets_all[0], [extra]]
scores = np.concatenate([d[:, 4] for d in dets_all])
lo = scores.min()
hi = max(scores.max(), np.finfo(np.float32).tiny) # max_score starts at realmin('single')
thr = 1 - np.arange(1, n_thr + 1) / n_thr
props, recs = np.zeros(n_thr), np.zeros(n_thr)
n_faces, flat = 0, []
for (gt, tiers, _), d in zip(images, dets_all):
keep = tiers <= setting
n_faces += keep.sum()
if len(gt) == 0 or len(d) == 0: # skipped by evaluation.m
continue
d = d[np.argsort(-d[:, 4], kind="stable")] # read_pred.m sorts by score
s = (d[:, 4] - lo) / (hi - lo)
prop, n_rec = match(gt, keep, d)
last = np.searchsorted(-s, -thr, side="right") - 1 # last detection with s >= thr
ok = last >= 0
props[ok] += np.cumsum(prop)[last[ok]]
recs[ok] += n_rec[last[ok]]
new_tp = np.diff(np.r_[0, n_rec]) > 0
flat += [(sc, p, t) for sc, p, t in zip(d[:, 4], prop, new_tp)]
with np.errstate(invalid="ignore"):
ap = voc_ap(recs / n_faces, recs / props) # 0/0 gives NaN, as in MATLAB
f = np.array(sorted(flat, key=lambda r: -r[0]))
f = f[f[:, 1] == 1] # dropped detections leave the list
tp = np.cumsum(f[:, 2]); n = np.arange(1, len(f) + 1)
exact = voc_ap(tp / n_faces, tp / n)
return ap, exact, recs[-1] / n_faces, n_faces
def dropped_on(images, setting):
"""Detections excused in a setting, by the tier of the face they hit."""
out = np.zeros(4, int)
for gt, tiers, d in images:
d = d[np.argsort(-d[:, 4], kind="stable")]
g = np.c_[gt[:, :2], gt[:, :2] + gt[:, 2:]]
prop, _ = match(gt, tiers <= setting, d)
for dd in d[~prop]:
out[tiers[boxoverlap(g, np.r_[dd[:2], dd[:2] + dd[2:4]]).argmax()]] += 1
return out
sigmoid = lambda z: 1 / (1 + np.exp(-z))
rows = []
for seed in range(5):
rng = np.random.default_rng(seed)
imgs = [make_image(rng) for _ in range(200)]
r = {}
for name, st in SETTINGS.items():
ap, exact, rec, n = wider_ap(imgs, st, transform=sigmoid)
r[name] = (n, rec, ap, exact)
drop = dropped_on(imgs, 0)
ap_logit = wider_ap(imgs, 2)[0] # raw logits, same ranking
ap_out, ex_out = wider_ap(imgs, 2, transform=sigmoid, extra=[0, 0, 4, 5, -1e3])[:2]
unann = [(g[t == 0], t[t == 0], d) for g, t, d in imgs] # only Easy faces annotated
ap_unann = wider_ap(unann, 0, transform=sigmoid)[0]
rows.append((r, drop, ap_logit, ap_out, ex_out, ap_unann))
if seed == 0:
print("seed 0 faces counted final recall AP (official) AP (exact)")
for name, (n, rec, ap, exact) in r.items():
print(f"{name:8s} {n:13d} {rec:13.3f} {ap:14.3f} {exact:11.3f}")
print("Easy setting, detections excused by tier:",
dict(zip(TIERS, drop.tolist())))
print("\nover 5 seeds (mean, min, max)")
def line(label, v):
v = np.array(v); print(f"{label:52s} {v.mean():.3f} {v.min():.3f} {v.max():.3f}")
for name in SETTINGS:
line(f"{name}: final recall", [r[name][1] for r, *_ in rows])
line(f"{name}: AP (official)", [r[name][2] for r, *_ in rows])
line("Hard: exact AP", [r["Hard"][3] for r, *_ in rows])
line("Hard: official AP, logits instead of sigmoid scores", [x[2] for x in rows])
line("Hard: official AP, plus one detection scored -1000", [x[3] for x in rows])
line("Hard: exact AP, plus one detection scored -1000", [x[4] for x in rows])
line("Easy: official AP if non-Easy faces were unannotated", [x[5] for x in rows])
seed 0 faces counted final recall AP (official) AP (exact)
Easy 348 0.971 0.955 0.955
Medium 761 0.920 0.890 0.891
Hard 1732 0.768 0.729 0.729
Easy setting, detections excused by tier: {'easy': 0, 'medium-only': 392, 'hard-only': 655, 'never counted': 120}
over 5 seeds (mean, min, max)
Easy: final recall 0.975 0.965 0.988
Easy: AP (official) 0.958 0.950 0.971
Medium: final recall 0.906 0.896 0.920
Medium: AP (official) 0.877 0.865 0.890
Hard: final recall 0.742 0.722 0.768
Hard: AP (official) 0.705 0.681 0.729
Hard: exact AP 0.705 0.682 0.729
Hard: official AP, logits instead of sigmoid scores 0.705 0.681 0.729
Hard: official AP, plus one detection scored -1000 0.478 0.449 0.496
Hard: exact AP, plus one detection scored -1000 0.705 0.682 0.729
Easy: official AP if non-Easy faces were unannotated 0.788 0.756 0.814
The same detections give three different scores because each setting decides which faces exist for the detector. A small face that only Hard counts is invisible to Easy in both directions: missing it costs no Easy recall, and a correct detection of it is removed from the proposals instead of being counted as a false positive. In seed 0, Easy excuses more than a thousand detections this way, most of them on Hard-only faces, and the 120 detections on faces that no setting counts are excused in all three. The last row shows what the ignore lists protect. If the same non-Easy faces were simply missing from the ground truth, every detection of them would become a false positive, and Easy AP would fall from a mean of 0.958 to 0.788 over the seeds. Hard AP is the lowest of the three because Hard counts the faces the detector handles worst, not because it is scored by a different rule; background false positives weigh on all three settings alike, since only hits on ignored faces are excused.
The other rows concern the 1,000 thresholds. With sigmoid scores the sampled curve and the exact curve give the same AP to within 0.001, and raw logits, a different scale with the same ranking, change nothing either: in this example the scores are spread over many of the thresholds. One extra detection with score −1000 changes that. Min–max normalization then maps every other detection into , the first threshold interval, so the curve collapses to a single point, the final precision and recall, and the code’s AP drops by about 0.23 while the exact AP is unchanged, as it must be for a detection ranked last. The extra detection is our construction, chosen to show the mechanism; a real submission whose scores bunch near the top of its range, or include a single extreme value, loses resolution in the same way to a smaller degree.
License
The official page ends with a License section that reads, in full, “Creative Common License (cc by-nc-nd)” (as of October 2026). It gives no version and links no license text, and it does not say whether the terms apply to the images, the annotations or both. The abbreviation corresponds to the Creative Commons Attribution-NonCommercial-NoDerivatives licenses, which allow non-commercial sharing with attribution and without modification, but which version and which material it covers are unclear from the page. The images themselves were collected from Google and Bing searches for WIDER (Xiong et al., 2015); neither the WIDER FACE page nor the archived WIDER page states who holds their copyright or under what terms they may be used. In the evaluation code, boxoverlap.m carries an MIT-like license notice from the voc-release code of Felzenszwalb and Girshick, the unused nms.m an MIT license notice from Malisiewicz’s Exemplar-SVM library, and the plotting helper saveTightFigure.m a copyright line of E. Akbas (2010) without terms; the evaluation files written for WIDER FACE carry no license notice.
Limitations and Bias
- People in web photographs. The faces belong to people photographed at public and private events whose images were found by web search. Neither the paper nor the official page discusses consent, privacy or the demographic composition of the people pictured, and the page gives no channel for removing an image (as of October 2026). The general questions these raise for face datasets are discussed in dataset bias.
- Selection by event queries. The scenes are those that search engines return for 60 or 61 event names drawn largely from an ontology whose concepts come mainly from TV news (Xiong et al., 2015, §3), which favours crowds, sports, ceremonies and public gatherings; the WIDER FACE authors present this as a source of diverse backgrounds (§3.3). How far it represents other uses, such as surveillance video or personal photographs, is not measured.
- An undocumented difficulty assignment. The paper defines the settings by EdgeBox recall but not the rule that put each face in a setting, and only the validation lists are public, so Easy and Medium AP are tied to these lists rather than to a stated face size or attribute.
- Annotation convention. Boxes span the forehead, chin and cheeks, and faces of 10 pixels or less are ignored. FDDB uses ellipses, and the WIDER FACE paper itself applied a linear transformation to each baseline’s boxes to fit WIDER FACE’s annotation, following Mathias et al. (§5.1). Results across face datasets are comparable only after such adjustments.
- Test evaluation by email. Without an evaluation server, test results depend on the organizers’ availability. Papers report most ablations on the validation set, whose ground truth is public and can be used for tuning.
- Saturation. By 2020 the best published Hard test results were within about a point of one another: TinaFace’s comparison lists seven entries from 0.912 to 0.924, six of them with test-time augmentation (Zhu et al., 2020, Table 2).
Common Uses
- Training face detectors. The training set, often with the validation set, is the standard training data for the detectors in Face Detection, including those evaluated on other benchmarks; the paper’s ACF and Faceness detectors retrained on WIDER FACE improved on FDDB as well (§5.2).
- Validation for ablations. Papers report component studies on the validation set with the official code, for example Hu and Ramanan’s comparison of backbones (2017, Table 2) and RetinaFace’s ablation of its extra supervision (Deng et al., 2020, Table 1).
- Final comparison on the test set in the three settings, usually under Scenario-Int, with Hard as the headline number.
- Analysis by attribute. The scale, occlusion, pose and event labels allow failure analysis such as the paper’s own (§5.1), and the event labels allow per-event AP.
Historical Milestones
- 2015–2016, the baselines. Under Scenario-Ext, four detectors trained elsewhere scored at most 0.704 AP on Easy, 0.573 on Medium and 0.273 on Hard (Faceness; Fig. 6), with Viola–Jones lowest at 0.412, 0.333 and 0.137; none exceeded 12% AP on un-occluded faces 10–50 pixels tall. Figure 7, which repeats the ACF baseline, prints slightly different values for it (0.639, 0.521, 0.253 against 0.642, 0.526, 0.252 in Figure 6). Retrained on WIDER FACE (Scenario-Int), Faceness reached 0.713, 0.604 and 0.315, and the authors’ multi-scale cascade CNN, with separate networks for faces of 10–30, 30–120, 120–240 and 240–480 pixels, raised Hard to 0.400 (Fig. 8). These results, on the test set, established that small faces were the open problem.
- 2017, tiny faces. Hu and Ramanan’s hybrid-resolution detector, with scale-specific templates and large context, reached 0.819 AP on the Hard test set, which they describe as halving the error of prior methods; the best earlier entries in their comparison, CMS-RCNN and the multi-task cascade CNN (MTCNN), had 0.643 and 0.607 (Hu & Ramanan, 2017, Fig. 11).
- 2019–2020, above 0.9 on Hard. Single-stage detectors with feature pyramids and anchors tuned for small faces passed 0.9 AP on the Hard test set; RetinaFace reported 0.917 (ResNet-152; Deng et al., 2020, §4.3 and Fig. 7; TinaFace’s Table 2 lists it at 0.914) and TinaFace 0.921 with a single model at one scale and 0.924 with test-time augmentation (Zhu et al., 2020, Table 2). Face Detection compares these methods.
- 2022, the last entries. The official results page lists Scenario-Int methods published up to 2022 (as of October 2026).
Related Datasets
FDDB
FDDB (Face Detection Data Set and Benchmark), released by Vidit Jain and Erik Learned-Miller of the University of Massachusetts Amherst in 2010, was the main benchmark for unconstrained face detection before WIDER FACE. Its images come from Berg et al.’s collection of news photographs and captions from Yahoo! News: from 3,527 images selected in chronological order, near-duplicates were found by clustering and manual inspection (682 images in 103 clusters, plus three further cases) and removed, and faces were annotated in 2,845 images, giving 5,171 faces after regions under 20 pixels in height or width were excluded. Annotators rejected regions in which neither eye (or a pair of glasses) was visible or whose position, size or orientation they could not estimate, and faces looking away from the camera were labelled non-faces (Jain & Learned-Miller, 2010, §4–5).
Each face is an ellipse given by its half-axes, orientation and centre. The major axis runs from the chin to the top of the head, the sides follow the boundary between face and ears, hair is ignored and occluded faces are drawn at their hypothesized full extent (§5.1, Appendix A). Initial ellipses were fitted to a skin classifier’s output and then checked and adjusted by hand. Detections may be rectangles or ellipses, each with a score.
The protocol has three parts:
- Matching. In each image, detections and faces are matched one to one by the Hungarian algorithm so that the total overlap is maximized, overlap being the IoU of the two regions (§6, Eq. 2, and §6.1); the code computes it on rasterized regions, so rectangles and ellipses can be compared.
- Two scores per matched detection (§6.2). The discrete score is 1 if the overlap exceeds 0.5 and 0 otherwise; the continuous score is the overlap itself. In the code (
Results.cpp), a matched detection with overlap 0.5 or less still adds its overlap to the continuous total but counts as a false positive in both. - ROC curves. The report recommends ROC curves for both scores. The code sweeps the threshold over every distinct detection score and writes the true positive rate, the summed score divided by the number of faces, against the number of false positives, not a false positive rate, since the number of non-face regions has no fixed size. Results are usually quoted at a fixed number of false positives.
The images are divided into ten fixed folds. In EXP-1 a detector is trained by ten-fold cross-validation on FDDB, and in EXP-2 any outside training data are allowed; in both, the ten ROC curves, one per fold, are averaged (§7). The report’s baselines, all frontal detectors run under EXP-2, included OpenCV’s Viola–Jones implementation with a scale factor of 1.2 and no minimum number of neighbours. Because box detectors are scored against ellipses, later authors fitted ellipses to their boxes before scoring, which matters for the continuous score; Face Detection gives examples. The FDDB website could not be reached when checked in October 2026 (its host name did not resolve); the report and code are cited here from archived copies.
Others
- AFW (Zhu & Ramanan, 2012): 205 Flickr images with 473 faces, each with a box, six landmarks and pose angles (WIDER FACE paper and page).
- PASCAL Faces: 851 images with 1,341 faces in the WIDER FACE paper’s count.
- MALF: 5,250 images with 11,931 faces, which the WIDER FACE paper calls the first face detection dataset to support fine-grained evaluation; it withheld its test annotations and, with KITTI, was a model for WIDER FACE’s difficulty levels.
- IJB-A: 24,327 images and 49,759 faces for detection and recognition, the largest earlier set by the paper’s comparison.
- WIDER: the event recognition dataset from which the images were selected (Xiong et al., 2015).
- MAFA, a benchmark of masked faces, and the datasets of Face Recognition such as Labeled Faces in the Wild serve neighbouring problems.
Resources
- Official page: description, release notes, download links for images and annotations, submission format, the two scenarios and the license line.
- Results page: precision–recall curves of the listed methods on validation and test, by scenario and setting.
- Evaluation code: the MATLAB evaluation and plotting scripts with the validation ground truth and setting lists.
- Technical report on arXiv, with the appendix on the multi-scale cascade and the event tables.
- FDDB’s report and evaluation code, archived copies.
Related
- PASCAL VOC
The PASCAL Visual Object Classes challenge (2005–2012), whose 20-class datasets of Flickr photographs with bounding boxes and segmentations set the standard protocol for evaluating object detection.
- KITTI
A benchmark suite of real driving data from Karlsruhe, with stereo, optical flow, scene flow, odometry, object detection, and tracking benchmarks built from camera, LiDAR, and GPS/IMU recordings.
- Viola-Jones Object Detection
The boosted cascade detector of Viola and Jones, which selects a few rectangle features with AdaBoost and chains the resulting classifiers so that most background windows are rejected after a handful of feature evaluations.
- Face Recognition
Deciding whether two face images show the same person (verification) or which enrolled person a face belongs to (identification, closed- or open-set), with the detect, align, embed and compare pipeline, its benchmarks and evaluation protocols, and NIST's measurements of demographic differentials.
- Dataset Bias
How the way a dataset's images are chosen, photographed and labelled makes it an unrepresentative sample of the visual world, how cross-dataset tests measure the damage, and what bias means when the images show people, from demographic representation to withdrawn datasets.
- 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
- Yang, S., Luo, P., Loy, C. C. & Tang, X. (2016). WIDER FACE: A Face Detection Benchmark. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 5525–5533.
- Yang, S., Luo, P., Loy, C. C. & Tang, X. (2015). WIDER FACE: A Face Detection Benchmark. arXiv:1511.06523v1 (technical report with appendix).
- Yang, S., Luo, P., Loy, C. C. & Tang, X. WIDER FACE: A Face Detection Benchmark, official website, home and results pages (accessed October 2026).
- Yang, S. WIDER FACE evaluation code, eval_tools.zip (wider_eval.m, read_pred.m, norm_score.m, evaluation.m, boxoverlap.m, plot/VOCap.m; announced 31 March 2017, archive members dated 21 June 2022, file last modified 26 October 2022; read in October 2026).
- Xiong, Y., Zhu, K., Lin, D. & Tang, X. (2015). Recognize Complex Events from Static Images by Fusing Deep Channels. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 1600–1609.
- Xiong, Y. Web Image Dataset for Event Recognition (WIDER), project page (archived copy of 6 November 2016).
- Jain, V. & Learned-Miller, E. (2010). FDDB: A Benchmark for Face Detection in Unconstrained Settings. Technical Report UM-CS-2010-009, University of Massachusetts Amherst (archived copy).
- Jain, V. (2010). FDDB evaluation code, evaluation.tgz (Matching.cpp, Results.cpp, evaluate.cpp; archived copy of 7 July 2022).
- Hu, P. & Ramanan, D. (2017). Finding Tiny Faces. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 1522–1530.
- Deng, J., Guo, J., Ververas, E., Kotsia, I. & Zafeiriou, S. (2020). RetinaFace: Single-Shot Multi-Level Face Localisation in the Wild. IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), 5202–5211.
- Zhu, Y., Cai, H., Zhang, S., Wang, C. & Xiong, Y. (2020). TinaFace: Strong but Simple Baseline for Face Detection. arXiv:2011.13183v3.