├── tests ├── foo.jpg └── imageAiTest.php ├── .gitignore ├── composer.json ├── LICENSE.md ├── src ├── PythonScript.php └── imageAi.php └── README.md /tests/foo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awssat/imageAi/HEAD/tests/foo.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/* 2 | /vendor 3 | composer.lock 4 | /vendor 5 | /.idea 6 | .env 7 | .DS_Store 8 | /.vscode 9 | .idea -------------------------------------------------------------------------------- /tests/imageAiTest.php: -------------------------------------------------------------------------------- 1 | make('foo.jpg'); 19 | 20 | $imageAi = imageAi::image($img)->detect(); 21 | $imageAi->results[0]->image->save('car.jpg'); 22 | $this->assertEquals('car', $imageAi->results[0]->name); 23 | } 24 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "awssat/imageai", 3 | "description": "Wrapper for imageAi in PHP", 4 | "keywords": [ 5 | "awssat", 6 | "imageAi" 7 | ], 8 | "homepage": "https://github.com/awssat/imageAi", 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Bader Almutairi", 13 | "email": "bderemail@gmail.com", 14 | "role": "Developer" 15 | } 16 | ], 17 | "require": { 18 | "php": "^7.1", 19 | "intervention/image": "^2.4", 20 | "symfony/filesystem": "^4.3", 21 | "symfony/process": "^4.0" 22 | }, 23 | "require-dev": { 24 | "phpunit/phpunit": "^7.0" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "Awssat\\ImageAi\\": "src" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Awssat\\ImageAi\\Test\\": "tests" 34 | } 35 | }, 36 | "scripts": { 37 | "test": "vendor/bin/phpunit" 38 | }, 39 | "config": { 40 | "sort-packages": true 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Bader Almutairi 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/PythonScript.php: -------------------------------------------------------------------------------- 1 | currentDirPath = dirname(__FILE__); 25 | 26 | $this->imagePath = $this->currentDirPath . "/" . 27 | $image->filename . '.' . $image->extension; 28 | 29 | $this->imageDetectedPath = $this->currentDirPath . "/" . 30 | $image->filename . 'Detected.' . $image->extension; 31 | 32 | $this->modelPath = $this->currentDirPath . "/" . "resnet50_coco_best_v2.0.1.h5"; 33 | } 34 | 35 | protected function objects() 36 | { 37 | if(!empty($this->customObjects)) { 38 | $objects = implode('=True,', $this->customObjects) . '=True'; 39 | return <<speed) { 51 | return ''; 52 | } 53 | 54 | return "detection_speed=\"{$this->speed}\""; 55 | } 56 | 57 | public function generate() 58 | { 59 | return <<modelType() 65 | detector.setModelPath("$this->modelPath") 66 | detector.loadModel({$this->speed()}) 67 | {$this->objects()}input_image="$this->imagePath", output_image_path="$this->imageDetectedPath", minimum_percentage_probability=$this->percentage, extract_detected_objects=True) 68 | 69 | objects = [] 70 | for eachObject, eachObjectPath in zip(detections, objects_path): 71 | objects.append({"name": eachObject["name"], "percentage": eachObject["percentage_probability"], "box_points": eachObject["box_points"], "path": eachObjectPath}) 72 | 73 | print(objects) 74 | EOF; 75 | } 76 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Php ImageaAi 2 | 3 | Php soultion for https://github.com/OlafenwaMoses/ImageAI . try AI features in Php with help of python libraries 4 | 5 | ## Requirements 6 | First you need to install https://github.com/OlafenwaMoses/ImageAI with all requirements 7 | ## Install 8 | 9 | Via Composer 10 | ```bash 11 | composer require awssat/imageai 12 | ``` 13 | 14 | 15 | ## Usage 16 | 17 | 18 | ```php 19 | $imageAi = imageAi::image($img)->model('RetinaNet', '/path/to/resnet50_coco_best_v2.0.1.h5')->detect(); 20 | ``` 21 | ##### Result 22 | 23 | ```php 24 | 25 | $imageAi->results = 26 | [ 27 | [ 28 | "name": "car" 29 | "percentage": 97.267699241638 30 | "box_points": [ 31 | 1392 32 | 116 33 | 3541 34 | 1276 35 | ] 36 | "image": Intervention\Image\Image //object iamge 37 | ] 38 | ] 39 | ``` 40 | 41 | you should always define a model that supported in OlafenwaMoses/ImageAI 42 | 43 | ### Model types 44 | 45 | ``` 46 | RetinaNet 47 | YOLOv3 48 | TinyYOLOv3 49 | ``` 50 | 51 | you must download the RetinaNet, YOLOv3 or TinyYOLOv3 object detection model via the links below:

52 | - RetinaNet (Size = 145 mb, high performance and accuracy, with longer detection time)
53 | 54 | - YOLOv3 (Size = 237 mb, moderate performance and accuracy, with a moderate detection time)
55 | 56 | - TinyYOLOv3 (Size = 34 mb, optimized for speed and moderate performance, with fast detection time)

57 | 58 | ### Other use cases 59 | 60 | #### Speed 61 | You can define speed of detection (affect accuracy) by simply calling 62 | 63 | ```php 64 | $imageAi = imageAi::image($img)->speed('fast')->model('RetinaNet', '/path/to/resnet50_coco_best_v2.0.1.h5')->detect(); 65 | ``` 66 | 67 | supported speeds (fast, faster, fastest, flash) 68 | 69 | #### Specfic objects 70 | 71 | You can only detect custom objects 72 | 73 | ```php 74 | $imageAi = imageAi::image($img)->customObjects(['car'])->model('RetinaNet', '/path/to/resnet50_coco_best_v2.0.1.h5')->detect(); 75 | ``` 76 | 77 | #### Percentage 78 | 79 | Define a minimum percentage of detection proccess 80 | 81 | ```php 82 | $imageAi = imageAi::image($img)->customObjects(['car'])->percentage(90)->model('RetinaNet', '/path/to/resnet50_coco_best_v2.0.1.h5')->detect(); 83 | ``` 84 | 85 | 86 | ## Contributing 87 | 88 | You are very welcome to contribute and improve this package. 89 | 90 | 91 | ## Credits 92 | 93 | - [Bader][link-author] 94 | - [All Contributors][link-contributors] 95 | 96 | ## License 97 | 98 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 99 | 100 | [link-author]: https://github.com/if4lcon 101 | [link-contributors]: ../../contributors 102 | -------------------------------------------------------------------------------- /src/imageAi.php: -------------------------------------------------------------------------------- 1 | image = $image; 27 | $this->fsObject = new Filesystem(); 28 | $this->imageManager = new ImageManager(); 29 | $this->pythonGenerator = new PythonScript($image); 30 | $this->execPath = $this->pythonGenerator->currentDirPath . "/exec.py"; 31 | } 32 | 33 | public function percentage(int $percentage) 34 | { 35 | $this->pythonGenerator->percentage = $percentage; 36 | 37 | return $this; 38 | } 39 | 40 | public function customObjects(array $objects) 41 | { 42 | $this->pythonGenerator->customObjects = $objects; 43 | 44 | return $this; 45 | } 46 | 47 | public function speed($speed) 48 | { 49 | if(!in_array($speed, ['normal', 'fast', 'faster', 'fastest', 'flash'])) { 50 | throw new \Exception('speed provided not supported'); 51 | } 52 | 53 | $this->pythonGenerator->speed = $speed; 54 | 55 | return $this; 56 | } 57 | 58 | public function model($type, $path) 59 | { 60 | if(!in_array($type, ['RetinaNet', 'TinyYOLOv3', 'YOLOv3'])) { 61 | throw new \Exception('Type provided not supported'); 62 | } 63 | 64 | $this->pythonGenerator->modelType = $type; 65 | $this->pythonGenerator->modelPath = $path; 66 | 67 | return $this; 68 | } 69 | 70 | static public function image(Image $image) 71 | { 72 | return (new self($image)); 73 | } 74 | 75 | public function detect() 76 | { 77 | //save a copy on working dir 78 | $this->image->save($this->pythonGenerator->imagePath); 79 | 80 | $this->createExecPythonFile(); 81 | 82 | $this->results = array_map(function ($object) { 83 | $object['image'] = $this->imageManager->make($object['path']); 84 | unset($object['path']); 85 | return (object) $object; 86 | }, $this->execAndGetOutput()); 87 | 88 | $this->truncateCaches(); 89 | 90 | return $this; 91 | } 92 | 93 | protected function getResults($output) 94 | { 95 | return json_decode($this->fixJSON($output), true) ?? []; 96 | } 97 | 98 | protected function fixJSON($JSON) 99 | { 100 | $JSON = str_replace("'","\"", $JSON); 101 | $JSON = str_replace("array(","", $JSON); 102 | $JSON = str_replace("])","]", $JSON); 103 | $JSON = str_replace(")","]", $JSON); 104 | $JSON = str_replace("(","[", $JSON); 105 | 106 | return $JSON; 107 | } 108 | 109 | protected function createExecPythonFile() 110 | { 111 | try { 112 | $this->fsObject->remove($this->execPath); 113 | 114 | if (!$this->fsObject->exists($this->execPath)) { 115 | $this->fsObject->touch($this->execPath); 116 | $this->fsObject->chmod($this->execPath, 0777); 117 | $this->fsObject->dumpFile($this->execPath, $this->pythonGenerator->generate()); 118 | } 119 | } catch (\Exception $exception) { 120 | throw new \Exception("Error creating file at" . $exception->getFile()); 121 | } 122 | } 123 | 124 | protected function truncateCaches() 125 | { 126 | $this->fsObject->remove($this->execPath); 127 | $this->fsObject->remove($this->pythonGenerator->imagePath); 128 | $this->fsObject->remove($this->pythonGenerator->imageDetectedPath); 129 | $this->fsObject->remove($this->pythonGenerator->imageDetectedPath . '-objects'); 130 | } 131 | 132 | protected function execAndGetOutput() 133 | { 134 | $process = new Process(['python3', $this->execPath]); 135 | $process->run(); 136 | 137 | // executes after the command finishes 138 | if (!$process->isSuccessful()) { 139 | 140 | $this->truncateCaches(); 141 | 142 | throw new ProcessFailedException($process); 143 | } 144 | 145 | return $this->getResults($process->getOutput()); 146 | } 147 | } 148 | --------------------------------------------------------------------------------