Most computer-vision projects end at a test-set number. I wanted one you can point a camera at. So I put my trained fruit-and-veg classifier on the web — it runs entirely in your browser, no server, no upload — and made it show not just what it thinks, but where it looked to decide.
What's under the hood
The model is a MobileNetV2 fine-tuned by transfer learning on the Fruits-360 dataset: 201 classes, from Apple Golden to Zucchini. The ImageNet-pretrained backbone stays frozen; only a small head on top is trained — a global-average-pooling layer feeding a single softmax layer. On the studio test set it lands around 90% accuracy.
Getting it into the browser was cleaner than the NLP model. The whole preprocessing pipeline — resize, and the MobileNet-specific rescaling to a minus-one-to-one range — is baked into the network as layers. So the browser just hands it raw pixels; TensorFlow.js runs the forward pass on the GPU via WebGL. The shipped bundle is about 4 MB after quantising the weights to 8-bit.
The heat map is free
Here's the detail I like. The classifier head is global-average-pooling followed by a single dense layer. That is exactly the setup Class Activation Mapping was built for. The heat map for the predicted class is just the last convolutional feature maps, weighted by that class's dense weights, summed up — no gradients, no second pass. It falls straight out of the architecture.
So when the demo lights up the pixels that pushed it toward "Lemon", that glow is not a decoration bolted on afterwards — it is literally the evidence the final layer added up. Tap any of the top-5 guesses and you see what that class would have keyed on.
Where it breaks — on purpose
Fruits-360 is a studio dataset: one fruit, centred, on a clean background. That is the model's entire world. The most useful thing the demo does is let you step outside it:
- Hold the fruit in your hand and skin, fingers and background all fight for the model's attention.
- Point it at a cluttered scene and it has no notion of which object to name — it was never asked that question in training.
- Show two fruits at once and it still has to pick a single label for the whole frame, and can't.
Watch the confidence sag and the heat map wander onto the wrong things. That gap between the clean test number and the messy live behaviour is distribution shift, and seeing it beats reading about it.
How you'd ship this for real
A supermarket scanner wouldn't classify the raw frame. It would first detect and segment the object — YOLO or SAM style — feed only that crop to the classifier, and train on messy real-world photos instead of clean studio shots. The classifier here is one honest component of that larger system.
That honesty is the point. A model that quietly guesses on inputs it was never built for is a liability; one whose competence boundary you can see is something you can safely put in a pipeline.
Poke at it
- Live demo — upload a photo or use your webcam, read the top-5, and toggle the heat map.
- Code: fruits-360-Classifier