Portfolio  ›  Projects  ›  Micro-Behaviour Analysis
Computer Vision Python MediaPipe

Micro-Behaviour Analysis,
Landmark Extraction

Live video in, 543 landmark coordinates per frame out — pose, face mesh and both hands, tracked by MediaPipe Holistic. That is the whole system, and saying so plainly is the substance of this case study.

◆ Research Prototype · extraction stage only
Context: Personal research project  ·  Role: Author, then recovery engineer
Starting point: One file, 1,127 bytes, broken against every current MediaPipe release
This pass: 5 defects fixed · verified on a 30-frame clip · scope corrected on the public claim
543Landmarks per frame
30/30Frames processed
5Defects fixed
0Behaviour classifiers
⚠️ What Was Never Built 🔧 See the Repairs
What It Measures

Coordinates, and only coordinates

Each frame goes through MediaPipe Holistic, which runs four models and returns landmark sets. The program draws them and moves to the next frame.

GroupLandmarksWhat each one is
Pose33Body joint positions, with visibility scores
Face mesh468Dense facial surface points
Left hand21Finger and palm joints
Right hand21Finger and palm joints
Total543Per frame, when all groups are visible
01 CAPTUREWebcam or video file via OpenCV
02 CONVERTBGR → RGB
03 HOLISTICPose + face + hands inference
04 DRAWLandmark overlay per group
05 TEMPORALNever built
06 CLASSIFYNever built
The Missing Half

The folder name promises something the code never contained

❌ It does not predict future actions

The directory is called Micro-Behavior-Analysis-for-Predicting-Future-Actions. The code does not predict future actions, and never did. There is no temporal model, no cross-frame feature aggregation, no behaviour classifier, no labels, no training code and no evaluation. The project has always been a single file containing the extraction stage.

That gap was left open deliberately during the repair. The missing components are exactly the interesting ones — a temporal model over landmark sequences is a real piece of research work — and writing one now would produce something that had never existed, presented under a project name implying it always had.

The judgement call

Option A

Build an LSTM over the landmark stream, label a small dataset, and publish the project as a working behaviour classifier. Faster to make impressive. Dishonest about provenance.

Option B

Repair the extraction stage so it runs on current MediaPipe, then state precisely which stages exist and which do not.

Chosen

B. The pipeline diagram above marks stages 05 and 06 as never built, in red, on the public page. If the classifier gets written later it will be dated to when it was written.

The Repair

It could not run on any current MediaPipe

The script was written against a MediaPipe API that has since been removed twice over. On a fresh install it failed before finishing the first frame.

#DefectEffect
1mp_holistic.FACE_CONNECTIONSRemoved in MediaPipe 0.8.9. AttributeError on frame 1 — the program never reached frame 2. Replaced with FACEMESH_CONTOURS.
2No MediaPipe upper boundRelease 1.0.0 deleted mp.solutions entirely, so the import fails. Now pinned <1.0.
3VideoStream(src=0).start() then immediate .read()Returns None until the first frame arrives; that None went straight into cv2.cvtColor, which raises. Replaced with cv2.VideoCapture plus an explicit frame check.
4draw_landmarks called unconditionallyMediaPipe returns None for groups it cannot see — a frame with no hands in it crashed the program. Now guarded per group.
5No camera → unhandled crashNow reports the cause and accepts --source <file> so it runs headless.

🛠️ Why the version pin is the important one

Defect 1 is a one-line fix. Defect 2 is the one that keeps the project alive: MediaPipe 1.0 removed the entire solutions namespace this code is built on. Without an upper bound, a routine pip install -r requirements.txt a year from now would fail at import with no obvious cause. The pin is documented in the requirements file with the reason attached.

Verification

Measured on a real clip

CheckResult
MediaPipe 0.10.21 imports, Holistic initialisesPass
Video source opens headless (--no-window)Pass
Frames processed without exception30 / 30
Pose landmarks recovered33 in 30/30 frames
Face landmarks recovered468 in 30/30 frames
Absent hand groups handled without crashPass

Environment: Python 3.12, OpenCV 4.11, CPU. No throughput figure is quoted. On a clip this short the elapsed time is dominated by model initialisation, so any frames-per-second number derived from it would misrepresent steady-state performance.

💻 Run it

python -m venv .venv && .venv\Scripts\activate
pip install -r requirements.txt

python main.py                                       # webcam
python main.py --source clip.mp4                     # video file
python main.py --source clip.mp4 --no-window --max-frames 100
Ethics

What this system is not evidence of

❌ No inference about people

This code measures body, face and hand landmark geometry. It infers nothing about mental state, emotion, personality, deception, criminal intent, or any medical or psychological condition. Any claim of that kind would be unsupported by this code, and the wider research literature does not support it either — landmark geometry is not a channel into someone's mind.

Behavioural computer vision attracts overclaiming, and the label "micro-behaviour" attracts it more than most. The scope statement above is reproduced verbatim in the project's own README so the constraint travels with the source rather than living only on this page.

Vision
MediaPipe HolisticPoseFace MeshHand tracking
Runtime
Python 3.12OpenCV 4.11NumPy
Practice
Pinned API surfaceHeadless modeScoped claims

Half a system, described as half a system

The extraction stage works and is verified. The temporal and classification stages do not exist. Both facts are on this page because a portfolio that only shows finished work is not a record of how research actually goes.