Camera and computer vision
Reading a live webcam, working its pixels, and simple thresholding and color tracking.
What’s realistic in Umfeld: there is a built-in
Captureclass for live cameras, and full access to pixels — so brightness thresholding and color tracking are a few loops away. Umfeld does not bundle OpenCV, blob detection, or face detection. If you need those, the patterns below (working directly onpixels[]) are the supported path; reach for an external C++ vision library only when you truly need it.
Using a webcam
Capture::list() enumerates devices; init() selects one with a resolution, frame rate, and
pixel format. Call reload() each frame before drawing it.
#include "Capture.h"
Capture* cam;
void setup() {
for (const auto& device : Capture::list()) console(device);
cam = new Capture();
cam->init("FaceTime HD Camera", "1280x720", "30", "nv12");
cam->start();
}
void draw() {
background(0);
cam->reload();
image(cam, 0, 0, width, height);
}
Reading the camera’s pixels
A Capture behaves like a PImage: after reload(), call loadPixels() and read pixels[].
Pull channels out of each pixel with red(), green(), blue().
cam->reload();
cam->loadPixels();
color_t c = cam->pixels[y * cam->width + x];
float brightness = (red(c) + green(c) + blue(c)) / 3.0f;
Thresholding video
Turn the frame into pure black and white at a brightness cut-off — the classic first step of any vision pipeline. Draw into the window’s own pixel buffer:
void draw() {
cam->reload();
cam->loadPixels();
loadPixels();
const float threshold = map(mouseX, 0, width, 0, 255);
for (int i = 0; i < width * height; i++) {
color_t c = cam->pixels[i];
float b = (red(c) + green(c) + blue(c)) / 3.0f;
pixels[i] = (b > threshold) ? color(255) : color(0);
}
updatePixels();
}
Color tracking
Find the average position of every pixel near a target color — enough to follow a brightly colored object without any library:
void draw() {
background(0);
cam->reload();
cam->loadPixels();
image(cam, 0, 0, width, height);
const color_t target = color(255, 0, 0); // tracking red
long sumX = 0, sumY = 0, count = 0;
for (int y = 0; y < cam->height; y++) {
for (int x = 0; x < cam->width; x++) {
color_t c = cam->pixels[y * cam->width + x];
float dr = red(c) - red(target);
float dg = green(c) - green(target);
float db = blue(c) - blue(target);
if (dr*dr + dg*dg + db*db < 60*60) { // within tolerance
sumX += x; sumY += y; count++;
}
}
}
if (count > 0) {
float cx = (float) sumX / count * width / cam->width;
float cy = (float) sumY / count * height / cam->height;
noFill();
stroke(0, 255, 0);
strokeWeight(4);
circle(cx, cy, 40);
}
}
The same idea — scanning pixels[] and collecting matching points — is the basis of a simple
blob tracker. Build up the bounding box of the matching pixels instead of just their average to
draw a box around the object.