Rebuild the CineQC baseline
Measure artifacts before asking a model to learn them.

- Implement metrics for flicker, stutter, color drift, sharpness collapse, and motion incoherence.
- Calibrate thresholds and explain normalization, false positives, and operating limits.
- Generate controlled synthetic defects and compare them with clean controls.
Explain why a metric fires on a synthetic defect and where it could produce a false positive.
Before training a model, make five deterministic signals visible. The Artifact Lab creates controlled defects, records raw scores, calibrates bounded thresholds, and shows where each heuristic lies.
Required route: diagnostic/model (45 min), five baselines (120 min), controlled defects and calibration (75 min), sandbox build (75 min), failure clinic (35 min), transfer/evidence (70 min). Total: 7 hours, including the selected OpenCV reading.
Entry diagnostic
A brightness-jump metric fires on a deliberate white flash. Is that automatically a defect? Explain the signal it measured, one plausible false positive, one clean control, and the human decision still required.
Self-check
Why must a test pair one changed sequence with an otherwise identical clean control?
Why this matters in CineQC
Heuristics are cheap, inspectable baselines. They expose signal before complexity and provide a fallback when a learned model is unavailable. They are not truth: editing, camera motion, intentional flashes, grain, and compression can resemble defects. CineQC should preserve the raw measurement, calibrated threshold, context, and human-review route.
Visual model — sequence to signal to decision
Five signal rows compare flicker, stutter, color drift, sharpness collapse, and motion incoherence measurements.
Each baseline follows decoded frame → CineQC worker reduction → tiny time series → metric score → review flag. The faithful bounded route here mirrors the current cineqc/workers/analysis.worker.js reductions and cineqc/js/metrics.js aggregations. It uses smaller arrays and grids so you can inspect them; it does not silently substitute different metrics.
Use luma units consistently (0..255 in CineQC). The first signal is second-difference RMS flicker: compute adjacent luma deltas, then the RMS of changes between those deltas. This high-pass measure ignores slow exposure drift better than a largest-jump proxy.
Runtime: Local Python 3.12 · NumPy 2.x · 20 min.
import numpy as np
luma_clean = np.array([100, 101, 102, 103, 104], dtype=np.float32)
luma_pulse = np.array([100, 101, 125, 103, 104], dtype=np.float32)
def second_difference_rms(luma):
deltas = np.diff(luma)
return float(np.sqrt(np.mean(np.diff(deltas) ** 2))) if len(deltas) >= 2 else 0.0
print(second_difference_rms(luma_clean), round(second_difference_rms(luma_pulse), 2))
Five deterministic baselines

Five defect frames and their signal plots shown side by side. If the video cannot play, this image and the transcript preserve the complete teaching claim.
- Flicker: second-difference RMS over the mean-luma series; CineQC maps about 8 luma RMS acceleration to its lowest quality score. It can flag flashes and cuts.
- Stutter: an 8×8 grid of mean-luma block fingerprints; adjacent fingerprints whose mean absolute block delta is below
0.08are duplicates. It can flag valid held frames or static shots. - Color drift: Bhattacharyya distance between normalized 4×4×4 RGB histograms eight frames apart. Comparisons crossing a scene boundary are set to zero; boundaries use adjacent-histogram Hellinger distance. It can flag intentional lighting changes.
- Sharpness collapse: variance of the four-neighbour Laplacian per frame, then a flag when a value falls below half the clip median. It can flag focus pulls or low-detail frames.
- Motion incoherence: downsample luma to 64×64, block-match 8×8 regions within a four-pixel search radius, then average each flow vector’s disagreement with its four-neighbour mean. It can flag cuts, whip pans, occlusion, or ambiguous texture.
The exercises may use 2×2 fingerprints, fewer histogram bins, and smaller flow grids for legibility, but preserve the same reduction and aggregation. Any such simplification must be named beside its result; the CineQC transfer reruns the production grid, bins, window, and search settings.
Runtime: Local Python 3.12 · NumPy 2.x · 25 min.
import numpy as np
def block_fingerprint(frame, grid=2):
height, width = frame.shape
return np.array([
frame[y * height // grid:(y + 1) * height // grid,
x * width // grid:(x + 1) * width // grid].mean()
for y in range(grid) for x in range(grid)
])
clean_a = np.arange(16, dtype=np.float32).reshape(4, 4)
clean_b = clean_a + 1
duplicate = clean_a.copy()
delta_real = np.abs(block_fingerprint(clean_b) - block_fingerprint(clean_a)).mean()
delta_duplicate = np.abs(block_fingerprint(duplicate) - block_fingerprint(clean_a)).mean()
print(delta_real, delta_duplicate, delta_duplicate < 0.08)
For color drift, compare window-lagged normalized histograms, and mask any comparison whose interval includes a scene-cut boundary. The production window is eight frames; this tiny demonstration uses two so every term is visible.
Runtime: Browser lab · Pyodide with NumPy · 20 min.
import numpy as np
def bhattacharyya(p, q):
return float(-np.log(max(float(np.sqrt(p * q).sum()), 1e-9)))
histograms = [
np.array([1.0, 0.0]), np.array([0.9, 0.1]),
np.array([0.2, 0.8]), np.array([0.1, 0.9]),
]
boundaries = [False, False, True, False]
window = 2
series = []
for index in range(window, len(histograms)):
crosses_cut = any(boundaries[index - window + 1:index + 1])
series.append(0.0 if crosses_cut else bhattacharyya(histograms[index], histograms[index - window]))
print(series)
Sharpness uses the actual four-neighbour Laplacian variance, not general edge energy. Compare every frame to the sequence median and flag values below median × 0.5.
Runtime: Browser lab · Pyodide with NumPy · 20 min.
import numpy as np
def laplacian_variance(frame):
values = frame.astype(np.float32)
lap = (4 * values[1:-1, 1:-1] - values[1:-1, :-2] - values[1:-1, 2:]
- values[:-2, 1:-1] - values[2:, 1:-1])
return float(lap.var())
checker = (np.indices((8, 8)).sum(axis=0) % 2 * 255).astype(np.float32)
blurred = np.full((8, 8), 127.5, dtype=np.float32)
sharp_values = np.array([laplacian_variance(checker)] * 4 + [laplacian_variance(blurred)])
median = float(np.median(sharp_values))
print(sharp_values.tolist(), (sharp_values < median * 0.5).tolist())
Motion uses local block-flow vectors, then measures neighbour disagreement. For the learning version, inspect a prepared vector grid: uniform pan vectors have zero disagreement; one contradictory block raises it. In the CineQC transfer, obtain those vectors with the production 64×64 downsample, 8×8 blocks, and ±4 search.
Runtime: Local Python 3.12 · NumPy 2.x · 20 min.
import numpy as np
def neighbor_disagreement(flow):
scores = []
height, width, _ = flow.shape
for y in range(height):
for x in range(width):
neighbors = [flow[ny, nx] for nx, ny in ((x-1,y),(x+1,y),(x,y-1),(x,y+1))
if 0 <= nx < width and 0 <= ny < height]
scores.append(np.linalg.norm(flow[y, x] - np.mean(neighbors, axis=0)))
return float(np.mean(scores))
smooth_pan = np.ones((3, 3, 2), dtype=np.float32)
chaotic = smooth_pan.copy(); chaotic[1, 1] = (-3, 4)
print(neighbor_disagreement(smooth_pan), round(neighbor_disagreement(chaotic), 3))
Self-check
A static locked-off shot produces a high duplicate ratio. What context prevents the stutter heuristic from becoming a false claim?
Generate one defect at a time

Numbered contact strip exposes the repeated frame without motion. If the video cannot play, this image and the transcript preserve the complete teaching claim.
Start with deterministic arrays or a lawful sanitized clip. Create a clean/defect pair for every metric, changing exactly one factor:
- add one luma pulse for flicker;
- duplicate selected frames for stutter;
- ramp one color channel for drift while retaining a separate hard-cut pair to prove cut masking;
- blur a bounded interval for sharpness collapse;
- shift or scramble a bounded interval for motion incoherence.
Keep a manifest with generator seed, parameters, affected frame range, and parent fixture identity. If multiple defects change at once, attribution becomes ambiguous.
Runtime: Local Python 3.12 · NumPy 2.x · 20 min.
import numpy as np
rng = np.random.default_rng(7)
base = rng.random((12, 16, 16), dtype=np.float32) * 12 + 110
drift = base.copy()
drift[6:] = np.clip(drift[6:] + 25, 0, 255)
print(base.shape, round(float(base.mean()), 2), round(float(drift[6:].mean()), 2))
Calibrate, do not guess
Create a small calibration table with raw score, defect/control label, and review note. Sweep candidate thresholds on calibration data only. Choose an operating point based on the cost of missed defects versus extra human review, then report results on untouched examples.
Do not tune on the final examples and then call their result a test. Preserve false-positive and false-negative galleries because aggregate accuracy hides why a heuristic failed.
Sandbox lab
Use local Python for the complete Artifact Lab; the current browser runner supports NumPy/Pillow scratch blocks but has no guided M06 package and no OpenCV. Implement faithful bounded equivalents of the five CineQC metrics as pure functions that return raw scores plus intermediate values. Generate five clean/defect pairs—one pair per metric—and an extra cut-masking check for color drift. Save a CSV or JSON score table and a compact HTML or notebook gallery.
Failure clinic
Diagnose these believable mistakes:
- adjacent luma jump used for flicker instead of second-difference RMS;
- a hard-coded threshold calibrated on the same examples reported as test results;
- scene cuts counted as flicker and motion defects without context;
- stutter inferred from nominal fps instead of block-fingerprint similarity;
- generic edge energy or frame difference substituted for Laplacian collapse or block-flow neighbour disagreement.
Repair with float conversion, separated calibration/test examples, review context, decoded measurements, and per-signal evidence.
CineQC transfer
For each CineQC-adjacent signal, compare the reimplementation with the current system on the same sanitized sequence. Record input contract, raw intermediates, aggregation, threshold, and outcome. A mismatch is an investigation result—not permission to silently modify production. State which version and settings were compared.
Self-check
What evidence distinguishes a useful imperfect heuristic from an untrustworthy one? Include calibration provenance, error cases, and a bounded human-review role.
Evidence gate
The Artifact Lab is complete when it contains:
- five named pure baseline functions faithfully matching second-difference RMS, block-fingerprint duplicates, masked window-lagged histogram distance, Laplacian-variance collapse, and block-flow neighbour disagreement;
- five deterministic clean/defect pairs plus a scene-cut masking pair, all with a generation manifest;
- a calibration table, frozen threshold choices, and results on separate examples;
- false-positive and false-negative cases with production context;
- a concise comparison with CineQC behavior, versioned and free of private media;
- a README that calls every metric a heuristic and states its known limitations.
Bound the artifact to five signals and a small lawful fixture. Do not add a learned model here.
One-page summary
- Measure first; decide with a separately calibrated threshold.
- Pair every controlled defect with an unchanged control.
- Preserve raw scores and per-signal intermediates.
- Calibrate away from the examples used for final reporting.
- False positives reveal context the metric cannot see.
- Heuristics remain useful as inspectable baselines and fallbacks.
- Artifact Lab proves disciplined measurement, not universal visual truth.
Use the official blur and filtering concepts to reason about sharpness and controlled defects. · 20 min
Read only the flow assumptions and failure cases when extending the motion baseline. · 20 min
Mini-capstone 2: Artifact Lab, an interactive case study comparing Python reimplementations with CineQC behavior.
Check the statements you can demonstrate in the challenge. Selections route your learning; they are not proof of mastery.
Start the full milestone.
Submit an inspectable artifact for independent review. Only a verified diagnostic challenge or reviewed evidence can mark this milestone proven. Proof is local self-tracking, not tamper-resistant against edits to this browser storage.
- Implement five deterministic baselines with inspectable intermediate values.
- Compare controlled defects with clean controls and record raw scores.
- Document calibrated thresholds, false positives, and honest limitations.
Current state: not-started. Advance through learning, practice, and submitted evidence; proof requires a later passed review.
Your local study notes mount here when JavaScript is available.
Teaching modes mount here when JavaScript is available. The readable course remains available without them.