$ show jo-m/trainbot
Trainbot (Onlytrains) is a computer vision application that automatically detects trains passing a fixed camera, stitches the train's frames into a single composite image, and logs sightings to a SQLite database. It is designed to run on a Raspberry Pi with a camera (USB, Pi Cam 3, or video file) and can optionally upload results via FTP to a web server. The project is unmaintained as stated in the README. Architecturally, it is a monolith Go backend with three CLI binaries: `trainbot` (main detection loop), `confighelper` (interactive crop selection), and `cleanup` (orphaned blob removal). The backend captures frames using `pkg/vid` (abstraction over V4L2, libcamera-vid, ffmpeg), processes them through a stitch pipeline that detects motion, computes frame offsets via patch matching, fits a constant-acceleration model using RANSAC, and then blends frames into a single JPEG and an animated GIF. Results are stored in a SQLite database and served by a built-in HTTP server. The frontend is a Vue 3 static SPA that loads the SQLite database client-side to display train sightings, stats, and images with no server-side rendering. Key highlights include highly optimized image processing: the `pkg/pmatch` package offers four implementations of cosine-similarity patch search (slow Go, optimized Go, Cgo, Vulkan compute), and the `pkg/ransac` package provides a generic RANSAC fitter for the speed model. The codebase demonstrates strong engineering craftsmanship with a clear package structure, extensive tests, test data sets, and a CI pipeline. However, heavy reliance on Cgo and Vulkan, plus the explicit unmaintained status, introduce cross-compilation complexity and potential drift from modern tooling.
The LLM identified 3 files worth highlighting for reuse:
A reusable image patch matching library that finds the best match of a template in a larger image using cosine similarity. Provides four implementations (slow Go, optimized Go, Cgo, Vulkan compute) selected at compile time via build tags, making it adaptable to various performance needs. Self-contained, with own test data and no internal imports beyond standard libraries and `pkg/imutil`. Can be extracted for any image matching task.
A generic RANSAC (Random Sample Consensus) implementation that fits a user-supplied model function to noisy data. In Trainbot it fits a quadratic velocity model to frame displacement points, but the algorithm is completely decoupled from any domain logic. The code is concise, well-tested, and can be reused for any regression or model fitting problem where outliers are present.
A thin Cgo wrapper around Vulkan compute pipelines that abstracts shader loading, buffer creation, descriptor sets, and pipeline dispatch. Simplifies running GPU compute shaders from Go without exposing the full Vulkan API. Self-contained and can be extracted for other compute-intensive tasks requiring GPU acceleration via Vulkan.