AI & Computer Vision, lesson 52 of 52

Retrospective: What You Learned, and What's Next

advanced36 min read

Introduction

You started with "an image is just numbers" and finished by shipping a product that sees, decides and acts. Today you turn round at the top of the climb, look back at the path, and draw a map for the next one: what to learn next, what to build, and how to show it.

By the end of this lesson you'll be able to:

  • Name what you can now do in each of the 11 units, and what you cannot yet
  • Describe four directions in computer vision and what each needs first
  • Explain what a vision job needs beyond a model: data, ethics, testing, communication
  • Write one goal that someone else could check
  • Prepare a portfolio that is complete and safe to share
  • Say what you are proud of and what you would do differently

Working principle

Six months on one page

UnitWhat you can now do
1. Foundations, how computers seeTreat a picture as numbers and manipulate it
2. Classic CV, seeing without AIFind edges, motion and shapes without a trained model
3. Data, annotation and consentCollect, label and split data fairly, with consent
4. Machine learning for visionTrain and read a model, and tell learning from memorising
5. Object detection and trackingDetect and follow objects with YOLO
6. Field trip 1, data harvestCapture real data in the real world
7. Automation, CV that actsTurn detections into triggers, APIs and hardware
8. AI integration with ClaudeCombine code that decides with a model that describes, and check what it says
9. Field trip 2, live eventRun live, keep a log, debrief honestly
10. Fairness and specialised techniquesTest a model across groups, estimate pose and speed, analyse tactics
11. CapstonePlan, build, test and present a whole product

Six ideas that kept coming back

  • Code decides, Claude describes. Let rules make decisions you can test, and let a model explain them.
  • Check everything that comes from outside. A model's answer, a network reply, a file from a stranger.
  • Record raw first. You can always reprocess a recording; you cannot recreate a missed match.
  • Honest error bars. A single number is not a result.
  • Better data beats a cleverer setting.
  • Consent and privacy are part of the design. Especially when the people in the pictures are children.

Where computer vision is heading

These are directions and not predictions. The field moves fast, so check current versions and papers before you start any of them.

DirectionIn one sentenceWhat you already have
Transformer-based visionModels built on attention, as in language models, now sit beside convolutional networks for classification and detectionUnit 4 and Unit 5
Promptable segmentationThe Segment Anything family outlines objects from a point, a box or a short description; SAM 3, released by Meta in late 2025, takes concept promptsUnit 2 and Unit 5
Edge AISmall models run on cheap camera boards, such as the ESP32-lesson 3, with no network, which also helps privacyUnit 4 and Unit 7
Faster, simpler detectorsNew YOLO releases (YOLO26 was announced in early 2026) aim at easier deployment on small devicesUnit 5
Multimodal modelsModels like Claude read images and text together, best when code checks the factsUnit 8
Responsible AIFairness audits, model cards and privacy law are becoming part of the jobUnit 3 and Unit 10

Two honest notes. First, the lessons in this course used a particular version of YOLO, and newer ones exist now. The ideas carry over: data, splits, metrics, the log. Second, "newer" is not always "better for you": test on your data, as in lesson 49.

Where it is used

Sports analytics, broadcast graphics, robotics, farm and crop monitoring, factory inspection, traffic and parking, healthcare imaging, accessibility tools for people who cannot see, wildlife cameras. What you learned applies to all of them: a detector, a trigger, an output, a test, and a duty of care to the people in the picture.

Careers, without hype

People who work with vision are usually part of a team: data and labelling, model training, software that uses the model, testing, product, and people who think about ethics and law. Roles and pay differ a lot by place and change over time, so do not rely on a number from a lesson. Look at current job listings, talk to people doing the work, and read what they ask for. Your portfolio is your answer to those lists.

A roadmap is a hypothesis

Rate yourself, find the gaps, pick a next step you are ready for, and set one goal with a number and a date within a year. The tool checks that the goal is something another person could check. If you wish to step up to something you are not yet ready for, the tool tells you what to strengthen first. The roadmap is not a promise. In three months you look at it and change it.

A portfolio you can share

A portfolio shows what you can do. For this course it holds seven things: your brief, your model card, your acceptance report, your demo (a video or a link), a README that says how to run it, your consent statement, and a short note on what you learned. The checker finds what is missing.

It also keeps you safe. Do not publish raw pictures or videos of people unless the consent you collected covers sharing them. Do not publish API keys: if one ever went into a file, treat it as leaked, delete it from the provider's page and make a new one. Deleting the line from the file is not enough if it was already shared.

Giving thanks and feedback

You learned with the help of teachers, teammates, venues and the people who agreed to be filmed. A short thank you to them is part of finishing well. A short note to your teacher about what worked and what did not helps the next class.

Optional: a coach that only asks questions

If you have access to Claude, you may paste your roadmap and ask it to interview you with five questions about it, and to not write any part of it for you. As in lesson 47, Claude is a critic and not an author. The plan has to be yours.

Honest limits

Self-ratings are opinions. The best check is to explain a unit to a classmate and see where you stumble. Treat the numbers as a starting point for a conversation with yourself and with your teacher.

Read more

What you'll need

  • Your notes and projects from the course
  • Your cv_course environment, for the roadmap and portfolio tools

Build it

Put roadmap.py and portfolio.py in one folder. Everything runs with no camera, no network and no key.

Cell 1: the roadmap tool

"""A personal learning roadmap built from honest self-ratings. Code picks strengths, gaps and what you are ready for."""
import datetime
 
UNITS = {1: "Foundations, how computers see", 2: "Classic CV, seeing without AI", 3: "Data, annotation and consent",
         4: "Machine learning for vision", 5: "Object detection and tracking", 6: "Field trip 1, data harvest",
         7: "Automation, CV that acts", 8: "AI integration with Claude", 9: "Field trip 2, live event",
         10: "Fairness and specialised techniques", 11: "Capstone"}
 
# Each next step names the units it builds on, and a two-week mini project. Check current versions before you start:
# these tools change quickly.
NEXT_STEPS = [
    {"id": "transformers", "name": "Transformer-based detectors and vision transformers", "needs": [4, 5],
     "try": "Run a transformer-based detector on your sprint test set and compare it with your YOLO model on accuracy and speed."},
    {"id": "segmentation", "name": "Segmentation with the Segment Anything family", "needs": [2, 5],
     "try": "Use a promptable segmentation model to outline the ball and players, and compare the outlines with your boxes."},
    {"id": "edge", "name": "Edge AI on small boards such as the ESP32-lesson 3", "needs": [4, 7],
     "try": "Run a tiny person or ball detector on a camera board and measure frames per second and battery life."},
    {"id": "tracking", "name": "Tracking and sports analytics", "needs": [5, 7],
     "try": "Extend your lesson 45 and lesson 46 work to a second match and compare players across the two."},
    {"id": "multimodal", "name": "Claude and other multimodal models in products", "needs": [7, 8],
     "try": "Build a tool where code detects and Claude explains, with checks on every number it says."},
    {"id": "responsible", "name": "Fairness, privacy and model cards", "needs": [3, 10],
     "try": "Audit a public dataset for who is missing, and write a model card for it."},
]
 
 
def validate_ratings(ratings):
    if set(ratings) != set(UNITS):
        raise ValueError("rate every unit from 1 to 11")
    if any(not isinstance(v, int) or isinstance(v, bool) or not 1 <= v <= 5 for v in ratings.values()):
        raise ValueError("ratings are whole numbers from 1 (not yet) to 5 (I could teach it)")
 
 
def strengths_gaps(ratings, k=2):
    validate_ratings(ratings)
    order = sorted(UNITS, key=lambda u: (-ratings[u], u))
    return order[:k], sorted(UNITS, key=lambda u: (ratings[u], u))[:k]
 
 
def suggest(ratings, interests=(), limit=3, ready_at=3):
    """Ready = every unit the step builds on is rated at least ready_at. Interests come first, then readiness."""
    validate_ratings(ratings)
    out = []
    for s in NEXT_STEPS:
        weak = [u for u in s["needs"] if ratings[u] < ready_at]
        out.append({**s, "ready": not weak, "strengthen_first": weak, "interested": s["id"] in interests})
    out.sort(key=lambda s: (not s["ready"], not s["interested"], len(s["strengthen_first"])))
    return out[:limit]
 
 
def lint_goal(goal, today=None):
    """A goal is something you can check: what, a number, a date within a year, and the evidence you will show."""
    today = today or datetime.date.today()
    problems = []
    for key in ("what", "measure", "evidence"):
        if not isinstance(goal.get(key), str) or len(goal.get(key, "").strip()) < 5:
            problems.append(f"'{key}' is missing or too short")
    n = goal.get("number")
    if not isinstance(n, (int, float)) or isinstance(n, bool) or n <= 0:
        problems.append("'number' must be a number above zero")
    try:
        by = datetime.date.fromisoformat(goal.get("by", ""))
        if by <= today:
            problems.append("'by' is not in the future")
        elif (by - today).days > 366:
            problems.append("'by' is more than a year away: pick a nearer checkpoint")
    except (ValueError, TypeError):
        problems.append("'by' must be a date like 2027-03-31")
    vague = {"better", "good", "improve", "learn more", "understand"}
    text = (goal.get("what", "") + " " + goal.get("measure", "")).lower()
    problems += [f"vague word '{w}': say what you will do or measure" for w in sorted(vague) if w in text]
    return problems
 
 
def plan_markdown(name, ratings, interests, goal, today=None):
    strong, gaps = strengths_gaps(ratings)
    steps = suggest(ratings, interests)
    lines = [f"# Learning roadmap: {name}", "", "## Where I am", ""]
    lines += [f"- Strongest: Unit {u}, {UNITS[u]} ({ratings[u]} of 5)" for u in strong]
    lines += [f"- Weakest: Unit {u}, {UNITS[u]} ({ratings[u]} of 5)" for u in gaps]
    lines += ["", "## Next steps", ""]
    for s in steps:
        tail = "ready now" if s["ready"] else "first strengthen " + ", ".join(f"Unit {u}" for u in s["strengthen_first"])
        lines.append(f"- {s['name']} ({tail}). Two-week try: {s['try']}")
    lines += ["", "## My goal", "", f"{goal['what']}. Measured by {goal['measure']}: {goal['number']}, by {goal['by']}. Evidence: {goal['evidence']}.", ""]
    problems = lint_goal(goal, today)
    if problems:
        lines += ["Goal still needs work:"] + [f"- {p}" for p in problems]
    return "\n".join(lines)

Cell 2: rate yourself honestly

Rate each unit from 1 (not yet) to 5 (I could teach it). Do not rate what you wish you knew. Rate what you could do tomorrow without notes.

from roadmap import UNITS, strengths_gaps, suggest, lint_goal, plan_markdown
 
ratings = {1: 5, 2: 4, 3: 4, 4: 3, 5: 4, 6: 3, 7: 4, 8: 2, 9: 3, 10: 2, 11: 3}    # replace with yours
 
strong, gaps = strengths_gaps(ratings)
print("Strongest:", [UNITS[u] for u in strong])
print("Weakest:  ", [UNITS[u] for u in gaps])

Cell 3: what are you ready for?

for s in suggest(ratings, interests=["edge", "tracking"], limit=4):
    status = "ready now" if s["ready"] else "first strengthen Unit " + ", ".join(map(str, s["strengthen_first"]))
    print("-", s["name"], "|", status)
    print("    try:", s["try"])

A step is "ready" when every unit it builds on is rated 3 or more. Interests only decide the order among steps you are ready for. You can also decide that a step is worth the extra work. The code only shows you where the gaps are.

Cell 4: one goal you can check

goal = {"what": "Run a transformer-based detector on my sprint test set",
         "measure": "mAP50 difference against my YOLO model",
         "number": 1,
         "by": "2027-02-28",
         "evidence": "a notebook and a one page comparison"}
print(lint_goal(goal) or "goal is checkable")
 
print(lint_goal({"what": "Get better at AI", "measure": "understand more", "by": "someday"}))

The second goal shows what vague looks like. Rewrite yours until the first kind of answer comes back.

Cell 5: write the roadmap

text = plan_markdown("Your name", ratings, ["edge", "tracking"], goal)
open("roadmap.md", "w").write(text)
print(text)

Cell 6: the portfolio checker

"""Is the capstone portfolio complete, and safe to share? Reads a folder. Code checks files; people judge quality."""
import glob
import os
import re
 
REQUIRED = {"brief (lesson 47)": ["brief*"], "model card (lesson 43)": ["model_card*", "modelcard*"],
            "acceptance report (lesson 50)": ["acceptance*"], "demo video or link (lesson 51)": ["demo*"],
            "README with how to run it": ["README*", "readme*"], "consent statement (lesson 14)": ["consent*"],
            "what I learned (a short note)": ["learned*", "reflection*"]}
 
RAW_FOLDERS = {"dataset", "raw", "frames", "footage", "captures", "images"}
MEDIA = (".jpg", ".jpeg", ".png", ".mp4", ".mov", ".mkv", ".avi")
SECRET = re.compile(r"(sk-ant-[A-Za-z0-9_\-]{10,}|ANTHROPIC_API_KEY\s*=\s*['\"]?[A-Za-z0-9_\-]{10,}|ROBOFLOW_API_KEY\s*=\s*['\"]?[A-Za-z0-9]{10,})")
TEXT = (".py", ".md", ".txt", ".json", ".env", ".ipynb", ".yaml", ".yml", ".cfg", ".csv")
 
 
def check(folder):
    missing, warnings = [], []
    for name, patterns in REQUIRED.items():
        found = [p for pat in patterns for p in glob.glob(os.path.join(folder, "**", pat), recursive=True)
                 if os.path.isfile(p) and os.path.getsize(p) > 0]
        if not found:
            missing.append(name)
    for root, dirs, files in os.walk(folder):
        parts = {p.lower() for p in os.path.relpath(root, folder).split(os.sep)}
        raw_media = [f for f in files if f.lower().endswith(MEDIA)]
        if raw_media and parts & RAW_FOLDERS:
            warnings.append(f"{os.path.relpath(root, folder)}: {len(raw_media)} picture or video files from a raw data folder. "
                            "Do not publish pictures of people unless consent covers sharing them")
        for f in files:
            p = os.path.join(root, f)
            if f.lower() == ".env" or f.lower().endswith(TEXT):
                try:
                    if SECRET.search(open(p, encoding="utf8", errors="ignore").read()):
                        warnings.append(f"{os.path.relpath(p, folder)}: looks like an API key. Remove it and make a new key")
                except OSError:
                    pass
    return {"complete": not missing, "safe": not warnings, "missing": missing, "warnings": warnings}

Run it on your capstone folder:

from portfolio import check
 
result = check("my_capstone")            # the folder you will share
print("Complete:", result["complete"], "| Safe to share:", result["safe"])
for m in result["missing"]:
    print("MISSING:", m)
for w in result["warnings"]:
    print("WARNING:", w)

It looks for seven items (brief, model card, acceptance report, demo, README, consent statement, a short note on what you learned). It also warns about two things that hurt people: pictures or videos from a raw data folder, and anything that looks like an API key. Fix every warning before sharing.

Cell 7: the tests

import datetime, os, shutil
from roadmap import *
from portfolio import check
 
n = 0
def ok(name, cond):
    global n
    print(("PASS " if cond else "FAIL ") + name); n += bool(cond)
    if not cond: raise SystemExit(1)
def bad(f):
    try: f(); return False
    except ValueError: return True
 
R = {1: 5, 2: 4, 3: 4, 4: 3, 5: 4, 6: 3, 7: 4, 8: 2, 9: 3, 10: 2, 11: 3}
strong, gaps = strengths_gaps(R)
ok("strengths: highest, ties by unit order", strong == [1, 2])
ok("gaps: lowest, ties by unit order", gaps == [8, 10])
ok("ratings must cover all 11 units", bad(lambda: strengths_gaps({1: 3})))
ok("ratings must be 1 to 5", bad(lambda: strengths_gaps({**R, 4: 6})) and bad(lambda: strengths_gaps({**R, 4: True})))
 
s = suggest(R, interests=["edge"], limit=6)
ok("ready steps come first", [x["ready"] for x in s] == sorted((x["ready"] for x in s), reverse=True))
ok("interest breaks ties among ready steps", s[0]["id"] == "edge" and s[0]["ready"])
ok("a step needing a weak unit says which", next(x for x in s if x["id"] == "responsible")["strengthen_first"] == [10])
ok("multimodal waits on Unit 8", next(x for x in s if x["id"] == "multimodal")["strengthen_first"] == [8] and not next(x for x in s if x["id"] == "multimodal")["ready"])
ok("limit respected", len(suggest(R, limit=2)) == 2)
low = {u: 1 for u in UNITS}
ok("a beginner is ready for nothing yet, and told what to strengthen", all(not x["ready"] and x["strengthen_first"] for x in suggest(low, limit=6)))
ok("an expert is ready for everything", all(x["ready"] for x in suggest({u: 5 for u in UNITS}, limit=6)))
 
today = datetime.date(2026, 12, 15)
good = {"what": "Run a transformer detector on my sprint test set", "measure": "mAP50 difference against my YOLO model", "number": 1, "by": "2027-02-28", "evidence": "a notebook and a one page comparison"}
ok("good goal has no problems", lint_goal(good, today) == [])
ok("vague goal flagged", any("vague word 'improve'" in p for p in lint_goal({**good, "what": "Improve at detection"}, today)))
ok("past date flagged", any("not in the future" in p for p in lint_goal({**good, "by": "2026-01-01"}, today)))
ok("far date flagged", any("more than a year" in p for p in lint_goal({**good, "by": "2029-01-01"}, today)))
ok("bad date flagged", any("must be a date" in p for p in lint_goal({**good, "by": "next spring"}, today)))
ok("no number flagged", any("'number'" in p for p in lint_goal({**good, "number": 0}, today)) and any("'number'" in p for p in lint_goal({**good, "number": "two"}, today)))
ok("missing evidence flagged", any("'evidence'" in p for p in lint_goal({**good, "evidence": ""}, today)))
ok("empty goal collects several problems", len(lint_goal({}, today)) >= 4)
 
md = plan_markdown("Asha", R, ["edge"], good, today)
ok("plan shows strengths, gaps, steps and goal", "Strongest: Unit 1" in md and "Weakest: Unit 8" in md and "ready now" in md and "first strengthen" not in md and "by 2027-02-28" in md)
ok("steps that are not ready say what to strengthen first", "first strengthen Unit" in plan_markdown("B", {u: 2 for u in UNITS}, [], good, today))
ok("a flawed goal is called out in the plan", "Goal still needs work" in plan_markdown("A", R, [], {**good, "by": "soon"}, today))
 
shutil.rmtree("p", ignore_errors=True); os.makedirs("p/dataset/train")
ok("empty folder: all 7 missing", len(check("p")["missing"]) == 7 and not check("p")["complete"])
for f in ["brief.md", "model_card.md", "acceptance_report.md", "demo_link.txt", "README.md", "consent_statement.md", "learned.md"]:
    open(f"p/{f}", "w").write("text")
r = check("p"); ok("all seven present: complete and safe", r["complete"] and r["safe"] and r["missing"] == [])
open("p/learned.md", "w").write(""); ok("empty file does not count", check("p")["missing"] == ["what I learned (a short note)"])
open("p/learned.md", "w").write("x")
open("p/dataset/train/a.jpg", "wb").write(b"x")
r = check("p"); ok("raw pictures in a dataset folder are warned", not r["safe"] and "raw data folder" in r["warnings"][0])
os.remove("p/dataset/train/a.jpg")
open("p/notebook.py", "w").write('client = anthropic.Anthropic(api_key="sk-ant-api03-abcdefghijklmnop")')
r = check("p"); ok("a pasted API key is found", any("looks like an API key" in w for w in r["warnings"]))
open("p/notebook.py", "w").write('import os\nclient = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from the environment')
ok("reading the key from the environment is fine", check("p")["safe"])
open("p/.env", "w").write("ANTHROPIC_API_KEY=abcdefghijklmnopqrst")
ok("a .env file with a key is found", not check("p")["safe"])
shutil.rmtree("p")
print(f"\n{n} checks passed")

Expected: 29 checks passed.

If it goes wrong

ErrorCauseFix
All ratings are 5 or all are 1No honest reflectionAsk for one example per unit that shows the rating
The goal is flagged as vagueWords like better or understandSay what you will do, how you will measure it, and what you will show
The checker reports a missing file but you have itIt has a different nameRename it to match the list, or add a short file that points to it
A warning about raw picturesA dataset folder is in the portfolioRemove it or keep it private; show a few permitted examples
A warning about an API keyA key was pasted into code or a notebookRemove it, delete the key at the provider, and make a new one
The roadmap is only a list of toolsChasing namesStart from the problem you want to solve, then pick the tool
You feel behindYou're comparing yourself with othersCompare with where you started, which the units table shows

Try it

  • Pick a second goal that builds on the first and add a checkpoint for the half-way point
  • Pick the one unit you want to strengthen and the one practice task from it

Check what you learnt

  1. What three stages does every CV system go through?

  2. What decides what a model can handle?

  3. Why test on a set the model has never seen?

  4. Which matters more when filming people: the model or consent?

  5. What's the best next step after this course?

Conclusion

Computer vision is pixels turned into decisions: perceive, decide, act. Along the way you learned that data decides what a model can do, that honest measurement beats impressive numbers, and that the people in the pictures come first. The next climb is yours: pick a small, real project and build it.

What next?

Well done on finishing AI & Computer Vision! Share what you built, and keep going.