feat: carry the JAN and the price's provenance through the tag pipeline
The card reader produces a JAN (the last three digits printed on the tag) and says whether a price was measured from the big digits or derived from the tax-included one; the session record and the wire payload dropped both, so the strongest identity anchor the tag carries never left the reader. Also reads each card at three scales rather than two. The tax-included price is small print and only resolves at 3x; without it the price falls back to the stylised digits, which misread (measured: 30 instead of 269, 20 instead of 199). Measured through the real still path on add/image6.jpg, the tags now attached to products read: 269/357, 379/400, 199/248, 209/500, 219/200, 349/150 - prices and JANs, where the same run previously reported tags that were not in the readable row at all and prices like 2630 from another tag's text. Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
23fd087611
commit
8e33b3ebdd
1 changed files with 19 additions and 1 deletions
|
|
@ -142,6 +142,8 @@ class TagRecord:
|
|||
"discount": self.discount,
|
||||
"unit_price": self.unit_price,
|
||||
"name": self.name,
|
||||
"jan": self.jan,
|
||||
"price_source": self.price_source,
|
||||
"flags": list(self.flags),
|
||||
"confidence": round(float(self.confidence), 3),
|
||||
"observations": len(self.observations),
|
||||
|
|
@ -510,7 +512,9 @@ class TagService:
|
|||
aspect = width / float(height)
|
||||
if not (TAG_MIN_ASPECT <= aspect <= TAG_MAX_ASPECT):
|
||||
continue
|
||||
pooled = read_card_lines(self.engine, image, box, scales=(1.0, 2.0 * max(1.0, scale_bias)))
|
||||
pooled = read_card_lines(
|
||||
self.engine, image, box, scales=(1.0, 2.0, 3.0 * max(1.0, scale_bias))
|
||||
)
|
||||
card = card_from_lines(pooled) if pooled else seed
|
||||
card.box = box
|
||||
if not card.fields.is_readable() and card.fields.price is None:
|
||||
|
|
@ -588,6 +592,8 @@ class TagService:
|
|||
names: Dict[str, float] = {}
|
||||
units: Dict[float, float] = {}
|
||||
discounts: Dict[float, float] = {}
|
||||
jans: Dict[str, float] = {}
|
||||
sources: Dict[str, float] = {}
|
||||
flags: set = set()
|
||||
confidences: List[float] = []
|
||||
for observation in record.observations:
|
||||
|
|
@ -603,6 +609,11 @@ class TagService:
|
|||
units[fields.unit_price] = units.get(fields.unit_price, 0.0) + weight
|
||||
if fields.discount is not None:
|
||||
discounts[fields.discount] = discounts.get(fields.discount, 0.0) + weight
|
||||
if getattr(fields, "jan", None):
|
||||
jans[fields.jan] = jans.get(fields.jan, 0.0) + weight
|
||||
sources[getattr(fields, "price_source", "none")] = (
|
||||
sources.get(getattr(fields, "price_source", "none"), 0.0) + weight
|
||||
)
|
||||
flags.update(fields.flags)
|
||||
confidences.append(observation.confidence)
|
||||
|
||||
|
|
@ -620,6 +631,13 @@ class TagService:
|
|||
record.name = top(names)
|
||||
record.unit_price = top(units)
|
||||
record.discount = top(discounts)
|
||||
record.jan = top(jans)
|
||||
# "measured" beats "derived" when both appear: a read is better evidence
|
||||
# than an inference, even though the inference is usually right.
|
||||
if sources.get("measured") and sources.get("derived"):
|
||||
record.price_source = "measured" if sources["measured"] >= sources["derived"] else "derived"
|
||||
else:
|
||||
record.price_source = top(sources) or "none"
|
||||
record.flags = sorted(flags)
|
||||
record.confidence = sum(confidences) / len(confidences) if confidences else 0.0
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue