{"id":50525574,"url":"https://github.com/b7s/fluentvision","last_synced_at":"2026-06-05T09:00:34.028Z","repository":{"id":361505646,"uuid":"1253892351","full_name":"b7s/fluentvision","owner":"b7s","description":"FluentVision is a fluent API package, that provides a unified interface to two object detection backends","archived":false,"fork":false,"pushed_at":"2026-06-03T02:37:55.000Z","size":6918,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-03T07:37:48.127Z","etag":null,"topics":["laravel","llm","nanodet","object-detection","php","vision","yolo"],"latest_commit_sha":null,"homepage":"https://brunots.dev/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b7s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-29T23:18:42.000Z","updated_at":"2026-06-03T02:37:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/b7s/fluentvision","commit_stats":null,"previous_names":["b7s/fluentvision"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/b7s/fluentvision","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Ffluentvision","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Ffluentvision/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Ffluentvision/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Ffluentvision/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b7s","download_url":"https://codeload.github.com/b7s/fluentvision/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Ffluentvision/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33895175,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","llm","nanodet","object-detection","php","vision","yolo"],"created_at":"2026-06-03T07:31:31.383Z","updated_at":"2026-06-04T08:00:34.425Z","avatar_url":"https://github.com/b7s.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"docs/images/logo-bw.png\" width=\"200\" alt=\"FluentVision Logo\"\u003e\n    \u003ch1\u003eFluentVision\u003c/h1\u003e\n\u003c/div\u003e\n\nA fluent PHP 8.3+ API for YOLO object detection powered by [Ultralytics YOLO26](https://docs.ultralytics.com/) and [NanoDet-Plus](https://github.com/RangiLyu/nanodet).\n\nDetect, segment, classify, and annotate images with an elegant chainable interface — same PHP result types regardless of which backend runs inference.\n\n## Quick Start\n\n```bash\ncomposer require b7s/fluentvision\n```\n\n```php\nuse B7s\\FluentVision\\FluentVision;\nuse B7s\\FluentVision\\Enums\\Provider;\nuse B7s\\FluentVision\\Enums\\YoloModel;\n\n$result = FluentVision::make()\n    -\u003euseUltralytics()\n    -\u003emodel(YoloModel::YOLO26s)\n    -\u003euseCpu()\n    -\u003econfidence(0.5)\n    -\u003emedia('photo.jpg')\n    -\u003edetect();\n\necho $result-\u003egetDetectionCount() . \" objects found\\n\";\n\nforeach ($result-\u003edetections as $detection) {\n    echo sprintf(\"- %s (%.1f%%)\\n\", $detection-\u003eclass, $detection-\u003econfidence * 100);\n}\n```\n\n## Installation\n\nFirst, install Python dependencies and download models:\n\n```bash\n# Install the PHP package\ncomposer require b7s/fluentvision\n\n# Set up Python venv + packages + models\nphp ./vendor/bin/fluentvision install\n\n# Or install only one provider\nphp ./vendor/bin/fluentvision install --provider=ultralytics\nphp ./vendor/bin/fluentvision install --provider=nanodet\n\n# Download a specific model\nphp ./vendor/bin/fluentvision install --model=yolo26s.pt\nphp ./vendor/bin/fluentvision install --model=yoloe-26s-seg.pt\nphp ./vendor/bin/fluentvision install --model=nanodet-plus-m-416\n```\n\nThe local user running your system must be the same user who will be using FluentVision.\n\nTry something like this:\n\n```sh\nsudo -u www php ./vendor/bin/fluentvision install\n```\n\nThis will create the environment in the user's \"www\" folder: `/home/www/.fluentvision`.\n\n**Check your environment:**\n\n```bash\nphp ./vendor/bin/fluentvision doctor\n```\n\n## Providers\n\n| Provider        | Backend                                   | Best For                                             |\n|-----------------|-------------------------------------------|------------------------------------------------------|\n| **Ultralytics** | YOLO26 (n/s/m/l/x), YOLOE-26 (s/m/l + PF) | Full-featured, multi-task, open-vocabulary detection |\n| **NanoDet**     | NanoDet-Plus (M/T/G)                      | Ultra-lightweight, edge devices, real-time           |\n\nBoth providers return identical PHP result types — switch backends without changing your code.\n\n### YOLOE-26 Open-Vocabulary Detection\n\nYOLOE models support **text prompts** to detect anything you can describe — not just the 80 COCO classes:\n\n```php\nuse B7s\\FluentVision\\Enums\\YoloModel;\n\n$result = FluentVision::make()\n    -\u003euseUltralytics()\n    -\u003emodel(YoloModel::YOLOE26s)\n    -\u003euseCpu()\n    -\u003econfidence(0.25) // default: 0.4\n    -\u003eprompts(['person', 'yellow hard hat'])\n    -\u003emedia('factory.jpg')\n    -\u003edetect();\n```\n\n| Variant           | Suffix                | Prompts                     | Best For                               |\n|-------------------|-----------------------|-----------------------------|----------------------------------------|\n| **Text-prompted** | `yoloe-26*-seg.pt`    | `-\u003eprompts([...])` required | Targeted attribute/concept detection   |\n| **Prompt-free**   | `yoloe-26*-seg-pf.pt` | Not supported               | Auto-detect without specifying prompts |\n\n### Ultralytics Solutions\n\n![solutions](docs/medias/solutions.webp)\n\nRun 12 built-in Ultralytics solutions (counting, heatmaps, speed estimation, etc.) with a single fluent call:\n\n```php\nuse B7s\\FluentVision\\Enums\\UltralyticsSolution;\n\n$result = FluentVision::make()\n    -\u003emedia('highway.mp4')\n    -\u003esolution(UltralyticsSolution::Count, [\n        'region' =\u003e '[[20,400],[1080,400],[1080,800],[20,800]]',\n    ])\n    -\u003ewithAnnotation(true)\n    -\u003eprocess();\n\necho \"In: {$result-\u003einCount}, Out: {$result-\u003eoutCount}\\n\";\n```\n\nSee [docs/solutions.md](docs/solutions.md) for all 12 solutions and their parameters.\n\n## Detection Examples\n\n### Modern Workspace\n\n```php\n$result = FluentVision::make()\n    -\u003euseUltralytics()\n    -\u003emodel(YoloModel::YOLO26s)\n    -\u003emedia('modern-workspace-with-laptop-coffee-plants.jpg')\n    -\u003edetect();\n```\n\n![Modern workspace detection](docs/medias/modern-workspace-with-laptop-coffee-plants.webp)\n\n### Person + Cup\n\n```php\n$result = FluentVision::make()\n    -\u003euseUltralytics()\n    -\u003emodel(YoloModel::YOLO26s)\n    -\u003econfidence(0.6)\n    -\u003emedia('woman-cup-coffe.jpg')\n    -\u003edetect();\n```\n\n![Woman cup detection](docs/medias/woman-cup-coffe.webp)\n\n### Street Scene with Segment\n\n```php\n$result = FluentVision::make()\n    -\u003euseUltralytics()\n    -\u003emodel(YoloModel::YOLOE26mPF) // Segment with Prompt free\n    -\u003econfidence(0.8)\n    -\u003emedia('woman-bike-cars-trees-road-day.jpg')\n    -\u003edetect();\n// 9 detections: person (90.6%), bicycle (91.2%), 7x car\n```\n\n![Street scene annotated](docs/medias/woman-bike-cars-trees-road-day-annotated.webp)\n\n### Video Detection — Street Traffic\n\n```php\n$result = FluentVision::make()\n    -\u003euseUltralytics()\n    -\u003emodel(YoloModel::YOLO26s)\n    -\u003econfidence(0.4)\n    -\u003eeveryNframes(10)\n    -\u003emedia('/path-to-video/people-crossing-cars.mp4')\n    -\u003edetect();\n\necho $result-\u003egetFrameCount() . \" frames\\n\";\necho $result-\u003egetTotalDetections() . \" total detections\\n\";\n// 48 frames, 342 detections — person, car, bus, traffic light\n```\n\n![Street video scene annotated](docs/medias/people-crossing-cars.gif)\n\n## Detection Result Array\n\nThe `detect()` method returns an `InferenceResult` object. Call `toArray()` to get a plain array:\n\n```php\n$result-\u003etoArray();\n\n// [\n//     'image_path' =\u003e '/path/to/photo.jpg',\n//     'provider' =\u003e 'ultralytics',\n//     'model' =\u003e 'yolo26s.pt',\n//     'inference_time' =\u003e 0.1367,\n//     'detection_count' =\u003e 2,\n//     'detections' =\u003e [\n//         [\n//             'class' =\u003e 'person',\n//             'confidence' =\u003e 0.910,\n//             'box' =\u003e ['x1' =\u003e 198.0, 'y1' =\u003e 242.0, 'x2' =\u003e 675.0, 'y2' =\u003e 836.0],\n//         ],\n//         [\n//             'class' =\u003e 'cup',\n//             'confidence' =\u003e 0.646,\n//             'box' =\u003e ['x1' =\u003e 638.0, 'y1' =\u003e 459.0, 'x2' =\u003e 844.0, 'y2' =\u003e 630.0],\n//         ],\n//     ],\n// ]\n```\n\n## Fluent API\n\n```php\nuse B7s\\FluentVision\\FluentVision;\nuse B7s\\FluentVision\\Enums\\Device;\nuse B7s\\FluentVision\\Enums\\Provider;\nuse B7s\\FluentVision\\Enums\\YoloModel;\nuse B7s\\FluentVision\\Enums\\NanodetModel;\nuse B7s\\FluentVision\\Enums\\YoloTask;\n\nFluentVision::make()\n    -\u003eprovider(Provider::Ultralytics) // or -\u003euseUltralytics() / -\u003euseNanodet()\n    -\u003emodel(YoloModel::YOLO26s) // or -\u003emodel('yolo26s.pt') or -\u003emodel('/path/to/custom.pt')\n    -\u003emedia('/path/to/image.jpg') // media type auto-detected from extension\n    // -\u003emedia('/path/to/clip.mp4') // video — auto-detected from extension\n    -\u003euseCpu() // or -\u003euseGpu()\n    -\u003econfidence(0.5) // confidence threshold\n    -\u003eiou(0.45) // IoU threshold (NMS)\n    -\u003eimgsz(640) // inference image size\n    -\u003emaxDet(100) // max detections per image\n    -\u003eclasses(['person', 'car']) // filter to specific classes\n    -\u003eprompts(['person wearing red', 'hard hat']) // YOLOE text prompts\n    -\u003eaugment() // test-time augmentation\n    -\u003ehalf() // FP16 inference (GPU required)\n    -\u003ewithDetections() // include detection data (default: true)\n    -\u003ewithAnnotation() // include annotated image (default: false)\n    -\u003eprocess(); // returns ProcessResult with both\n    // -\u003emedia('rtsp://camera/live')\n    // -\u003estreamConfig(function ($frame, $num, $result) { ... }, null, 100) // real-time stream (Ultralytics only)\n    // -\u003eprocess(); // returns StreamResult\n```\n\n### Image Detection\n\n```php\n$result = FluentVision::make()\n    -\u003emedia('photo.jpg')\n    -\u003edetect();\n```\n\n### Video Detection\n\n```php\n$result = FluentVision::make()\n    -\u003emedia('clip.mp4')  // .mp4 auto-detected as video\n    -\u003eeveryNframes(10) // process every 10th frame - default: 5\n    //-\u003evidStride(10) // Alias for -\u003eeveryNframes(10)\n    -\u003edetect();\n\necho $result-\u003egetFrameCount() . \" frames processed\\n\";\necho $result-\u003egetTotalDetections() . \" total detections\\n\";\n```\n\n\u003e For realtime stream, check: [Real-Time Streaming](docs/realtime-streaming.md)\n\n### Image Annotation\n\n```php\n$result = FluentVision::make()\n    -\u003emedia('photo.jpg')\n    -\u003eannotate();\n\necho \"Annotated image saved to: \" . $result-\u003eannotatedPath . \"\\n\";\n```\n\n### Detect + Annotate in One Call\n\nUse `process()` to get both detections and an annotated image in a single inference run:\n\n```php\nuse B7s\\FluentVision\\Results\\ProcessResult;\n\n$result = FluentVision::make()\n    -\u003emedia('photo.jpg')\n    -\u003ewithDetections()       // include detection data (default: true)\n    -\u003ewithAnnotation()       // include annotated image (default: false)\n    -\u003eprocess();             // returns ProcessResult\n\necho \"Detections: \" . $result-\u003egetDetectionCount() . \"\\n\";\necho \"Annotated: \" . $result-\u003egetAnnotatedPath() . \"\\n\";\n\n// Access the individual results\n$detections = $result-\u003edetections;  // InferenceResult|VideoInferenceResult\n$annotation = $result-\u003eannotation;  // AnnotatedResult\n```\n\n`process()` runs inference **once** — more efficient than calling `detect()` and `annotate()` separately.\n\n### Working with Results\n\n```php\n$result = FluentVision::make()-\u003emedia('photo.jpg')-\u003edetect();\n\n// Counts\n$result-\u003egetDetectionCount();\n$result-\u003eisEmpty();\n\n// Filter detections\n$persons = $result-\u003efilterByClass('person');\n$highConf = $result-\u003efilterByMinConfidence(0.8);\n\n// Unique classes\n$classes = $result-\u003egetClasses();\n\n// Individual detections\nforeach ($result-\u003edetections as $d) {\n    echo $d-\u003eclass;           // \"person\"\n    echo $d-\u003econfidence;      // 0.92\n    echo $d-\u003ebox-\u003ex1;         // 100.0\n    echo $d-\u003ebox-\u003ewidth();    // 150.5\n    echo $d-\u003ebox-\u003earea();     // 22650.25\n}\n\n// Serialize\n$data = $result-\u003etoArray();\n```\n\n### NanoDet Example\n\n```php\nuse B7s\\FluentVision\\Enums\\NanodetModel;\n\n$result = FluentVision::make()\n    -\u003euseNanodet()\n    -\u003emodel(NanodetModel::PlusM416)\n    -\u003emedia('photo.jpg')\n    -\u003edetect();\n```\n\n### Custom Trained Models\n\nPass a path to your own trained model — provider is auto-inferred from the file extension:\n\n```php\n// Ultralytics (.pt, .onnx, .engine, etc.) — auto-detected\n$result = FluentVision::make()\n    -\u003emodel('/path/to/my-trained-model.pt')\n    -\u003emedia('photo.jpg')\n    -\u003edetect();\n\n// NanoDet — use nanodetCustom() for config + checkpoint\n$result = FluentVision::make()\n    -\u003enanodetCustom('/path/config.yml', '/path/model.ckpt')\n    -\u003emedia('photo.jpg')\n    -\u003edetect();\n```\n\nSee [Custom Models](docs/custom-models.md) for full details on supported formats, model resolution, and provider auto-inference.\n\n## Configuration\n\nCreate `fluentvision-config.php` in your project root:\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nreturn [\n    'default_provider'       =\u003e 'ultralytics',\n    'ultralytics_default_model' =\u003e 'yolo26s.pt',\n    'nanodet_default_model'  =\u003e 'nanodet-plus-m-416',\n    'default_device'         =\u003e 'cpu',\n    'default_conf'           =\u003e 0.25,\n    'default_iou'            =\u003e 0.7,\n    'default_imgsz'          =\u003e 640,\n    'python_path'            =\u003e null,           // auto-detect\n    'python_venv_path'       =\u003e null,           // default: ~/.fluentvision/venv\n    'model_dir'              =\u003e null,           // default: ~/.fluentvision/models\n    'nanodet_repo_path'      =\u003e null,           // default: ~/.fluentvision/nanodet\n    'timeout'                =\u003e 0,              // 0 = no timeout\n    'verbose'                =\u003e false,\n];\n```\n\nOr load from a custom path:\n\n```php\n$vision = FluentVision::make('/path/to/my-config.php');\n```\n\n## CLI Commands\n\n```bash\n# Environment check\nvendor/bin/fluentvision doctor\n\n# Install all dependencies\nvendor/bin/fluentvision install\n\n# Install specific provider\nvendor/bin/fluentvision install --provider=ultralytics\nvendor/bin/fluentvision install --provider=nanodet\n\n# Download a model\nvendor/bin/fluentvision install --model=yolo26m.pt\nvendor/bin/fluentvision install --model=nanodet-plus-m-416\n\n# Use custom config\nvendor/bin/fluentvision doctor --config=/path/to/config.php\nvendor/bin/fluentvision install --config=/path/to/config.php\n```\n\n## Requirements\n\n- PHP 8.3+\n- Python 3.8+ with pip\n- Ultralytics or NanoDet Python packages (installed via `fluentvision install`)\n\n## Documentation\n\n- [Installation Guide](docs/installation.md) — step-by-step setup\n- [Configuration Reference](docs/configuration.md) — all config options\n- [Usage Guide](docs/usage.md) — complete fluent API reference\n- [Providers](docs/providers.md) — Ultralytics vs NanoDet details\n- [Custom Models](docs/custom-models.md) — using your own trained models\n- [Result Objects](docs/results.md) — InferenceResult, ProcessResult, StreamResult, SolutionResult, DetectionResult, BoundingBox API\n- [Ultralytics Solutions](docs/solutions.md) — object counting, heatmaps, speed estimation, and 9 more built-in solutions\n- [Real-Time Streaming](docs/realtime-streaming.md) — RTSP, RTMP, webcam frame-by-frame detection\n- [CLI Commands](docs/cli.md) — install, doctor, and options\n\n## License\n\nMIT\n\n---\n\n[Image by freepik](https://www.magnific.com/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb7s%2Ffluentvision","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb7s%2Ffluentvision","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb7s%2Ffluentvision/lists"}