Open-source Python toolkit

Computer vision that keeps your code visible.

CVGO simplifies repetitive OpenCV and MediaPipe setup while keeping the familiar while True flow easy to read, edit, and customize.

CVGO — Simple Computer Vision for Python

Simple code, without hiding the process.

Start with useful defaults. Keep control of frames, detections, conditions, output, and cleanup when your project grows.

Readable camera loops

Read a frame, inspect a result, make a decision, and display it yourself.

Computer vision building blocks

Face, hand, pose, holistic, gesture, object detection, and segmentation.

Ready for real projects

FPS, timers, alarms, Arduino serial, Telegram photos, and editable thresholds.

Install CVGO.

Use Python 3.10, 3.11, or 3.12 in a dedicated virtual environment.

Quick install
python -m pip install cvgo
Windows PowerShell
py -3.11 -m venv .venv-cvgo
.venv-cvgo\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install cvgo
Linux / Armbian
python3.11 -m venv .venv-cvgo
source .venv-cvgo/bin/activate
python -m pip install --upgrade pip
python -m pip install cvgo
Check installation and camera 4
python -m cvgo check
python -m cvgo check --camera 4

Install only opencv-contrib-python for CVGO. Avoid another OpenCV package variant in the same environment. CVGO is a universal Python wheel; on AArch64, pip must still find compatible OpenCV and MediaPipe wheels for the target operating system.

Defaults that stay customizable.

Constructors work with no arguments for beginners. Optional parameters remain available when a camera or project needs different behavior.

Main defaults

Camera()
Camera 0, OpenCV CAP_ANY
FaceDetector()
Fast engine, maximum one face
FaceLandmarks()
Maximum one face
HandTracker()
Maximum two hands
PoseTracker()
One main pose, complexity 1
GestureRecognizer()
Video mode, two hands
ObjectDetector()
Video mode, 10 objects
Serial()
Automatic port, 9600 baud
Telegram()
Environment config, 30 s cooldown
Timer()
One-second duration
Smoother()
Alpha 0.45

Python naming style

  • Classes use PascalCase: PoseTracker.
  • Methods use snake_case: put_text().
  • Constants use UPPER_CASE: BIT_DROWSY.
  • Use fps.read() for the short, readable FPS API.

MediaPipe task modes

ObjectDetector and GestureRecognizer support three modes. Video remains the compatible default; live keeps camera loops responsive.

mode="image"
Independent still images
mode="video"
Synchronous sequential frames
mode="live"
Latest asynchronous camera result
result_ready
First result has completed

Consistent bounding boxes

Face, hand, pose, and object boxes share one predictable API. Pose boxes ignore low-visibility landmarks by default.

box.xyxy
Left, top, right, bottom
box.center
Center pixel coordinates
box.area
Box area in pixels
box.draw()
Rectangle and optional label

Advanced parameters, without losing simplicity.

Keep the basic examples unchanged. Add only the named parameters needed by a camera, model, output, or calibrated project.

Start small, then customize.

Every omitted parameter keeps its documented default. Parameters after an asterisk are keyword-only, so their names stay visible.

Adding only the parameters you need
camera = go.Camera()
camera = go.Camera(4)
camera = go.Camera(4, width=1280, height=720, fps=30)
  • Confidence values use 0.0 to 1.0.
  • OpenCV colors use BGR, not RGB.
  • None keeps the system or library default.
  • static=True is for unrelated still images.
  • mode="live" keeps task-based camera loops responsive.
Camera and drawing Choose a source, request capture settings, and customize the GUI.

go.Camera(source=0, *, width=None, height=None, fps=None, backend=None)

ParameterDefaultWhat it changes
source0Camera index, video path, or stream URL.
widthNoneRequested capture width in pixels.
heightNoneRequested capture height in pixels.
fpsNoneRequested camera frame rate.
backendNoneOpenCV backend; None uses CAP_ANY.

Width, height, and FPS are requests; a camera driver may choose the nearest supported value. Read camera.size after opening, or use camera.capture for raw OpenCV settings.

Display and text

API / parameterDefaultWhat it changes
show.title"CVGO"Window title.
show.delay1Keyboard polling delay in milliseconds.
show.quit_key"q"One character that closes the loop.
close.windowsTrueDestroy OpenCV GUI windows; use False for a headless check.
put_text.position(20, 35)Text origin in pixels.
put_text.color(0, 255, 0)Text color in BGR.
put_text.scale0.7OpenCV font scale.
put_text.thickness2Text stroke width.
put_text.backgroundFalseAdd a black text background.
box.draw.color(0, 255, 0)Shared bounding-box color.
box.draw.thickness2Shared bounding-box thickness.
box.draw.labelNoneOptional shared bounding-box label.

Diagnostics

go.system_info()

go.check_camera(source=0, *, backend=None)

Use these from a custom support tool, or run python -m cvgo check --camera 4. The camera check reads one frame, reports its dimensions, and closes without opening a GUI window.

Custom camera and GUI
camera = go.Camera(1, width=1280, height=720, fps=30)

go.put_text(
    frame,
    "Security active",
    color=(0, 255, 255),
    background=True,
)
camera.show(frame, title="Security Camera", quit_key="x")
Face detection and landmarks Control face count, confidence, iris refinement, boxes, and drawing.

go.FaceDetector(*, max_faces=1, padding=10, model=0, detection_confidence=0.5, engine="auto", refine=False, tracking_confidence=0.5)

go.FaceLandmarks(*, max_faces=1, refine=False, detection_confidence=0.5, tracking_confidence=0.5)

ParameterDefaultWhat it changes
max_faces1Maximum faces returned per frame.
padding10Extra pixels around a detector box.
model0Fast model: 0 near-range or 1 full-range.
engine"auto"Select auto, fast, or Face Mesh-compatible mesh.
refineFalseMesh only: refine eyes and lips and add iris landmarks.
detection_confidence0.5Minimum initial face detection confidence.
tracking_confidence0.5Mesh only: minimum landmark tracking confidence.

The default auto engine uses lightweight MediaPipe Face Detection. It keeps the compatible mesh engine when refine=True or a custom tracking_confidence is supplied. Every fast FaceBox also exposes confidence. raw_result remains available in both modes; detector.faces contains landmarks only in mesh mode.

Face result methods

API / parameterDefaultWhat it changes
face.box.padding10Extra pixels around landmark bounds.
face.draw.style"contours"contours, tesselation, iris, or all.
face.draw.color(0, 255, 0)Landmark and connection color.
face.draw.thickness1Connection thickness.
face.draw.radius1Landmark radius.
FaceBox.draw.color(0, 255, 0)Box and label color.
FaceBox.draw.thickness2Box and label thickness.
FaceBox.draw.label"Face"Box label; None hides it.
Custom face landmarks
detector = go.FaceDetector(
    max_faces=2,
    detection_confidence=0.7,
    model=0,
)

landmarker = go.FaceLandmarks(
    max_faces=2,
    refine=True,
    detection_confidence=0.7,
)

faces = landmarker.detect(frame)

for face in faces:
    face.draw(frame, style="tesselation", color=(255, 180, 0))
    face.box(padding=20).draw(frame, label="Tracked face")
Hand tracking Balance speed, accuracy, hand count, handedness, and drawing.

go.HandTracker(*, max_hands=2, model_complexity=1, detection_confidence=0.5, tracking_confidence=0.5, static=False, mirrored=False)

ParameterDefaultWhat it changes
max_hands2Maximum hands returned per frame.
model_complexity10 is lighter; 1 is more accurate.
detection_confidence0.5Minimum hand detection confidence.
tracking_confidence0.5Minimum landmark tracking confidence.
staticFalseUse True for independent still images.
mirroredFalseUse True if the input was already flipped horizontally.

Hand result methods

API / parameterDefaultWhat it changes
hand.box.padding10Extra pixels around the hand.
hand.draw.color(0, 255, 0)Connection color.
hand.draw.point_color(255, 0, 255)Landmark color.
hand.draw.thickness2Connection thickness.
hand.draw.radius2Landmark radius.
HandBox.draw.label"Hand"Box label; None hides it.
Lightweight single-hand tracking
tracker = go.HandTracker(
    max_hands=1,
    model_complexity=0,
    detection_confidence=0.7,
)

hands = tracker.detect(frame)

for hand in hands:
    hand.draw(frame, color=(255, 200, 0), point_color=(0, 0, 255))
Pose tracking Select Lite, Full, or Heavy and tune visibility-based boxes.

go.PoseTracker(*, model_complexity=1, detection_confidence=0.5, tracking_confidence=0.5, smooth=True, segmentation=False, static=False)

ParameterDefaultWhat it changes
model_complexity10 Lite, 1 Full, or 2 Heavy.
detection_confidence0.5Minimum pose detection confidence.
tracking_confidence0.5Minimum landmark tracking confidence.
smoothTrueSmooth landmarks and an optional segmentation mask.
segmentationFalseAlso produce pose.mask.
staticFalseUse True for independent still images.

Pose result methods

API / parameterDefaultWhat it changes
pose.visible.confidence0.5Required landmark visibility.
pose.box.padding20Extra pixels around the visible body.
pose.box.min_visibility0.5Ignore weaker landmarks when building the box.
pose.draw.color(0, 255, 0)Skeleton connection color.
pose.draw.point_color(255, 0, 255)Landmark color.
pose.draw.thickness2Connection thickness.
pose.draw.radius2Landmark radius.
PoseBox.draw.label"Person"Box label; None hides it.

Use model_complexity=0 for an STB or low-power board.

Lightweight pose box
tracker = go.PoseTracker(
    model_complexity=0,
    detection_confidence=0.6,
    segmentation=True,
)

pose = tracker.detect(frame)

if pose:
    pose.box(padding=30, min_visibility=0.6).draw(
        frame,
        label="Person",
    )
Holistic tracking Configure the combined face, pose, hands, and segmentation pipeline.

go.HolisticTracker(*, model_complexity=1, detection_confidence=0.5, tracking_confidence=0.5, smooth=True, refine_face=False, segmentation=False, static=False)

ParameterDefaultWhat it changes
model_complexity1Pose model complexity: 0, 1, or 2.
detection_confidence0.5Minimum initial detection confidence.
tracking_confidence0.5Minimum landmark tracking confidence.
smoothTrueSmooth landmarks and an optional mask.
refine_faceFalseRefine landmarks around the eyes and lips.
segmentationFalseAlso produce result.mask.
staticFalseUse True for independent still images.

result.draw(frame, face=True, pose=True, hands=True) can show or hide each landmark group independently. All three Boolean parameters default to True.

Choose holistic result parts
tracker = go.HolisticTracker(
    model_complexity=0,
    refine_face=True,
)
result = tracker.detect(frame)

if result:
    result.draw(frame, face=False, pose=True, hands=True)
Object detection Filter labels, tune confidence, select a task mode, or load a model.

go.ObjectDetector(model_path=None, *, confidence=0.5, max_objects=10, allow=None, deny=None, locale="en", mode="video", stream=None, download=True)

ParameterDefaultWhat it changes
model_pathNoneCompatible custom .tflite model path.
confidence0.5Minimum object score.
max_objects10Maximum results per frame.
allowNoneReturn only these labels, such as ["person"].
denyNoneExclude these labels.
locale"en"Preferred display-name locale in model metadata.
mode"video"image, video, or asynchronous live.
streamNoneLegacy option; new code should use mode.
downloadTrueDownload the default model when not cached.

allow and deny cannot be combined. In live mode, detect() returns the latest completed result; result_ready identifies the first completion.

Detected object drawing

ParameterDefaultWhat it changes
color(0, 255, 0)Box and label color.
thickness2Box and label thickness.
show_scoreTrueInclude confidence in the label.
Filtered live object detection
detector = go.ObjectDetector(
    confidence=0.65,
    max_objects=3,
    allow=["person", "car"],
    mode="live",
)

objects = detector.detect(frame)

for item in objects:
    item.draw(frame, color=(0, 200, 255), show_score=False)
Gesture recognition and task models Tune gesture stages, use asynchronous results, and prepare offline models.

go.GestureRecognizer(model_path=None, *, max_hands=2, gesture_confidence=0.5, detection_confidence=0.5, presence_confidence=0.5, tracking_confidence=0.5, mirrored=False, mode="video", stream=None, download=True)

ParameterDefaultWhat it changes
model_pathNoneCompatible custom .task model path.
max_hands2Maximum hands recognized per frame.
gesture_confidence0.5Minimum score for a recognized gesture.
detection_confidence0.5Minimum hand detection confidence.
presence_confidence0.5Minimum hand presence confidence.
tracking_confidence0.5Minimum landmark tracking confidence.
mirroredFalseUse True if input was already flipped.
mode"video"image, video, or asynchronous live.
streamNoneLegacy option; new code should use mode.
downloadTrueDownload the default model when not cached.

Gesture result methods

API / parameterDefaultWhat it changes
gesture.box.padding10Extra pixels around the gesture hand.
gesture.draw.color(0, 255, 0)Connections and box color.
gesture.draw.point_color(255, 0, 255)Hand landmark color.
Custom gesture and offline model setup
model = go.download_model(
    "gesture_recognizer",
    directory="models",
    timeout=180,
)
recognizer = go.GestureRecognizer(
    model,
    max_hands=1,
    gesture_confidence=0.7,
    mode="live",
)

Model download parameters

ParameterDefaultWhat it changes
nameRequiredobject_detection or gesture_recognizer.
directoryNoneCustom download folder.
forceFalseDownload again when a valid model exists.
timeout120.0Download timeout in seconds.

Set CVGO_MODEL_DIR to change the shared model cache. CVGO verifies each pinned model's header and SHA-256 checksum and downloads a damaged or incomplete cache file again.

Segmentation and timing Choose a segmentation model and tune masks, timers, smoothing, and FPS.
API / parameterDefaultWhat it changes
SelfieSegmenter.model10 general; 1 landscape/webcam.
foreground.threshold0.5Minimum mask value treated as foreground.
apply.background(0, 0, 0)BGR color or image matching the frame size.
apply.threshold0.5Foreground cutoff.
blur.amount35Blur kernel; an even value is raised to the next odd value.
blur.threshold0.5Foreground cutoff.
Timer.seconds1.0Time a condition must remain true.
Smoother.alpha0.45Lower is smoother; higher reacts faster.
FPS.update_every1.0Seconds between displayed FPS updates.
Custom segmentation and timing
segmenter = go.SelfieSegmenter(model=0)
timer = go.Timer(1.5)
smoother = go.Smoother(alpha=0.3)
fps = go.FPS(update_every=0.5)

result = segmenter.segment(frame)
frame = result.blur(frame, amount=51, threshold=0.6)
Serial, Telegram, and alarm output Configure device connections, notification cooldowns, and sound.

go.Serial(port=None, *, baud=9600, timeout=1.0, reconnect_after=5.0, settle_time=2.0, newline=False, connect=True)

Serial parameterDefaultWhat it changes
portNoneAuto-detect, or use a path such as COM5 or /dev/ttyUSB0.
baud9600Baud rate; it must match the board.
timeout1.0Read timeout in seconds.
reconnect_after5.0Minimum delay between reconnect attempts.
settle_time2.0Wait after a board resets on connect; use 0 when unnecessary.
newlineFalseAppend a newline to outgoing values.
connectTrueConnect during construction.

send() waits for its result. send_async() uses one ordered worker so a serial reconnect or write does not hold the camera loop. Both return a boolean result; the asynchronous form wraps it in a Future.

go.Telegram(token=None, chat_id=None, *, cooldown=30.0, timeout=15.0, silent=False, protect=False)

Telegram parameterDefaultWhat it changes
tokenEnvironmentBot token or CVGO_TELEGRAM_TOKEN.
chat_idEnvironmentTarget ID or CVGO_TELEGRAM_CHAT_ID.
cooldown30.0Seconds between successful sends using the same key.
timeout15.0HTTP request timeout in seconds.
silentFalseSend without notification sound.
protectFalseAsk Telegram to protect message content.

send_message() parameters

ParameterDefaultWhat it changes
textRequiredMessage text, from 1 to 4096 characters.
key"message"Independent cooldown name.
forceFalseBypass cooldown intentionally.
silentNoneUse or override the constructor setting.
protectNoneUse or override the constructor setting.
parse_modeNoneFormatting mode such as HTML.

send_photo() parameters

ParameterDefaultWhat it changes
photoRequiredOpenCV frame, image bytes, or image path.
caption""Caption up to 1024 characters.
key"photo"Independent cooldown name.
forceFalseBypass cooldown intentionally.
filenameNoneOptional uploaded filename.
quality85JPEG quality from 1 to 100 for OpenCV frames.
silentNoneUse or override the constructor setting.
protectNoneUse or override the constructor setting.
parse_modeNoneCaption formatting mode.

send_message_async() and send_photo_async() accept the same parameters and use one background queue. Camera frames are copied before queueing. Call telegram.close() after the loop; its wait=True default finishes queued sends.

go.Alarm(*, frequency=1500, duration=180, repeat=3, cooldown=0.8)

Alarm parameterDefaultWhat it changes
frequency1500Beep frequency in Hz on Windows.
duration180Length of each beep in milliseconds.
repeat3Number of beeps per trigger.
cooldown0.8Minimum seconds between alarm starts.
Custom output settings
arduino = go.Serial(
    "/dev/ttyUSB0",
    baud=115200,
    newline=True,
)
telegram = go.Telegram(cooldown=60, silent=True)
alarm = go.Alarm(frequency=1800, repeat=2, cooldown=1.0)

arduino.send_async("1")
telegram.send_message_async("CVGO active")
Advanced Driver Monitor Calibrate eye, head, missing-face, serial, and event behavior.

Driver Monitor groups related thresholds into small configuration objects, so each part can be calibrated without a crowded constructor.

EyeConfig parameterDefaultWhat it changes
closed_threshold0.20Enter closed-eye state below this EAR.
open_threshold0.24Leave closed-eye state above this EAR.
alert_after1.5Closed-eye seconds before drowsiness is active.
smoothing0.45EAR smoother alpha.
HeadConfig parameterDefaultWhat it changes
yaw_normal0.50Calibrated straight-ahead yaw ratio.
turn_threshold0.12Enter looking-away state beyond this offset.
turn_release0.07Leave looking-away state below this offset.
turn_alert_after0.7Looking-away seconds before an alert.
pitch_normal0.50Calibrated upright pitch ratio.
down_threshold0.055Enter head-down state beyond this offset.
down_release0.030Leave head-down state below this offset.
down_alert_after0.7Head-down seconds before an alert.
Other parameterDefaultWhat it changes
FaceConfig.missing_alert_after2.0Missing-face seconds before an alert.
DriverMonitor.camera0Camera source or configured Camera.
DriverMonitor.serialFalseTrue for auto serial or a Serial object.
DriverMonitor.soundFalseEnable its built-in alarm.
serial_repeat_after0.5Seconds between repeated mask transmissions.
Calibrated Driver Monitor
eyes = go.EyeConfig(
    closed_threshold=0.22,
    open_threshold=0.26,
    alert_after=1.2,
)
head = go.HeadConfig(turn_threshold=0.10, down_threshold=0.05)
face = go.FaceConfig(missing_alert_after=3.0)

monitor = go.DriverMonitor(
    camera=go.Camera(4, width=640, height=480),
    serial=go.Serial("/dev/ttyUSB0", baud=115200),
    sound=True,
    eyes=eyes,
    head=head,
    face=face,
)
monitor.serial_repeat_after = 1.0

Events: drowsy, looking_away, looking_left, looking_right, head_down, face_missing, and normal. The result keeps measurements, durations, landmarks, alert flags, FPS, mask, and mask_hex available for custom logic.

Driver Monitor display and shortcut mode

Method parameterDefaultWhat it changes
show.title"CVGO Driver Monitor"GUI window title.
show.draw_landmarksTrueDraw face landmarks before showing.
show.landmark_style"contours"Face drawing style.
show.quit_key"q"GUI quit key.
run.showFalseEnable a GUI window in shortcut mode.
run.draw_landmarksFalseDraw landmarks in shortcut mode.
run.print_statusTruePrint status twice per second.
run.quit_key"q"GUI quit key when show=True.

Raw access remains available

AccessRaw or editable valueUse
camera.capturecv2.VideoCaptureAdditional OpenCV camera properties.
tracker.raw_resultMediaPipe resultFeatures not wrapped by CVGO.
face.raw / hand.raw / pose.rawMediaPipe landmarksDirect MediaPipe interoperability.
item.raw / gesture.rawTask result or categoryModel-specific metadata.
face.points / hand.points / pose.pointsCVGO pointsReadable custom calculations.

34 complete, copy-ready examples.

Every topic includes a complete Standard / GUI program and a complete CLI / Terminal program, including imports, loops, and cleanup.

CLI examples are ordinary Python scripts that print live status. Stop them with Ctrl+C.

01 Camera and GUIOpen a camera with OpenCV CAP_ANY. Press q to quit the window or Ctrl+C in terminal mode.
examples/01_camera.py
"""Example 1: open and display the camera."""

import cvgo as go


camera = go.Camera()

while True:
    frame = camera.read()

    if frame is None:
        break

    if not camera.show(frame):
        break

camera.close()
02 Face DetectionDetect faces, draw the boxes, or print the live face count.
examples/02_face_detection.py
"""Example 2: detect faces."""

import cvgo as go


camera = go.Camera()
detector = go.FaceDetector()

while True:
    frame = camera.read()

    if frame is None:
        break

    faces = detector.detect(frame)

    for face in faces:
        face.draw(frame)

    if not camera.show(frame):
        break

camera.close()
detector.close()
03 Face LandmarksRead and draw detailed face landmarks for custom measurements.
examples/03_face_landmarks.py
"""Example 3: display face landmarks."""

import cvgo as go


camera = go.Camera()
landmarker = go.FaceLandmarks()

while True:
    frame = camera.read()

    if frame is None:
        break

    faces = landmarker.detect(frame)

    for face in faces:
        face.draw(frame)

    if not camera.show(frame):
        break

camera.close()
landmarker.close()
04 Face MetricsCalculate EAR, yaw, and pitch while keeping thresholds editable.
examples/04_face_metrics.py
"""Example 4: read EAR, yaw, and pitch."""

import cvgo as go


camera = go.Camera()
landmarker = go.FaceLandmarks()

while True:
    frame = camera.read()

    if frame is None:
        break

    faces = landmarker.detect(frame)

    if faces:
        face = faces[0]

        ear = go.eye_ratio(face)
        yaw = go.yaw_ratio(face)
        pitch = go.pitch_ratio(face)

        go.put_text(frame, f"EAR: {ear:.3f}")
        go.put_text(frame, f"Yaw: {yaw:.3f}", (20, 70))
        go.put_text(frame, f"Pitch: {pitch:.3f}", (20, 105))

        face.draw(frame)

    if not camera.show(frame):
        break

camera.close()
landmarker.close()
05 Serial ArduinoConnect automatically and send values to an Arduino.
examples/05_serial_arduino.py
"""Example 5: send data to Arduino."""

import cvgo as go


arduino = go.Serial()

if arduino.connected:
    arduino.send("1")

arduino.close()
06 Face to ArduinoSend face-presence status without repeating unchanged serial data.
examples/06_face_to_arduino.py
"""Example 6: send face detection status to Arduino."""

import cvgo as go


camera = go.Camera()
detector = go.FaceDetector()
arduino = go.Serial()
last_status = None

while True:
    frame = camera.read()

    if frame is None:
        break

    faces = detector.detect(frame)
    status = 1 if faces else 0

    if status != last_status:
        if arduino.send(status):
            last_status = status

    for face in faces:
        face.draw(frame)

    if not camera.show(frame):
        break

camera.close()
detector.close()
arduino.close()
07 Drowsiness DetectionCombine EAR, smoothing, a timer, and an alarm.
examples/07_drowsiness.py
"""Example 7: detect drowsiness based on EAR and duration."""

import cvgo as go


EAR_THRESHOLD = 0.20

camera = go.Camera()
landmarker = go.FaceLandmarks()
eye_timer = go.Timer(1.5)
ear_smoother = go.Smoother()
alarm = go.Alarm()

while True:
    frame = camera.read()

    if frame is None:
        break

    faces = landmarker.detect(frame)
    drowsy = False

    if faces:
        face = faces[0]
        ear = ear_smoother.update(go.eye_ratio(face))
        eyes_closed = ear < EAR_THRESHOLD
        drowsy = eye_timer.check(eyes_closed)

        status = "DROWSY" if drowsy else "NORMAL"
        color = (0, 0, 255) if drowsy else (0, 255, 0)

        go.put_text(frame, f"Status: {status}", color=color)
        go.put_text(frame, f"EAR: {ear:.3f}", (20, 70))
        face.draw(frame, color=color)
    else:
        eye_timer.reset()
        ear_smoother.reset()

    alarm.trigger(drowsy)

    if not camera.show(frame):
        break

camera.close()
landmarker.close()
08 Driver MonitorComplete modular monitoring with eyes, head direction, serial output, and FPS.
examples/08_driver_monitor.py
"""Example 8: final driver monitor project that is still easy to study."""

import cvgo as go


# Detection thresholds
EAR_THRESHOLD = 0.20
YAW_NORMAL = 0.50
YAW_LIMIT = 0.12
PITCH_NORMAL = 0.50
PITCH_LIMIT = 0.055

# Components
camera = go.Camera()
landmarker = go.FaceLandmarks()
arduino = go.Serial()
alarm = go.Alarm()
fps_counter = go.FPS()

# Condition timers
eye_timer = go.Timer(1.5)
turn_timer = go.Timer(0.7)
down_timer = go.Timer(0.7)
missing_timer = go.Timer(2.0)

# Eye value smoother
ear_smoother = go.Smoother()

# Last serial status
last_mask = None

while True:
    frame = camera.read()

    if frame is None:
        break

    faces = landmarker.detect(frame)
    fps = fps_counter.read()

    ear = None
    yaw = None
    pitch = None

    drowsy = False
    looking_away = False
    head_down = False
    face_missing = False

    if faces:
        face = faces[0]

        ear = ear_smoother.update(go.eye_ratio(face))
        yaw = go.yaw_ratio(face)
        pitch = go.pitch_ratio(face)

        eyes_closed = ear < EAR_THRESHOLD
        turn_condition = abs(yaw - YAW_NORMAL) > YAW_LIMIT
        down_condition = pitch - PITCH_NORMAL > PITCH_LIMIT

        drowsy = eye_timer.check(eyes_closed)
        looking_away = turn_timer.check(turn_condition)
        head_down = down_timer.check(down_condition)

        missing_timer.reset()
        face.draw(frame)
    else:
        eye_timer.reset()
        turn_timer.reset()
        down_timer.reset()
        ear_smoother.reset()

        face_missing = missing_timer.check(True)

    mask = 0

    if drowsy:
        mask |= go.BIT_DROWSY

    if looking_away:
        mask |= go.BIT_LOOKING_AWAY

    if head_down:
        mask |= go.BIT_HEAD_DOWN

    if face_missing:
        mask |= go.BIT_FACE_MISSING

    if mask != last_mask:
        if arduino.send(f"{mask:X}"):
            last_mask = mask

    alerts = []

    if drowsy:
        alerts.append("DROWSY")

    if looking_away:
        alerts.append("LOOKING_AWAY")

    if head_down:
        alerts.append("HEAD_DOWN")

    if face_missing:
        alerts.append("FACE_MISSING")

    status = " | ".join(alerts) if alerts else "NORMAL"
    color = (0, 0, 255) if alerts else (0, 255, 0)

    ear_text = "-" if ear is None else f"{ear:.3f}"
    yaw_text = "-" if yaw is None else f"{yaw:.3f}"
    pitch_text = "-" if pitch is None else f"{pitch:.3f}"

    go.put_text(
        frame,
        f"Status: {status}",
        (20, 35),
        color=color,
        background=True,
    )
    go.put_text(frame, f"EAR: {ear_text}", (20, 70))
    go.put_text(frame, f"Yaw: {yaw_text}", (20, 105))
    go.put_text(frame, f"Pitch: {pitch_text}", (20, 140))
    go.put_text(frame, f"FPS: {fps:.1f} | Mask: {mask:X}", (20, 175))

    alarm.trigger(mask != 0)

    if not camera.show(frame, title="CVGO Driver Monitor"):
        break

camera.close()
landmarker.close()
arduino.close()
09 Hand TrackingTrack 21 landmarks, handedness, and confidence for each hand.
examples/09_hand_tracking.py
"""Example 9: hand tracking, hand labels, and FPS."""

import cvgo as go


camera = go.Camera()
tracker = go.HandTracker()
fps = go.FPS()

while True:
    frame = camera.read()

    if frame is None:
        break

    hands = tracker.detect(frame)

    for hand in hands:
        hand.draw(frame)
        label = f"{hand.handedness}: {hand.confidence:.2f}"
        hand.box().draw(frame, label=label)

    go.put_text(frame, f"Hands: {len(hands)}")
    go.put_text(frame, f"FPS: {fps.read():.1f}", (20, 70))

    if not camera.show(frame, title="CVGO Hand Tracking"):
        break

camera.close()
tracker.close()
10 Pose TrackingDetect one main body pose with 33 landmarks.
examples/10_pose_tracking.py
"""Example 10: body pose tracking."""

import cvgo as go


camera = go.Camera()
tracker = go.PoseTracker()
fps = go.FPS()

while True:
    frame = camera.read()

    if frame is None:
        break

    pose = tracker.detect(frame)
    person_detected = pose is not None

    if pose:
        pose.draw(frame)

    status = "POSE DETECTED" if person_detected else "NO POSE"
    color = (0, 255, 0) if person_detected else (0, 0, 255)

    go.put_text(frame, status, color=color)
    go.put_text(frame, f"FPS: {fps.read():.1f}", (20, 70))

    if not camera.show(frame, title="CVGO Pose Tracking"):
        break

camera.close()
tracker.close()
11 Pose Security Use Pose Lite as a lightweight person box without a skeleton.
examples/11_security_pose.py
"""Example 11: lightweight person security with a pose bounding box."""

import cvgo as go


camera = go.Camera()
tracker = go.PoseTracker(model_complexity=0)
presence_timer = go.Timer(0.5)
alarm = go.Alarm()
fps = go.FPS()

while True:
    frame = camera.read()

    if frame is None:
        break

    pose = tracker.detect(frame)
    person_detected = pose is not None
    alert = presence_timer.check(person_detected)

    status = "ALERT" if alert else "SAFE"
    color = (0, 0, 255) if alert else (0, 255, 0)

    if pose:
        pose.box(
            padding=30,
        ).draw(
            frame,
            color=color,
            label="Person",
        )

    go.put_text(frame, f"Status: {status}", color=color)
    go.put_text(frame, f"FPS: {fps.read():.1f}", (20, 70))
    alarm.trigger(alert)

    if not camera.show(frame, title="CVGO Person Security Lite"):
        break

camera.close()
tracker.close()
12 Object DetectionDetect common objects and inspect labels, scores, and boxes.
examples/12_object_detection.py
"""Example 12: general object detection."""

import cvgo as go


camera = go.Camera()
detector = go.ObjectDetector(mode="live")
fps = go.FPS()

while True:
    frame = camera.read()

    if frame is None:
        break

    objects = detector.detect(frame)

    for item in objects:
        item.draw(frame)

    go.put_text(frame, f"Objects: {len(objects)}")
    go.put_text(frame, f"Loop FPS: {fps.read():.1f}", (20, 70))

    if not camera.show(frame, title="CVGO Object Detection"):
        break

camera.close()
detector.close()
13 Person SecurityFilter object detection to people for a security monitor.
examples/13_person_security.py
"""Example 13: detect multiple people for simple security."""

import cvgo as go


camera = go.Camera()
detector = go.ObjectDetector(allow=["person"], mode="live")
presence_timer = go.Timer(0.5)
alarm = go.Alarm()

while True:
    frame = camera.read()

    if frame is None:
        break

    people = detector.detect(frame)
    alert = presence_timer.check(bool(people))

    for person in people:
        person.draw(frame, color=(0, 0, 255))

    status = "ALERT" if alert else "SAFE"
    color = (0, 0, 255) if alert else (0, 255, 0)

    go.put_text(frame, f"Status: {status}", color=color)
    go.put_text(frame, f"Count: {len(people)}", (20, 70))
    alarm.trigger(alert)

    if not camera.show(frame, title="CVGO Person Security"):
        break

camera.close()
detector.close()
14 Gesture RecognitionRecognize supported hand gestures and their confidence.
examples/14_gesture_recognition.py
"""Example 14: hand gesture recognition."""

import cvgo as go


camera = go.Camera()
recognizer = go.GestureRecognizer(mode="live")

while True:
    frame = camera.read()

    if frame is None:
        break

    gestures = recognizer.detect(frame)

    for gesture in gestures:
        gesture.draw(frame)

    if not camera.show(frame, title="CVGO Gesture Recognition"):
        break

camera.close()
recognizer.close()
15 Holistic TrackingTrack face, pose, and both hands through one result.
examples/15_holistic_tracking.py
"""Example 15: face, pose, and hands in one pipeline."""

import cvgo as go


camera = go.Camera()
tracker = go.HolisticTracker()

while True:
    frame = camera.read()

    if frame is None:
        break

    result = tracker.detect(frame)
    result.draw(frame)

    if not camera.show(frame, title="CVGO Holistic Tracking"):
        break

camera.close()
tracker.close()
16 Selfie SegmentationSeparate a person from the background or measure coverage.
examples/16_selfie_segmentation.py
"""Example 16: blur the webcam background."""

import cvgo as go


camera = go.Camera()
segmenter = go.SelfieSegmenter()

while True:
    frame = camera.read()

    if frame is None:
        break

    result = segmenter.segment(frame)
    frame = result.blur(frame)

    if not camera.show(frame, title="CVGO Selfie Segmentation"):
        break

camera.close()
segmenter.close()
17 Telegram SecuritySend a camera photo to Telegram when a person is detected.
examples/17_telegram_security.py
"""Example 17: send a Telegram photo when a person is detected."""

import cvgo as go


camera = go.Camera()
detector = go.ObjectDetector(allow=["person"], mode="live")
telegram = go.Telegram()
presence_timer = go.Timer(0.5)
notified = False
pending = None

while True:
    frame = camera.read()

    if frame is None:
        break

    people = detector.detect(frame)
    alert = presence_timer.check(bool(people))

    if pending is not None and pending.done():
        if not pending.result():
            print(f"Telegram: {telegram.last_error}")
        pending = None

    for person in people:
        person.draw(frame, color=(0, 0, 255))

    status = "PERSON DETECTED" if alert else "SAFE"
    color = (0, 0, 255) if alert else (0, 255, 0)
    go.put_text(frame, f"Status: {status}", color=color)

    if alert and not notified and pending is None:
        pending = telegram.send_photo_async(
            frame,
            f"Warning: {len(people)} person(s) detected.",
            key="security",
        )

    notified = alert

    if not camera.show(frame, title="CVGO Telegram Security"):
        break

camera.close()
detector.close()
telegram.close()

Built to be studied and changed.

CVGO is released under the MIT License. The visible camera loops and decisions can grow into learning projects, security tools, or a complete driver-monitoring final project.

Back to top