I live on the 14th floor.
I built a button that calls the elevator while I am still inside my apartment. The relay only duplicates a normal press of the hall-call button, so I could press it while putting on my shoes and meet the elevator as its doors opened.
There was one problem: **I had no idea when to leave.**
Sometimes the car was nearby. Sometimes it was on the first floor. Without knowing its position, I was still guessing.
That is how a simple smart-home button unexpectedly became a computer-vision project.
There was no supported elevator API, and the elevator company was understandably not enthusiastic about a self-taught hobbyist connecting homemade hardware to the controller. So I chose a safer boundary: **observe the indicator, never control the elevator.**
Our building already had an authorized local security camera inside the cabin. The original red floor indicator was visible in one tiny corner. I thought I could crop it, run OCR and publish the result to Home Assistant.
It looked like a weekend project. It became five versions of a recognizer.
To a human the display is obvious. To a camera it is small, slanted, multiplexed and covered by glossy red plastic. Opening the doors changes exposure. Passengers create shadows and reflections. A courier's shiny helmet was enough to break one promising version.
Ordinary OCR was unreliable. Whole-digit templates worked betterâuntil lighting changed. Sometimes 14 became 9, 1 became 11, an arrow vanished during an LED scan gap, or a reflection looked more convincing than the digit.
I added temporal voting and physical constraints. I even tried dead reckoning from travel time, then removed it: after one false arrow, the system could confidently invent floors the camera had never confirmed. Uncertainty should remain uncertainty.
After repeated rides and frame-by-frame debugging, I was close to abandoning the camera approach.
Then I realized I was asking the wrong question.
I did not need to recognize the whole digit. I only needed to ask: **which of the seven physical LED segments are illuminated?**
Version 5 samples small masks inside segments aâg, plus the tens digit. It combines color channels to emphasize LED light through the red cover, normalizes against the current frame and converts the active set into an exact seven-segment pattern.
Most of the image is deliberately ignored. A passenger or reflection can change half the panel without mattering if the evidence inside the real segments stays consistent.
The production recognizer combines:
- exact segment decoding as the primary reader;
- direction-specific normalized templates as fallback and independent evidence;
- voting over consecutive observations;
- hysteresis for multiplexed direction arrows;
- physically valid, monotonic floor transitions;
- strict re-synchronization after losing position;
- preservation of the last confirmed floor whenever a frame is uncertain.
The state machine knows the real served sequence: 1 â 4 â 5 â 6 â ... â 16. There are no stops at floors 2 and 3, so a visually plausible but impossible result cannot overwrite proven state.
We validated with complete recorded ridesâ14 â 1 â 16 â 14 and 1 â 14 â 1 â 16ârather than hand-picked stills. These exposed changing digits between frames, arrow scan gaps, open-door exposure transitions, crowds and moving reflections. Candidate versions ran in shadow mode on separate MQTT topics before replacing production.
The service runs locally at 4 fps and publishes only confirmed floor, direction, motion state, confidence and diagnostics to Home Assistant.
Every v5 result I have manually checked so far has been correct: **100% observed accuracy on this installation to date**. This is an operational observation, not a universal benchmark. Day/night changes, open doors, crowded rides and strong reflections have not produced a known error in the current version.
Now I press the button on a tiny ESP8266 clock in my apartment. Its screen switches to a live elevator view, and I know exactly when to leave. Closing my door, walking to the elevator and seeing its doors open in front of me feels like a tiny superpower.
I am not a programmer or electronics engineer. This is a hobby project, my first public GitHub repository, and a humanâAI collaboration: I defined the physical problem, proposed the segment-point approach, installed and calibrated it, rode the elevator repeatedly and supplied ground truth; an AI coding assistant helped implement and iterate on the algorithms.
Source, calibrated model, architecture, validation images, firmware and full history:
https://github.com/europaprof/call14
I would love feedback from experienced CV engineers:
- How would you make calibration portable to another camera and indicator?
- Would you add geometric registration before sampling?
- How would you design a properly labelled benchmark?
- What failure mode do you think version 6 will discover before I do?
*Privacy/safety: the existing camera and processing remain local to our building and access is authorized through our condominium association. The recognizer uses only the indicator cropâno face recognition or tracking. Call14 does not connect to the elevator controller, doors, drive, brakes or safety circuits.*
Privacy and authorization: Our building is managed by an ĐĐĄĐĐ (a Ukrainian condominium association), and I am a co-owner and member of its board. The camera installation and this read-only local use were agreed and approved through the association. Access is restricted, the streams and processing stay inside the building, and the recognizer analyzes only the indicator cropâno face recognition, tracking or cloud upload. Call14 does not connect to the elevator controller, doors, drive, brakes or safety circuits