File size: 3,925 Bytes
42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 563f365 42f3240 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | ---
license: apache-2.0
library_name: onnx
tags:
- meter-reading
- water-meter
- gas-meter
- home-assistant
pipeline_tag: image-classification
---
# VisionState wheel reader
The models [VisionState](https://github.com/oleost/VisionState) β a Home Assistant app that turns
camera images into sensors, locally β reads mechanical counters with (water and gas meters with
rolling digit wheels).
A model looks at **one wheel** and tells how far it has turned: a distribution over 100 positions
around the wheel (0.0, 0.1, β¦ 9.9), so a wheel half way between two digits is read as such.
VisionState splits the counter into one cell per wheel and picks the most likely value whose
wheel positions fit together (a wheel only turns while the wheel to its right goes from 9 to 0).
| File | Size | Inputs | Outputs |
|---|---|---|---|
| `wheels-v1.onnx` | 2.2 MB, 565 k parameters | `cells`: N Γ 1 Γ 48 Γ 32, float, 0β¦1 | `logits`: N Γ 100 |
| `wheels-v2.onnx` | 6.1 MB, 1.5 M parameters | `cells` as wheels-v1, and `context`: N Γ 1 Γ 48 Γ 64, the same cells with half a cell of the frame on each side | `logits`: N Γ 100 (log probabilities); `embedding`: N Γ 512 |
**Preprocessing of a cell:** grey from each pixel's darkest colour channel (coloured wheels look
like black ones), resized to 32 Γ 48 (64 Γ 48 with context, bilinear), autocontrast with 1 %
cut-off, divided by 255. wheels-v1 takes about 2 ms for eight wheels on one CPU thread,
wheels-v2 about 7 ms.
**wheels-v2** reads every wheel twice, once alone and once with its neighbours in view, so it
finds the wheel even when the region drawn around the counter does not quite fit. It was
distilled from an ensemble of 16 such pairs. Its confidence is the weakest wheel's (how sure it is
of the wheel it is least sure of), not the mean of all wheels.
## Training data
All of it may be used for anything:
- Drawn wheels (600 000 cells, and for wheels-v2 drawn rows of wheels with the region off) with
fonts from Google Fonts (SIL Open Font License): many colours, lighting, blur, noise and JPEG
artefacts, with exactly known positions.
- [Word-Wheel Water Meter Dataset](https://doi.org/10.5061/dryad.7d7wm3860) (Scientific Data,
2026), recognition crops β CC0.
- Checked readings shared by VisionState users in GitHub issues #32 and #40 β CC0; for wheels-v2
also two new exports of two water meters (October 2026) β CC0.
Training code, data sources and how to make the models again:
[`tools/wheelreader`](https://github.com/oleost/VisionState/tree/beta/tools/wheelreader).
## Results
Read with VisionState's decoding. wheels-v1:
- A water meter with red decimal wheels seen by an ESP32 camera with its flash, held out from
training: 17 of 17.
- Two water meters never seen in training: 30β33 of 35 and 15β18 of 18, no value too high.
- Word-Wheel test set (2,400 photos): 97.7 % when the photo is the right way up.
wheels-v2, each water meter held out from training in turn (five training runs; about 1,300
frames, every frame's value read by eye), against wheels-v1 on the same frames, through the app's
rules (published from 70 % confidence on, a counter never goes down):
| | wheels-v1 | wheels-v2 |
|---|---|---|
| Wrong values published, four periods of two meters | 3, 2, 1, 0 | 0 in 19 of 20 runs and periods; one run 1 (2 litres) |
| Frames read right, maintainer's meter | β | +4.4 and +1.4 points (significant) |
| Frames read right, the other meter | β | +0.6 and +0.1 points (no significant difference) |
| Region with its right edge half a cell short | 69 % right | 96 % |
| 33 free photos of meters no model has seen (Openverse) | 26 right | 28 right |
| Word-Wheel test set, six-wheel meters | 90.2 % | 94.0 % |
It publishes less often than wheels-v1 on a meter photographed from the side with the last wheel
turning: it is unsure there, and waits.
Not for pointer dials. Licence: Apache-2.0.
|