Read Gas / Water / Electricity Meter with webcam

I tried this out of interest and it seems to work. It only works (and not perfectly – it’s only a few hours’ worth of work) on one of our meters. The water meter is in the back of a dark kitchen cupboard where lighting of the meter dials can be controlled. I originally tried it on the electricity meter which sits on the wall behind our front door, between the stairs and living room door. Quite aside from the problem of daylight shining unreliably through the door glass, the scraps of wood and G-clamps required to hold the webcam and laptop in position in the confined but busy space were politically difficult.

Kitchen cupboard, desk lamp, webcam, water meter

Kitchen cupboard, desk lamp, webcam, water meter

The recipe:

  • PC (I used a Dell Mini 9 – a low power ‘netbook’) with:
  • USB webcam (not a built-in one – it’s handy to be able to use the PC without disturbing the webcam)
  • Light (I used a cheap LED-bulbed desklamp)
  • Power extension cable.

You may not have precisely the same ingredients in your cupboard: adjust the recipe to suit whatever you have handy.

Code in archive at the foot of the article – it should be obvious it’s a bodged proof-of-concept and not a finished product. The approach I took was to attempt to match the readout digits to samples of the digits. The webcam takes an image of the meter. That image is cropped to the meter readout window. The dials on my electricity meter were difficult to match because they didn’t ‘snap’ to showing full digits:

testcrop

I tried constructing a single vertical image showing all digits on it, but results from matching were bad. It was sometimes difficult to do it by eye – even ‘domain specific knowledge’ didn’t always help. Variable lighting conditions also had a devastating effect on the image correlations. The water meter’s readout is much better:

Water meter

Water meter

Even so, digits aren’t well aligned (some are occasionally slightly hidden by the edges of the readout window):

watermetercrop

The readout wheels also seem to move from side to side a little. The cropped digits after threshold are here:

crop0 crop1 crop2 crop3 cropa cropb

Individual digits are cropped out of this image and threshold applied to give a black-white image. Original testing was done with some manually-generated digit tiles which gave not bad results, but only with much intervention. As new digits appeared in the meter window, I cropped these down to ‘good’ examples. This can be a slow process, depending on how fast you consume the metered resource. My wife now responds to the sound of me flushing the toilet with “testing your software again?”

Comparing the unknown meter digits with the known examples is done with ImageMagick’s compare -NCC (Normalised Cross Correlation). Each cropped digit is compared with each sample digit and the ‘best’ match is taken as the integer value of the meter digit. This can throw up spurious results, so the Java code flags descending values (meter readings should go only up) and meter readings that rise unexpectedly quickly (I set a limit of one litre per second). Those rules could obviously be used to constrain the number of comparisons done, but that’s a ‘TODO’.

WaterMeter chart from firtl.com's log

WaterMeter chart from firtl.com’s log

The NCC on so many pairs of files is slow and my Dell Mini 9 will occasionally fail to complete all of them before the next sample – particularly if I’m logged in editing an image in GIMP, for example. Sampling is currently done by uvccapture which starts the image matching and data validation process after each sample. If I do any more work on this, I’d reverse that relationship first.

I’ve added a log-updating cURL line at the end of the bash script to upload the meter readings to a logging web service at another of my ‘works in progress’ to demonstrate the whole thing working. The chart presents 24 hours’ meter readings, showing no use overnight and slower use through the day than in the morning or evening.

“While I was in there” I added an image attachment facility to firtl.com’s log so that I can attach the cropped-out meter reading image with the log entry. This is what it looks like:

watermeterupdate

The update method uses a randomly-generated API key string so there’s no need to stay logged in nor to negotiate a login to submit data.

I’m not sure how long I’ll keep logging data for: the Dell Mini 9 is popular with my kids for playing Tremulous on, the extension power snaking around the kitchen worktop is controversial and the contents of that cupboard go into free-fall when the washing machine goes into its spin cycle. The archive contains sources, scripts and a little bit of example data. Enjoy!

Download readmeter.zip

A little update – the effect of the washing machine spin: the camera has moved. It’s obvious the reading is “0695.25″ but the code is producing “888X.25″. The ‘X’ is ‘no conclusive match’. If the 5 in the units position matches, the code will still reject ’8885.25′ as ‘too high’ due to the 1 litre-per-second maximum rate.

crop0 crop1 crop2 crop3 cropa cropb

Time for some intervention… and then some more intervention: a bad reading caused by the digit being low in the frame. I’ll leave that one in for posterity. I had to clear the ‘last good reading’ in my program to get it to report the next meter reading. Here are the readings for the 24 hours showing the bad reading. And here’s a little feature I added to tag and exclude bad readings (they may also be deleted).

Obviously

Obviously nobody (else) is about to G-clamp a laptop, desklamp, webcam and light-excluding housing to their domestic utility meter. I see no good reason why this couldn’t be re-packaged as a temporary ‘false front’ for analogue meters no larger than the meter faceplate (and not much thicker than a beermat) good for collecting up to weeks of data.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>