PHPackages                             alkauni/planogrid - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. alkauni/planogrid

ActiveLibrary

alkauni/planogrid
=================

Framework-agnostic PHP package for Planogram Spatial Grid Sorting and AWS Rekognition Image Annotation.

v1.0.0(today)00MITPHPPHP ^8.1

Since Aug 14Pushed todayCompare

[ Source](https://github.com/hanifalkauni/planogrid)[ Packagist](https://packagist.org/packages/alkauni/planogrid)[ RSS](/packages/alkauni-planogrid/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (2)Versions (2)Used By (0)

Planogrid (`alkauni/planogrid`)
===============================

[](#planogrid-alkauniplanogrid)

[![PHP Version](https://camo.githubusercontent.com/acffb6ae1962992d26e4466782832787e79504a6250f80d732c4283458b9f497/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e312d626c75652e737667)](https://packagist.org/packages/alkauni/planogrid)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](LICENSE)[![Framework Agnostic](https://camo.githubusercontent.com/4a773f63f786a7935be1d25e5eddd31bdb33ad0263562dadb0acd496cde73d3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4672616d65776f726b2d41676e6f737469632d737563636573732e737667)](#framework-agnostic)

🌐 **Languages**: [English](README.md) | [Bahasa Indonesia](README.id.md)

---

**Planogrid** is a high-performance, **framework-agnostic** standalone PHP package designed for **2D Planogram Spatial Grid Sorting (Row x Column)** and **Output Image Generation (Bounding Box &amp; Label Annotations)** powered by AI detection results (such as AWS Rekognition Custom Labels or Vision AI).

Built purely with **PHP 8.1+**, it has zero framework dependencies and implements the **Strategy Pattern** with 6 spatial sorting algorithms to solve real-world shelf layout challenges (perspective tilt, varying product heights, chained vertical drift, physical shelf gap detection, etc.).

---

📌 Key Features
--------------

[](#-key-features)

- **Framework-Agnostic**: Compatible with **Laravel (10/11/12)**, **Symfony**, **CodeIgniter 4**, **Yii2**, or **Native PHP Scripts**.
- **2D Spatial Grid Sorter**: Converts unordered bounding box detections into an ordered 2D matrix: **Rows (Top to Bottom)** and **Columns (Left to Right)**.
- **6 Spatial Row Sorting Strategies (Strategy Pattern)**:
    - 🔹 **Strategy 0 (`SequentialDeltaStrategy`)**: Default sequential delta (`diffRangeValue >= minHeight`).
    - 🔹 **Strategy 1 (`BaselineAnchorStrategy`)**: Locks row top baseline anchor to eliminate cumulative chained drift.
    - 🔹 **Strategy 2 (`CenterYOverlapStrategy`)**: Groups items based on vertical Center-Y range overlap; ideal for mixing tall bottles and short boxes on the same shelf.
    - 🔹 **Strategy 3 (`SpatialClusterStrategy`)**: 1D Density Clustering on Center-Y for camera perspective tilt tolerance.
    - 🔹 **Strategy 4 (`VerticalIoUStrategy`)**: Objectively clusters rows using standard Computer Vision **1D Vertical Intersection over Union (IoU)** metric.
    - 🔹 **Strategy 5 (`ShelfProjectionStrategy`)**: 1D Vertical density histogram gap projection to detect physical shelf dividers.
- **Interactive Visual Image Annotator (Intervention Image v3)**:
    - Parallel double-line 2px bounding box border to prevent anti-aliasing blur.
    - **Dynamic Bounding Box Colors**:
        - 🟩 **Green (`#00d400`)**: Match / Verified according to planogram.
        - 🟥 **Red (`#ff0000`)**: Misplaced item / Competitor brand.
        - 🟨 **Yellow (`#ffcc00`)**: Confidence score below threshold.
    - **Adaptive Font Sizing &amp; Label Holder**: Dynamically scales label background to product name length.
    - **Custom TrueType Font (`.ttf`) Support**.
- **Template Verifier &amp; Compliance Scorer**: Evaluates detected grid matrix against target `PlanogramTemplate` to produce compliance percentage scores (% compliance).

---

💻 Minimum Requirements
----------------------

[](#-minimum-requirements)

- **PHP**: `^8.1` (PHP 8.2 / 8.3 recommended)
- **PHP Extensions**: `gd` or `imagick`
- **Package Dependency**: `intervention/image: ^3.0`

---

🚀 Installation
--------------

[](#-installation)

Install the package via Composer:

```
composer require alkauni/planogrid
```

---

📖 Usage Guide
-------------

[](#-usage-guide)

### 1. Spatial Grid Sorting (`process`)

[](#1-spatial-grid-sorting-process)

```
use Alkauni\Planogrid\PlanogramProcessor;
use Alkauni\Planogrid\Strategies\CenterYOverlapStrategy;

// 1. Raw detection data from AWS Rekognition Custom Labels
$customLabels = [
    [
        'Name' => 'Product Alpha 250ml',
        'Confidence' => 98.45,
        'Geometry' => ['BoundingBox' => ['Width' => 0.12, 'Height' => 0.25, 'Left' => 0.10, 'Top' => 0.15]],
    ],
    [
        'Name' => 'Product Beta 500ml',
        'Confidence' => 99.10,
        'Geometry' => ['BoundingBox' => ['Width' => 0.15, 'Height' => 0.25, 'Left' => 0.30, 'Top' => 0.16]],
    ],
];

// 2. Initialize Processor with Chosen Strategy
$processor = new PlanogramProcessor();
$gridResult = $processor
    ->setRowStrategy(new CenterYOverlapStrategy())
    ->process(
        customLabels: $customLabels,
        imageWidth: 1000,   // Image width in pixels
        imageHeight: 1000   // Image height in pixels
    );

// 3. Retrieve Formatted Output
$resultGeometry = $gridResult->getResultGeometry(); // Sorted pixel geometry array [row][col]
$resultBrands   = $gridResult->getResult();         // Matrix of "Brand 1", "Brand 2"
$jsonOutput     = $gridResult->toJson();
```

---

### 2. Full Verification &amp; Image Annotation (`verify`)

[](#2-full-verification--image-annotation-verify)

```
use Alkauni\Planogrid\PlanogramProcessor;
use Alkauni\Planogrid\DTO\PlanogramTemplate;
use Alkauni\Planogrid\DTO\PlanogramRow;
use Alkauni\Planogrid\DTO\PlanogramItem;
use Alkauni\Planogrid\Strategies\VerticalIoUStrategy;

// 1. Define Target Planogram Template (Ideal Grid Layout)
$expectedTemplate = new PlanogramTemplate([
    // Row 1 (Top Shelf)
    new PlanogramRow([
        new PlanogramItem('Product Alpha 250ml'),
        new PlanogramItem('Product Beta 500ml'),
    ]),
    // Row 2 (Bottom Shelf)
    new PlanogramRow([
        new PlanogramItem('Product Gamma 1L'),
        new PlanogramItem('Product Delta 100g'),
    ]),
]);

// 2. Load Input Photo Binary
$imageBinary = file_get_contents('shelf_photo.jpg');

// 3. Execute Complete Verification Workflow
$processor = new PlanogramProcessor();
$evaluation = $processor
    ->setRowStrategy(new VerticalIoUStrategy())
    ->setThresholdScore(100.0) // Compliance score threshold (100%)
    ->verify(
        imageBinary: $imageBinary,
        customLabels: $customLabels,
        expectedTemplate: $expectedTemplate,
        imageWidth: 1000,
        imageHeight: 1000
    );

// 4. Inspect Verification Results
echo "Status: " . $evaluation->getStatus(); // "correct" or "incorrect"
echo "Compliance Score: " . $evaluation->getComplianceScore() . "%";
echo "Matched Items: " . $evaluation->getMatchedCount() . " of " . $evaluation->totalExpected;

// 5. Save Annotated Output PNG Image
file_put_contents('output_annotated.png', $evaluation->getAnnotatedImage());
```

---

📊 Comparison of 6 Spatial Sorting Strategies
--------------------------------------------

[](#-comparison-of-6-spatial-sorting-strategies)

StrategyClass NameCore AlgorithmDetailed GuideRecommended Use Case**Strategy 0**`SequentialDeltaStrategy`Sequential delta `diffRangeValue >= minHeight`[🇬🇧 English](docs/strategies/strategy-0-sequential-delta.md) / [🇮🇩 Indonesia](docs/strategies/strategy-0-sequential-delta.id.md)Fast &amp; simple default**Strategy 1**`BaselineAnchorStrategy`Anchor initial top position + height multiplier[🇬🇧 English](docs/strategies/strategy-1-baseline-anchor.md) / [🇮🇩 Indonesia](docs/strategies/strategy-1-baseline-anchor.id.md)Long rows to prevent cumulative drift**Strategy 2**`CenterYOverlapStrategy`Center-Y vertical overlap range[🇬🇧 English](docs/strategies/strategy-2-center-y-overlap.md) / [🇮🇩 Indonesia](docs/strategies/strategy-2-center-y-overlap.id.md)Mixing tall bottles &amp; short boxes on same shelf**Strategy 3**`SpatialClusterStrategy`1D Center-Y density clustering[🇬🇧 English](docs/strategies/strategy-3-spatial-cluster.md) / [🇮🇩 Indonesia](docs/strategies/strategy-3-spatial-cluster.id.md)Tilted photos / camera perspective skew**Strategy 4**`VerticalIoUStrategy`1D Vertical Intersection over Union (IoU &gt;= 0.40)[🇬🇧 English](docs/strategies/strategy-4-vertical-iou.md) / [🇮🇩 Indonesia](docs/strategies/strategy-4-vertical-iou.id.md)Objective Computer Vision standard metric**Strategy 5**`ShelfProjectionStrategy`1D vertical density histogram gap projection[🇬🇧 English](docs/strategies/strategy-5-shelf-projection.md) / [🇮🇩 Indonesia](docs/strategies/strategy-5-shelf-projection.id.md)Segmenting products by physical shelf dividers---

🎨 Image Annotator Customization
-------------------------------

[](#-image-annotator-customization)

Customize bounding box colors, font size, custom TTF fonts, and labels via `ImageAnnotationConfig`:

```
use Alkauni\Planogrid\DTO\ImageAnnotationConfig;

$config = new ImageAnnotationConfig(
    matchColor: '#00d400',          // Green for match
    mismatchColor: '#ff0000',       // Red for mismatch
    lowConfidenceColor: '#ffcc00',  // Yellow for low confidence
    confidenceThreshold: 85.0,      // Items with < 85% confidence get yellow box
    fontPath: '/path/to/Inter.ttf', // Custom TTF Font
    fontSize: 14,
    borderThickness: 2,
    adaptiveFontSize: true,
    showConfidenceText: true
);

$processor->setImageConfig($config);
```

---

📚 Complete API Reference
------------------------

[](#-complete-api-reference)

### 1. `PlanogramProcessor` (Main Facade)

[](#1-planogramprocessor-main-facade)

The primary entrypoint class to control spatial grid sorting, template matching, and image annotations.

Method SignatureDescriptionReturn Type`setRowStrategy(RowSortingStrategyInterface $strategy)`Configures active row sorting strategy (Strategy 0 to 5).`static``setThresholdScore(float $score)`Sets compliance score passing percentage threshold (default `100.0`).`static``setImageConfig(ImageAnnotationConfig $config)`Configures visual bounding box drawing &amp; font options.`static``process(array $customLabels, float $imageWidth = 1.0, float $imageHeight = 1.0)`Executes 2D spatial grid sorting and returns sorted matrix.`PlanogramGridResult``verify(mixed $imageBinary, array $customLabels, ?PlanogramTemplate $expectedTemplate = null, float $imageWidth = 1.0, float $imageHeight = 1.0)`Executes complete verification workflow: sorting, template matching, and image annotation.`PlanogramEvaluation``annotate(mixed $imageBinary, array $customLabels, array $matchStatuses = [], float $imageWidth = 1.0, float $imageHeight = 1.0)`Annotates image binary with bounding boxes &amp; brand tags without template matching.`string` (PNG binary)---

### 2. `PlanogramGridResult` (Spatial Matrix Result DTO)

[](#2-planogramgridresult-spatial-matrix-result-dto)

Method SignatureDescriptionReturn Type`getResultGeometry()`Returns 2D matrix of sorted pixel coordinates `[row][col]` (`name`, `top`, `left`, `height`, `width`).`array``getResult()`Returns 2D brand label matrix `[row][Brand 1, Brand 2, ...]`.`array``toArray()`Returns combined `result_geometry` and `result` arrays.`array``toJson(int $options = JSON_PRETTY_PRINT)`Converts matrix result to formatted JSON string.`string`---

### 3. `PlanogramEvaluation` (Evaluation Result DTO)

[](#3-planogramevaluation-evaluation-result-dto)

Method SignatureDescriptionReturn Type`isCorrect()`Checks if planogram verification passed (`true` if score &gt;= threshold).`bool``getComplianceScore()`Returns planogram compliance score percentage (0.0% to 100.0%).`float``getStatus()`Returns verification status string (`"correct"` or `"incorrect"`).`string``getMatchedCount()`Returns count of items successfully matched with target template.`int``getDetectedMatrix()`Returns detected matrix structure.`array``getAnnotatedImage()`Returns annotated PNG image binary stream.`?string``toArray()`Converts evaluation result and mismatch list to array.`array`---

### 4. `ImageAnnotationConfig` (Image Drawing Config DTO)

[](#4-imageannotationconfig-image-drawing-config-dto)

```
new ImageAnnotationConfig(
    string $matchColor = '#00d400',         // HEX color for matched items
    string $mismatchColor = '#ff0000',      // HEX color for mismatched/competitor items
    string $lowConfidenceColor = '#ffcc00', // HEX color for low confidence score items
    float $confidenceThreshold = 85.0,     // Confidence score threshold (%)
    ?string $fontPath = null,               // Path to custom TrueType font (.ttf) file
    int $fontSize = 12,                     // Base font size
    int $borderThickness = 2,               // Bounding box border line thickness (px)
    bool $adaptiveFontSize = true,          // Auto font sizing based on product name length
    bool $showConfidenceText = true         // Render confidence score percentage text tag
);
```

---

⚡ Laravel Integration (Optional)
--------------------------------

[](#-laravel-integration-optional)

The package automatically registers its ServiceProvider via package auto-discovery in Laravel projects.

### Publishing Optional Config File:

[](#publishing-optional-config-file)

To customize default settings centrally across your Laravel application, publish the config file:

```
php artisan vendor:publish --tag=planogrid-config
```

This creates a new configuration file at `config/planogrid.php`.

### Usage in Laravel Controller:

[](#usage-in-laravel-controller)

```
use Alkauni\Planogrid\PlanogramProcessor;

class PlanogramController extends Controller
{
    public function verify(Request $request, PlanogramProcessor $processor)
    {
        $evaluation = $processor->verify(
            imageBinary: $request->file('photo')->get(),
            customLabels: $request->input('custom_labels'),
            expectedTemplate: $expectedTemplate
        );

        return response()->json($evaluation->toArray());
    }
}
```

---

🧪 Running Tests
---------------

[](#-running-tests)

Execute unit and integration tests via PHPUnit:

```
vendor/bin/phpunit
```

---

📜 License
---------

[](#-license)

This package is open-sourced software licensed under the [MIT License](LICENSE).

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/58505245?v=4)[Muhammad Hanif](/maintainers/hanifalkauni)[@hanifalkauni](https://github.com/hanifalkauni)

---

Top Contributors

[![hanifalkauni](https://avatars.githubusercontent.com/u/58505245?v=4)](https://github.com/hanifalkauni "hanifalkauni (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/alkauni-planogrid/health.svg)

```
[![Health](https://phpackages.com/badges/alkauni-planogrid/health.svg)](https://phpackages.com/packages/alkauni-planogrid)
```

###  Alternatives

[bagisto/bagisto

Bagisto Laravel E-Commerce

28.0k175.2k9](/packages/bagisto-bagisto)[unopim/unopim

UnoPim Laravel PIM

10.8k2.5k](/packages/unopim-unopim)[code16/sharp

Laravel Content Management Framework

79266.1k10](/packages/code16-sharp)[october/rain

October Rain Library

1601.7M103](/packages/october-rain)[intervention/image-laravel

Laravel Integration of Intervention Image

1589.8M225](/packages/intervention-image-laravel)[hasinhayder/tyro-dashboard

Tyro Dashboard - Beautiful admin dashboard for managing Tyro roles, privileges, users, and settings

5495.1k](/packages/hasinhayder-tyro-dashboard)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
