--- license: apache-2.0 base_model: yolo26n language: - en tags: - object-detection - yolo - indian-fmcg - onnx - ultralytics pipeline_tag: object-detection datasets: - agentsk47/indian-grocery-object-detection-mfsnx - iit-patna-qg1jh/grocery_items-7i2em - project-c5ho0/indian-market-qieug --- # YOLO26n — Indian FMCG Product Detection Fine-tuned [YOLO26n](https://docs.ultralytics.com) on a **merged dataset of three Indian grocery sources** from Roboflow Universe to detect and localize packaged FMCG products in shelf or counter images. Part of the **Kirana Detective** project — an AI system for small Indian grocery stores to visually count and reconcile inventory from photos. > **Note**: This file is a local reference snapshot. The actual model card uploaded to HuggingFace Hub is generated dynamically at the end of `train_yolo26n.py` and will include the real class list and metrics from the latest training run. ## Model Description The model takes a 640×640 image and returns bounding boxes, class labels, and confidence scores for all detected Indian FMCG product categories. It is exported as ONNX for deployment on both CPU and GPU without requiring a full PyTorch installation. The class list is built at training time by merging the three Roboflow dataset vocabularies (deduped, insertion-order). See `class_names.json` on HF Hub for the exact unified list. ## Pilot Run Results (single dataset, 10 classes) The metrics below are from a previous training run using only the `agentsk47/indian-grocery-object-detection` dataset (10 classes). They are superseded by the current merged 3-dataset training run. **Pilot classes:** | # | Class | |---|---| | 0 | Bournvita | | 1 | Mysore Sandal Soap | | 2 | Nescafe Classic Coffee | | 3 | Nivea Body Lotion | | 4 | Nivea Soft Moisturising Cream | | 5 | Parachute Coconut Oil | | 6 | Patanjali Dant Kanti | | 7 | Society Tea Powder Plain | | 8 | Tresemme Hairfall Defense Conditioner | | 9 | Tresemme Hairfall Defense Shampoo | ## Pilot Evaluation Results (best.pt, epoch 65 — single dataset run) | Class | Images | Instances | Precision | Recall | mAP50 | mAP50-95 | |---|---|---|---|---|---|---| | **all** | **41** | **51** | **0.935** | **0.971** | **0.993** | **0.933** | | Bournvita | 3 | 3 | 0.902 | 1.000 | 0.995 | 0.995 | | Mysore Sandal Soap | 8 | 8 | 1.000 | 0.905 | 0.995 | 0.944 | | Nescafe Classic Coffee | 4 | 4 | 0.927 | 1.000 | 0.995 | 0.908 | | Nivea Body Lotion | 7 | 7 | 0.935 | 1.000 | 0.995 | 0.923 | | Nivea Soft Moisturising Cream | 3 | 3 | 0.924 | 1.000 | 0.995 | 0.895 | | Parachute Coconut Oil | 6 | 6 | 1.000 | 0.819 | 0.972 | 0.928 | | Patanjali Dant Kanti | 7 | 7 | 1.000 | 0.985 | 0.995 | 0.971 | | Society Tea Powder Plain | 2 | 2 | 0.878 | 1.000 | 0.995 | 0.845 | | Tresemme Hairfall Defense Conditioner | 1 | 1 | 0.814 | 1.000 | 0.995 | 0.995 | | Tresemme Hairfall Defense Shampoo | 10 | 10 | 0.968 | 1.000 | 0.995 | 0.922 | ## How to Use ### Python (ONNX Runtime) ```python import json import numpy as np import onnxruntime as ort from PIL import Image session = ort.InferenceSession("yolo26n_fmcg.onnx", providers=["CPUExecutionProvider"]) class_names = json.load(open("class_names.json")) def preprocess(image_path, size=640): img = Image.open(image_path).convert("RGB").resize((size, size)) arr = np.array(img, dtype=np.float32) / 255.0 return arr.transpose(2, 0, 1)[None] # BCHW input_name = session.get_inputs()[0].name outputs = session.run(None, {input_name: preprocess("shelf.jpg")}) # outputs[0]: (1, 300, 6) — [x1, y1, x2, y2, confidence, class_id] ``` ### Ultralytics (PyTorch) ```python from ultralytics import YOLO model = YOLO("yolo26n_fmcg.onnx", task="detect") results = model.predict("shelf.jpg", imgsz=640, conf=0.25) results[0].show() ``` ## Training Details ### Datasets (merged) All three downloaded in **YOLOv8 format** (not openai), class IDs remapped to a unified list before training. | Dataset | Workspace | Version | Images | Classes | |---|---|---|---|---| | [Indian Grocery Object Detection](https://universe.roboflow.com/agentsk47/indian-grocery-object-detection-mfsnx) | agentsk47 | v1 | ~400 | 10 | | [Grocery Items](https://universe.roboflow.com/iit-patna-qg1jh/grocery_items-7i2em) | IIT Patna | v45 | 6,695 | 20 | | [Indian Market](https://universe.roboflow.com/project-c5ho0/indian-market-qieug) | project-c5ho0 | v2 | 4,694 | 2 | ### Hyperparameters | Parameter | Value | |---|---| | Base model | YOLO26n | | Input size | 640 × 640 | | Epochs (scheduled) | 100 | | Epochs (actual) | 85 (early stop at 65+20) | | Batch size | 16 | | Early stopping patience | 20 | | Optimizer | Auto (Ultralytics default) | | Export format | ONNX opset 12 | ### Training Infrastructure | Field | Value | |---|---| | Hardware | NVIDIA A10G (22 GB VRAM) | | Framework | Ultralytics 8.4.63 | | PyTorch | 2.12.0+cu130 | | Orchestration | Modal | | Training time | 0.094 hours (~5.6 minutes) | | Model size | 5.4 MB (PyTorch) · 9.4 MB (ONNX) | | Parameters | 2,376,786 | | GFLOPs | 5.2 | | Inference speed | 0.2 ms preprocess + 1.0 ms inference (A10G) | ### Training Curve Notes (pilot run) - Best checkpoint at **epoch 65** (mAP50 = 0.993, mAP50-95 = 0.933) — single-dataset pilot - EarlyStopping triggered at epoch 85 (no improvement for 20 epochs) - Final box loss: 0.4201 · cls loss: 0.4657 · dfl loss: 0.006 The current 3-dataset merged training run will produce updated curve notes. ## Limitations - Merged dataset skewed toward beauty/personal care (Tresemmé, Nivea, Patanjali); may underperform on grocery staples - ~11K images across 3 sources; performance on crowded shelves or partial occlusions is untested - Exported at opset 12 for broad compatibility; advanced indexing operations use multi-op decomposition (see ONNX export warning) ## Citation ```bibtex @misc{kirana-detective-yolo-2026, title = {Kirana Detective: YOLO26n Indian FMCG Product Detector}, author = {Syed Naazim Hussain}, year = {2026}, url = {https://huggingface.co/build-small-hackathon/yolo26n-indian-fmcg-detection} } ```