A number of months ago, I was implementing some complex transaction forming functionality in a work project, and found I was spending more time creating test scenarios and testing my implementation than I could spend developing, as a consequence of the complex nature of the data, and real-time processing components. Traditionally, we would create data using real and configured hardware, or load a video into one of our ANPR (Automatic Number Plate Recognition) engine providers, to simulate a camera. Although I had previously made tools to automatically create videos for simulation from a csv of licence plate data, it wasn’t practical to make synchronised videos for > 2 ANPR lanes.
The transaction forming and read processing systems are idiosyncratic in the industry, and offer a lot of flexibility in ANPR applications. A number plate would typically be detected by our ANPR/LPR hardware in free flow (a vehicle passes through the camera and its presence is automatically acknowledged by the system), or triggered (another device or mechanism prompts the engine to analyse the currently buffered field of view and extract a licence plate read), and passed by its provider to the integrator, which would abstract the provider’s function and configuration, and facilitate a conduit to the processing hub and data repositories. The hub is then able to accept the read, analyse the circumstances from which it arrived, and determine the next stage to pass it to for further processing.
Stages could do anything, from post-correcting a numberplate (changing a low confidence ‘i’ to a ‘1’ in an Australian state with a plate format that has a higher probability of presenting a ‘1’ in this position), or transposing the read from its physical origin to a virtual lane or camera based on complex rules or traffic direction, to forming transactions and journeys from the existing reads in conjunction with this read, representing a visit in a car park, or passage through a defined zone.
When a stage is developed or modified, it typically relies on complex aggregated read data. Understandably using real hardware is quite burdensome to set up, configure, and track. The alternative is to artificially create data; this might otherwise result in setting up integration tests or seeding a data store. These again only go so far, especially whilst debugging in real time. I created a solution at home to simplify the end to end process, with a generation system that could create an artificial looking number plate and attach it to a drawn vehicle. Although petty, the image of the vehicle is important because this makes it easy to keep track of a certain car and notice greater system flaws during integration.
My solution mounted as a provider inside our existing integrator, and was effortlessly absorbed by the IOC (inversion of control) resolver, (ensuring compatibility back to 2012!), and presented a WebAPI 2.0 set of endpoints. The endpoints permitted triggering a free flow read or queueing data at a camera/lane/engine level to be dequeued should a trigger arrive externally. This further extended to generate a random licence plate from the permissible stand-issue Victorian plates, or to generate a car for a known plate in the correct format, to providing the exact data desired for the read; including metadata, to images.
Although I haven’t updated this specific tool in a long time, I have expanded components for many other projects with features such as Taxi and Bus support, multiple state standard issue plate support, consistent car generation for any particular plate text, and fun value adds, like derelict looking vehicles to attach to watch lists, and people rendered driving the cars. I am now at a point where I would like to formalise the generation, rendering, and web interface components, to support my LEAP (LPR Engine Accuracy Platform) family of projects, which will eventually contribute towards developing my own ANPR/LPR engine from the ground up. This would include:
- A portable definition file for a licence plate format, so that it can be created in an editor by a graphic designer or engineer, and integrated with any other LEAP component.
- A portable definition file for a vehicle, or content generally. Supporting multiple colours, layers, and rules. Again, the goal would be to extract the engineering/design work so that it can be performed by someone more effective in this domain.
- An ANPR/LPR virtual engine, with full metadata, such as plate coordinates, and an inaccuracy factor to simulate a real engine in software.
- An abstracted ANPR/LPR Engine interface, with a provider to utilise my virtual implementation.
- A presentable web interface to wrap and present all the virtual engine functions, and configure the instance.
As the study semester concludes and my free time becomes more available, this will be something I work towards, after first defining the shape of a generic ANPR/LPR read (LEAP.ReadIO). A new and exciting project has arisen at work which would largely benefit from such a system, and I’m confident time in orders of magnitude could be saved in development and testing.