Responsible CV: Privacy, Fairness, Security, Governance
In this series (30 parts)
- Computer Vision Roadmap: From Basics to Real Projects
- What is Computer Vision? From Pixels to Decisions
- A Short History of Computer Vision: 1545 to Now
- Math for CV Beginners: Vectors, Matrices, Convolutions
- Image Fundamentals: Color, Histograms, Noise, Filtering
- How Images and Video Are Stored: Colour, JPEG, Frames
- OpenCV Setup + First 10 Tasks in Python
- Vision Metrics: Accuracy, Precision, Recall, mAP, IoU
- CV Project Workflow: Dataset, Baseline, Error Iteration
- Intensity Transforms and Frequency-Domain Filtering
- Edge Detection and Thresholding That Actually Work
- Morphology, Contours, and Shape Analysis for Real Images
- Feature Matching (SIFT/ORB) and Image Stitching
- Camera Calibration and Perspective Correction
- Epipolar Geometry, Stereo Vision, and Depth Estimation
- Optical Flow and Motion Tracking in Video
- HOG, HOF and MBH: Descriptors Before Deep Learning
- Your First Image Classifier (PyTorch + Transfer Learning)
- Data Pipelines and Augmentation for Vision Models
- CNN Architectures Explained: From LeNet to ResNet
- YOLO Detection Pipeline: Data to Inference
- Semantic and Instance Segmentation: U-Net to Mask R-CNN
- Vision Transformers (ViT) and When to Use Them
- CV Explainability: Grad-CAM, Failures, Bias Checks
- 3D Vision Basics: SfM, Point Clouds, and Pose Estimation
- Multimodal Vision: CLIP, Embeddings, and Retrieval Systems
- Video Understanding: Flow Networks, Interpolation, Stabilisation
- Real-Time CV Systems: Tracking, Latency, Streaming
- Deploying CV Models: ONNX, TensorRT, Edge, and APIs
- Responsible CV: Privacy, Fairness, Security, Governance
The traffic counting system works. It also has eight cameras pointed at a public street, storing footage of everyone who walks past, and a pedestrian detector whose recall nobody has checked across different groups of people. None of that shows up in the mAP.
Prerequisites: Model explainability and bias checks and deploying computer vision models.
Four questions, all measurable
| # | Question | Concretely | Measured by |
|---|---|---|---|
| 1 | Does it work equally well? | Recall by group | Slice metrics + confidence intervals |
| 2 | What are we storing? | Bytes retained, and for how long | Data inventory |
| 3 | Can it be attacked? | Accuracy under perturbation | Adversarial evaluation |
| 4 | Who is accountable? | Named owner, documented limits | Model card + release checklist |
None of these are philosophical. All four produce a number or a name.
Fairness, computed
fairness gap A difference in a model's performance between groups of people, measured with the same metric on comparable data.The pedestrian detector, evaluated on a held-out set split by apparent skin tone using the Fitzpatrick scale:
| # | Group | N | Detected | Recall target | FPR |
|---|---|---|---|---|---|
| 1 | Fitzpatrick 1–3 (lighter) | 1840 | 1641 | 0.8918 | 0.041 |
| 2 | Fitzpatrick 4–6 (darker) | 1210 | 1022 | 0.8446 | 0.048 |
Recall by group on the pedestrian detector.
Equal opportunity difference — the gap in recall:
Disparate impact ratio — the ratio of the lower to the higher:
four-fifths rule A rule of thumb from US employment law: if the ratio between groups falls below 0.8, the disparity is treated as significant enough to require justification.
At 0.947 this passes. But before acting on either number, check whether they are real.
The confidence interval that decides whether the gap exists
Recall is a proportion, so the standard error is:
For the darker-skinned group at :
The lighter group’s interval is . They do not overlap, so the 4.7-point gap is real.
Now suppose the slice had only 120 samples:
That interval comfortably contains the other group’s recall. The same 4.7-point gap would be indistinguishable from noise.
| # | Slice size n | SE | 95% CI half-width target | Smallest detectable gap |
|---|---|---|---|---|
| 1 | 60 | 0.0468 | ±0.092 | ~18 points |
| 2 | 120 | 0.0331 | ±0.065 | ~13 points |
| 3 | 300 | 0.0209 | ±0.041 | ~8 points |
| 4 | 1210 | 0.0104 | ±0.020 | ~4 points |
| 5 | 5000 | 0.0051 | ±0.010 | ~2 points |
At recall 0.845. A slice of 60 cannot detect anything under about 18 points, which is a catastrophic gap.
Where the gap comes from, and what to do
| # | Cause | How to check | Fix | Typical gain target |
|---|---|---|---|---|
| 1 | Training data under-represents the group | Count examples per group | Collect more, or reweight the loss | large |
| 2 | Low-light performance differs | Slice by time of day as well | Add night data, improve exposure handling | large |
| 3 | Annotation quality differs | Re-adjudicate a sample from each group | Fix labels, retrain | moderate |
| 4 | One global threshold suits one group | Plot PR curves per group | Per-group thresholds (check legality first) | moderate |
| 5 | Genuine visual difficulty | Expert review of the errors | Usually needs a model or sensor change | small |
Diagnose before fixing. The first two explain most gaps and are the cheapest to address.
Slicing by two variables at once is usually the revealing step. The gap above was 4.7 points overall — but 1.9 points in daylight and 11.3 points after dark. That is not a fairness problem in the abstract; it is a low-light problem that lands unevenly, and the fix is exposure handling and night-time training data.
Privacy through not collecting things
data minimisation Collecting and keeping only the data needed for the stated purpose, for only as long as it is needed.The traffic system’s purpose is counting vehicles. Compare what that requires with what a default installation stores:
| # | What is stored | Per year (8 cameras) target | Re-identifies people? | Needed for counting? |
|---|---|---|---|---|
| 1 | Raw 1080p footage, 30-day rolling | 10.4 TB at any time | yes | no |
| 2 | Cropped detections | ~180 GB | yes | no |
| 3 | Blurred frames | ~126 TB | harder, not impossible | no |
| 4 | Bounding boxes + class + timestamp | ~4 GB | movement patterns only | no |
| 5 | Per-minute aggregate counts | 26 MB | no | yes |
Five levels of retention for the same system. Only the last is required.
The ratio is the argument. Aggregate counts are 400,000 times smaller than the footage and answer the question completely. Everything above them is stored for reasons nobody wrote down — usually “in case we need it later”, which is exactly the reasoning that fails a data protection review.
flowchart TD
A["Camera frame"] --> B["Detect + track<br/>on device"]
B --> C["Aggregate to counts"]
C --> D["Publish counts<br/>per minute"]
A --> E{"Retain frame?"}
E -->|"default"| F["Discard immediately"]
E -->|"explicit request only"| G["Blur faces + plates"]
G --> H["Encrypted store<br/>auto-delete after 7 days"]
H --> I["Access logged<br/>+ approval required"]
The default path never writes a frame anywhere. The retention path exists but requires a specific request, and it expires by itself.
| # | Technique | Protects against | Cost | Limitation |
|---|---|---|---|---|
| 1 | Process on device, never transmit | Interception, cloud breach | edge hardware | Harder to debug remotely |
| 2 | Blur faces and plates before storing | Casual re-identification | ~3 ms/frame | Gait and clothing still identify |
| 3 | Store aggregates only | Almost everything | none | Cannot investigate incidents |
| 4 | Short automatic retention | Long-term profiling | none | Needs enforcement, not policy |
| 5 | Encryption at rest and in transit | Theft, interception | minimal | Not against authorised misuse |
| 6 | Access logging and approval | Insider misuse | process overhead | Detects after the fact |
Privacy controls. The cheapest one — not storing it — is also the strongest.
Security
Three distinct threats, often conflated.
| Threat | What the attacker does | When it happens | Main defence |
|---|---|---|---|
| Evasion | Perturbs the input to avoid detection | at inference | Adversarial training, input checks |
| Poisoning | Corrupts the training data | at training | Data provenance, review of new labels |
| Model extraction | Queries the API to clone the model | at inference | Rate limits, coarse outputs |
| Inversion | Reconstructs training data from the model | at inference | Differential privacy, limit output detail |
Evasion, with numbers
The standard demonstration adds a small perturbation in the direction that most increases the loss:
With , every pixel moves by at most 8 of 255 levels — under the threshold at which a person notices anything.
| # | ε (of 255) | Max pixel change | Visible to a person? | Model accuracy target |
|---|---|---|---|---|
| 1 | 0 | 0 | — | 94.2% |
| 2 | 2 | 0.008 | no | 61.3% |
| 3 | 4 | 0.016 | no | 28.7% |
| 4 | 8 | 0.031 | barely | 10.9% |
| 5 | 16 | 0.063 | faint texture | 3.1% |
FGSM on an undefended classifier. At ε=8/255 the image looks unchanged and accuracy has collapsed.
Physical attacks exist too — printed patches that stop a person being detected, and stickers that change a sign’s classification. They are less transferable than the digital versions, but they need no access to anything.
Whether to care depends entirely on the threat model. A traffic counter has no motivated adversary and adversarial training would cost 7 points of clean accuracy for nothing. A system controlling access to a building does, and the trade looks completely different.
Governance you can actually run
model card A short document recording what a model does, what data it was trained on, how it performs across groups, and where it should not be used.| # | Section | What goes in it | Length |
|---|---|---|---|
| 1 | Intended use | The specific task and setting | 2–3 lines |
| 2 | Out of scope | Uses that are explicitly not supported | 3–5 lines |
| 3 | Training data | Source, size, dates, known gaps | a short paragraph |
| 4 | Performance | Overall metrics plus every slice, with n | a table |
| 5 | Known failure modes | What breaks it, from error analysis | a list |
| 6 | Owner | A named person and a review date | 1 line |
A model card fits on one page. The out-of-scope section is the one people skip and the one that matters.
The out-of-scope section is where a counting model gets stopped from becoming an enforcement model. Writing “this system is not validated for identifying individuals and must not be used for enforcement” before launch is a two-minute job. Writing it after someone has asked for that feature is a negotiation.
A release checklist
| # | Check | Passes when | Blocks release? |
|---|---|---|---|
| 1 | Slice metrics computed | Every slice has n and a CI reported | yes |
| 2 | No slice ratio below 0.8 | Or the gap is documented and justified | yes |
| 3 | Explainability spot-check | Grad-CAM on 20 errors shows no shortcut | yes |
| 4 | Calibration measured | ECE reported; thresholds set on calibrated scores | if a threshold gates a decision |
| 5 | Data retention enforced in code | Automatic deletion job exists and is tested | yes |
| 6 | Model card written | Including the out-of-scope section | yes |
| 7 | Failure path defined | System degrades safely, does not fail open | yes |
| 8 | Monitoring live | Drift, drop rate, and detection-rate alerts firing | yes |
| 9 | Rollback tested | Previous version restorable in under 10 minutes | yes |
| 10 | Named owner and review date | A person, and a date within 12 months | yes |
Ten checks. Most are half a day of work in total, and each one has caught a real problem in some deployment.
flowchart TD
A["Model trained"] --> B["Slice metrics + CIs"]
B --> C{"Any ratio < 0.8?"}
C -->|yes| D["Diagnose cause<br/>fix or document"]
D --> A
C -->|no| E["Explainability spot-check"]
E --> F{"Shortcut found?"}
F -->|yes| D
F -->|no| G["Calibration + thresholds"]
G --> H["Model card + owner"]
H --> I["Canary: 5% of sites"]
I --> J{"Metrics hold for 7 days?"}
J -->|no| K["Roll back"]
K --> D
J -->|yes| L["Full rollout"]
L --> M["Monitor drift"]
M --> N{"Drift detected?"}
N -->|yes| A
- The system's output affects people — access, enforcement, safety, eligibility
- It observes people, whether or not it identifies them
- It will run in settings different from where it was trained
- It is in a regulated domain, or covered by the EU AI Act
- It is a prototype that will not be deployed — but slice your metrics anyway
- There are genuinely no people in the images, such as pure industrial inspection
- You would substitute the review for actually measuring performance
Even in the exempt cases, slice the metrics. It costs an hour and it is the check that finds real bugs, not just governance ones.
Practice task
Use any classifier or detector with metadata available.
- Pick two or more slices. Compute the metric for each, with n.
- Compute the standard error and 95% CI for each slice. Do the intervals overlap?
- Compute the disparity ratio. Compare against 0.8.
- Re-slice on two variables at once — group and lighting, or group and time of day.
- Write down every piece of data your system stores and how long it keeps it. Cross out what is not needed.
- Implement FGSM at ε of 2, 4, 8, 16 of 255. Plot accuracy. Look at the ε=8 image.
- Write a one-page model card, including the out-of-scope section.
- Run the ten-item release checklist honestly. Note which items you cannot currently pass.
Step 8 is the one that finds things. Most systems fail three or four items on the first pass, and the failures are usually the easy ones — no enforced deletion, no named owner, no tested rollback.
Summary
Fairness is measurable. The pedestrian detector had recall 0.8918 and 0.8446 across two groups: a gap of 0.0472 and a ratio of 0.9471, which passes the four-fifths rule. At the confidence intervals were ±0.020 and did not overlap, so the gap was real — at the margin would have been ±0.065 and the same gap would have been invisible. Re-slicing by time of day showed 1.9 points in daylight and 11.3 after dark, which turns a vague fairness concern into a specific low-light fix.
Privacy is mostly about not collecting. Aggregate counts are 26 MB a year against 10.4 TB of rolling footage, and they answer the question completely.
Security depends on the threat model. FGSM at ε = 8/255 took accuracy from 94.2% to 10.9% with no visible change to the image, and adversarial training recovered it to 64.2% at a cost of 7 points on clean data. Only worth it if someone is actually attacking you.
Governance is a one-page model card and ten checks. The out-of-scope section is the one that matters most and takes the least time.
- Fairness is a measurement: recall per group, the difference, and the ratio.
- The four-fifths rule gives a concrete line — a ratio below 0.8 needs justification.
- Always report the confidence interval and n. At n=60, an 18-point gap looks insignificant.
- Slice on two variables at once. A 4.7-point gap was 1.9 in daylight and 11.3 after dark.
- Most fairness gaps trace to training data composition or lighting, not architecture.
- Data minimisation is the strongest privacy control and it is free: 26 MB against 10.4 TB.
- 'Temporary' storage without an enforced deletion job is permanent storage.
- A perturbation of 8/255 per pixel, invisible to a person, took accuracy from 94% to 11%.
- Adversarial training costs ~7 points of clean accuracy — only pay it against a real threat model.
- Write the out-of-scope section before launch. Afterwards it becomes a negotiation.
Where this leaves you
That is the series. You started with a pixel grid and a rule about dark fractions, and worked through image formation, filtering, edges, contours, features, calibration, stereo, motion, classification, detection, segmentation, transformers, explainability, 3D, retrieval, real-time systems, deployment, and now the checks that decide whether any of it should ship.
The series roadmap has the full map if you want to revisit a track. The most useful next step is not another topic — it is one project end to end: collect a small dataset, work the project loop, get something running, and slice its metrics before you tell anyone it works.