Skip to content

Bag

Your bag is empty

Building BikeID: Race Number Tagging Is Harder Than It Looks

0 Comments

Building BikeID: Race Number Tagging Is Harder Than It Looks

I am pretty cautious about the use of generative AI in mountain bike event photography. I do not use AI to generate, replace or fake anything in my race images. For me, the whole point is that the photos are real moments from real events, and I want them to stay that way.

With that said, I do think there is a place for AI in a race photographer’s workflow, but not in the way people might first assume. Rather than using AI to create, edit, or change an image, BikeID was conceived to solve a different problem: identifying race number plates and automatically tagging images, speeding up the post-race workflow.

When I shoot a race or an event, speed matters. It is not just about getting the photos edited nicely. Riders want to find themselves while the event is still fresh in their minds, and if the gallery goes up too late, interest has already moved on. Race photo sites, including platforms like Roots & Rain, let riders search by plate number. For a lot of racers, that is the main way they find their images. That makes tagging really important.

The problem: tagging is one of the most time-consuming parts of the whole process. After a race weekend, you might have hundreds, if not thousands, of images to sort through. Going through those manually, reading every number plate, and tagging each rider takes time. For race and event photography, where getting the photos out quickly really matters, that is a massive bottleneck.

That is what led me to start building BikeID.

BikeID is a macOS app I have been working on to identify race numbers from mountain bike photos using machine learning and AI. The idea is fairly simple: process a set of race images, detect the number on the rider’s plate, and make the tagging process faster. In practice, it turns out to be much more difficult than it sounds.

Why race number plates are awkward

Race number plates should be easy to read, but in photos they often are not. They can be tilted, covered in mud, blown out by light, hidden in shadow, or distorted by movement. On mountain bikes, there is another very specific problem: brake cables. A number might be perfectly clear to a human at a glance, but if a brake cable cuts across one of the digits, the system can struggle. A 6 can start to look like an 8. A 1 can disappear. A 3 can become something else entirely. It is exactly the kind of messy real-world problem that looks simple until you try to automate it.

How BikeID works

BikeID uses local machine learning models to try and match the number plate without sending every image off to an external AI model. That local matching step is useful because it is faster, cheaper, and gives me more control over the process. It also keeps the reliance on LLMs down, with the local matching currently covering around 70% of the images before anything needs to go near an LLM.

That was partly a practical decision, but also a way of avoiding unnecessary API calls. If the local matching is not confident enough, the app can then fall back to using a large language model through an API. The idea is that the local process handles the obvious cases, while the LLM is only used when the number is harder to read. At the moment, I am getting an overall accuracy rate around a 95%, which is not bad for a messy real-world problem like this. Clean plates, decent angles and obvious numbers are usually fine.

Where it gets interesting

The worrying bit is not that it gets some plates wrong. I expected that. The bigger issue is confidence. When BikeID gets a plate wrong, the AI does not always behave as if it is unsure. In some cases it will return the wrong number with complete confidence. That is much harder to work with than a simple “not sure”.

For a race gallery, that matters. If the system says it cannot read a plate, I can flag it for manual checking. That is useful. But if it confidently puts the wrong rider number against a photo, it creates a different problem. The image ends up being incorrectly tagged, the wrong rider finds it, and the person it belongs to may never see it. This is not meant as a dig at AI. If anything, the project has made me more impressed by what it can do. But it has also shown me that confidence and accuracy are not always the same thing.

Where AI still struggles

AI is now incredibly advanced, but BikeID has been a useful reminder that advanced does not mean reliable at everything. The hardest examples are often the ones a person can work out fairly quickly. If a brake cable cuts across a plate, you can sometimes mentally ignore it and still read the number. The model does not always do that reliably.

It might read the cable as part of the digit, or treat an obscured number as something else entirely. That is the part I still need to work on. It is not just about getting the system to read more plates. It is about getting it to understand when an answer should be trusted, and when the image needs to be checked manually.

Why this matters for race photography

For race photography, accurate number detection could make a big difference. The galleries are already searchable by plate number, but the tagging has to happen first. If BikeID can make that process faster without introducing too many mistakes, it could reduce one of the biggest bottlenecks in getting race photos online.

But it needs to be reliable enough to actually help. There is no point building something that looks clever but creates more work in the long-run. If I still have to check every image manually, or fix loads of wrong matches, the app has not really solved the problem. The goal is not to use AI for the sake of it. The goal is to make the workflow better.

What's next for BikeID?

BikeID is still unfinished. It works in places, falls over in others, and proves that even clever AI can still get confused by a rogue brake cable. I will hopefully come back to it, tighten up the confidence checking, and see if I can turn it into something genuinely useful in a race photography workflow.

Leave a comment

This site is protected by hCaptcha and the hCaptcha Privacy Policy and Terms of Service apply.

All comments are moderated before being published.