For my MSc dissertation I built a retail robot that drives past shelves, recognises products and updates a stock system. The first lesson was that a camera and a stock count work on completely different clocks.
The same product, thirty times a second
A detector looks at each frame on its own. A product that stays in view for a few seconds is detected in every one of those frames. If each detection were treated as an item, one bottle would become dozens.
So the first step is tracking. A tracker links detections across frames into one object with a stable identity. I used DeepSORT for that, on top of YOLO detections.
Tracking is not enough either
Trackers make mistakes that matter here. An object can be lost for a moment when something passes in front of it and then picked up again under a new identity. A box can flicker at the edge of the frame. Each of those looks like a new product arriving.
So between the tracker and the stock count I put a short history. An object has to be seen consistently over a window before it counts, and something that vanishes and reappears straight away in the same place is treated as the same thing. That is what debouncing means here: waiting for an observation to settle before believing it.
Only then does stock change
The part that talks to the stock system, over Odoo's API, sees settled observations and nothing else. The frame rate of the camera never reaches it.
A count also needs a place. An observation is tied to where the robot was and which shelf it was facing, so the same product seen from two aisles is not counted twice.
What I did not measure
This ran in a simulated shop in Gazebo. I evaluated that the pieces worked together. I do not have measured accuracy figures from a physical shop and I do not claim any.
The idea that carries over
A fast, noisy signal should pass through a deliberate step before it becomes a lasting record. The same rule applies to a webhook that fires twice or a button pressed twice.