nx_haar_cascade.nx source
↩ module page · 59 lines · 2472 B
1// nx_haar_cascade.nx -- Viola-Jones attentional cascade EVALUATOR (R-FACE-2).
2// The detector engine: a weak classifier is a Haar feature + threshold +
3// polarity; a stage sums weighted weak votes vs a stage threshold; the cascade
4// runs stages in order and EARLY-REJECTS the moment any stage fails (so the
5// vast non-object majority is discarded after 1-2 cheap stages).
6//
7// This evaluates a GIVEN cascade. The cascade PARAMETERS (thresholds/polarities/
8// alphas/stage thresholds) come from TRAINING (AdaBoost over a labeled face /
9// non-face set) -- a separate data-dependent rung. This rung is the machinery,
10// validated with a hand-built toy cascade.
11//
12// Layout (caller-supplied flat i64 arrays):
13// weak row (8 i64): [kind, x, y, w, h, threshold, polarity(+1/-1), alpha]
14// stage row (3 i64): [weak_offset(in rows), weak_count, stage_threshold]
15//
16// genealogy_id: viola_jones_2001_attentional_cascade + freund_schapire_adaboost_1997
17// lineage_id: weak_classifier + boosted_stage + early_reject_cascade
18// license_tier: ORIGINAL
19import "syscalls.nx"
20import "nx_image.nx"
21import "nx_integral.nx"
22import "nx_haar.nx"
23
24const NX_WEAK_FIELDS: i64 = 8
25const NX_STAGE_FIELDS: i64 = 3
26
27// One weak classifier: 1 if the feature votes "object", else 0.
28// vote = (polarity * feature) < (polarity * threshold)
29func nx_weak_eval(ii: *IntegralImage, weak: *i64) -> i64 {
30 let f: i64 = nx_haar_eval(ii, weak[0], weak[1], weak[2], weak[3], weak[4])
31 let pol: i64 = weak[6]
32 if pol * f < pol * weak[5] { return 1 }
33 return 0
34}
35
36// One stage: pass(1)/fail(0). Pass if sum of alpha over firing weaks >= stage_thresh.
37func nx_stage_eval(ii: *IntegralImage, weaks: *i64, n: i64, stage_thresh: i64) -> i64 {
38 var s: i64 = 0
39 var i: i64 = 0
40 while i < n {
41 let row: *i64 = (weaks as i64 + i * NX_WEAK_FIELDS * 8) as *i64
42 if nx_weak_eval(ii, row) == 1 { s = s + row[7] }
43 i = i + 1
44 }
45 if s >= stage_thresh { return 1 }
46 return 0
47}
48
49// Full cascade: 1 if ALL stages pass (early reject on first failure).
50func nx_haar_cascade_eval(ii: *IntegralImage, stages: *i64, n_stages: i64, weaks: *i64) -> i64 {
51 var st: i64 = 0
52 while st < n_stages {
53 let meta: *i64 = (stages as i64 + st * NX_STAGE_FIELDS * 8) as *i64
54 let wrow: *i64 = (weaks as i64 + meta[0] * NX_WEAK_FIELDS * 8) as *i64
55 if nx_stage_eval(ii, wrow, meta[1], meta[2]) == 0 { return 0 }
56 st = st + 1
57 }
58 return 1
59}