From 2a86d2ef2d36a86c2dd52382eb3f57fe1e186523 Mon Sep 17 00:00:00 2001 From: Rok Povsic Date: Mon, 22 Oct 2018 11:15:59 +0200 Subject: [PATCH] Add support for custom face recognition --- .../Requests/Inputs/ModifyInputRequest.php | 37 ++++++++++++-- .../API/Requests/Models/PredictRequest.php | 14 ++++-- src/Clarifai/DTOs/Crop.php | 7 ++- src/Clarifai/DTOs/Inputs/ClarifaiInput.php | 28 ++++++++++- src/Clarifai/DTOs/Inputs/ClarifaiURLImage.php | 16 ++++-- src/Clarifai/DTOs/Outputs/ClarifaiOutput.php | 3 ++ src/Clarifai/DTOs/Predictions/Concept.php | 5 ++ .../DTOs/Predictions/FaceConcepts.php | 13 ++++- src/Clarifai/DTOs/Predictions/Region.php | 49 +++++++++++++++++++ 9 files changed, 156 insertions(+), 16 deletions(-) diff --git a/src/Clarifai/API/Requests/Inputs/ModifyInputRequest.php b/src/Clarifai/API/Requests/Inputs/ModifyInputRequest.php index 403f7b0..ca25e05 100644 --- a/src/Clarifai/API/Requests/Inputs/ModifyInputRequest.php +++ b/src/Clarifai/API/Requests/Inputs/ModifyInputRequest.php @@ -6,6 +6,7 @@ use Clarifai\API\CustomV2Client; use Clarifai\API\RequestMethod; use Clarifai\API\Requests\ClarifaiRequest; +use Clarifai\DTOs\Feedbacks\RegionFeedback; use Clarifai\DTOs\Inputs\ClarifaiInput; use Clarifai\DTOs\Inputs\ModifyAction; use Clarifai\DTOs\Predictions\Concept; @@ -25,10 +26,19 @@ class ModifyInputRequest extends ClarifaiRequest /* @var Concept[] $positiveConcepts */ private $positiveConcepts; + + /** + * @param Concept[] $val + * @return $this + */ public function withPositiveConcepts($val) { $this->positiveConcepts = $val; return $this; } /* @var Concept[] $negativeConcepts */ private $negativeConcepts; + /** + * @param Concept[] $val + * @return $this + */ public function withNegativeConcepts($val) { $this->negativeConcepts = $val; return $this; } private $metadata; @@ -38,6 +48,14 @@ public function withNegativeConcepts($val) { $this->negativeConcepts = $val; ret */ public function withMetadata($val) { $this->metadata = $val; return $this; } + /** @var RegionFeedback[] */ + private $regionFeedbacks; + /** + * @param RegionFeedback[] $array + * @return $this + */ + public function withRegionFeedbacks($val) { $this->regionFeedbacks = $val; return $this; } + /** * Ctor. * @param ClarifaiHttpClientInterface $httpClient The Clarifai HTTP client. @@ -79,8 +97,16 @@ protected function httpRequestBody(CustomV2Client $grpcClient) $data->setConcepts($concepts); if (!is_null($this->metadata)) { - $a = new ProtobufHelper(); - $data->setMetadata($a->arrayToStruct($this->metadata)); + $pbh = new ProtobufHelper(); + $data->setMetadata($pbh->arrayToStruct($this->metadata)); + } + + if (!is_null($this->regionFeedbacks)) { + $regionFeedbacks = []; + foreach ($this->regionFeedbacks as $regionFeedback) { + array_push($regionFeedbacks, $regionFeedback->serialize()); + } + $data->setRegions($regionFeedbacks); } return $grpcClient->PatchInputs((new _PatchInputsRequest()) @@ -98,6 +124,9 @@ protected function httpRequestBody(CustomV2Client $grpcClient) */ protected function unmarshaller($inputsResponse) { - return ClarifaiInput::deserialize($inputsResponse->getInputs()[0]); + /** @var _Input[] $inputs */ + $inputs = $inputsResponse->getInputs(); + // Since only one input was added, only one output should be present. + return ClarifaiInput::deserialize($inputs[0]); } -} \ No newline at end of file +} diff --git a/src/Clarifai/API/Requests/Models/PredictRequest.php b/src/Clarifai/API/Requests/Models/PredictRequest.php index c7a50b1..2a05811 100644 --- a/src/Clarifai/API/Requests/Models/PredictRequest.php +++ b/src/Clarifai/API/Requests/Models/PredictRequest.php @@ -12,6 +12,7 @@ use Clarifai\Exceptions\ClarifaiException; use Clarifai\Internal\_Model; use Clarifai\Internal\_MultiOutputResponse; +use Clarifai\Internal\_Output; use Clarifai\Internal\_OutputConfig; use Clarifai\Internal\_OutputInfo; use Clarifai\Internal\_PostModelOutputsRequest; @@ -139,11 +140,14 @@ public function httpRequestBody(CustomV2Client $grpcClient) { */ public function unmarshaller($response) { - $outputResponses = $response->getOutputs(); - if ($outputResponses != null && count($outputResponses) === 1) { - $outputResponse = $outputResponses[0]; - return ClarifaiOutput::deserialize($this->httpClient, $this->modelType, $outputResponse); + if (is_null($response->getOutputs()) || count($response->getOutputs()) === 0) { + return ClarifaiOutput::deserialize($this->httpClient, $this->modelType, null); } - throw new ClarifaiException('There should be a single output.'); + $outputResponse = null; + if (!is_null($response->getOutputs())) { + /** @var _Output $outputResponse */ + $outputResponse = $response->getOutputs()[0]; + } + return ClarifaiOutput::deserialize($this->httpClient, $this->modelType, $outputResponse); } } diff --git a/src/Clarifai/DTOs/Crop.php b/src/Clarifai/DTOs/Crop.php index 7ad3304..7efd7a0 100644 --- a/src/Clarifai/DTOs/Crop.php +++ b/src/Clarifai/DTOs/Crop.php @@ -66,4 +66,9 @@ public static function deserialize($boxResponse) $boxResponse->getBottomRow(), $boxResponse->getRightCol()); } } -} \ No newline at end of file + + public function __toString() + { + return "[Crop: (top: $this->top, left: $this->left, bottom: $this->bottom, right: $this->right)]"; + } +} diff --git a/src/Clarifai/DTOs/Inputs/ClarifaiInput.php b/src/Clarifai/DTOs/Inputs/ClarifaiInput.php index 0f058f8..044dc1e 100644 --- a/src/Clarifai/DTOs/Inputs/ClarifaiInput.php +++ b/src/Clarifai/DTOs/Inputs/ClarifaiInput.php @@ -4,6 +4,7 @@ use Clarifai\DTOs\GeoPoint; use Clarifai\DTOs\Predictions\Concept; +use Clarifai\DTOs\Predictions\Region; use Clarifai\Exceptions\ClarifaiException; use Clarifai\Internal\_Data; use Clarifai\Internal\_Geo; @@ -89,7 +90,7 @@ public function withID($val) { $this->id = $val; return $this; } public function positiveConcepts() { return $this->positiveConcepts; } /** * @param Concept[] $val - * @return ClarifaiInput $this + * @return $this */ public function withPositiveConcepts($val) { $this->positiveConcepts = $val; return $this; } @@ -100,16 +101,31 @@ public function withPositiveConcepts($val) { $this->positiveConcepts = $val; ret public function negativeConcepts() { return $this->negativeConcepts; } /** * @param Concept[] $val - * @return ClarifaiInput $this + * @return $this */ public function withNegativeConcepts($val) { $this->negativeConcepts = $val; return $this; } private $metadata; + /** + * @return array + */ public function metadata() { return $this->metadata; } + /** + * @param array $val + * @return $this + */ public function withMetadata($val) { $this->metadata = $val; return $this; } private $createdAt; + + /** + * @return \DateTime + */ public function createdAt() { return $this->createdAt; } + /** + * @param \DateTime $val + * @return $this + */ public function withCreatedAt($val) { $this->createdAt = $val; return $this; } /** @var GeoPoint */ @@ -124,6 +140,14 @@ public function geo() { return $this->geo; } */ public function withGeo($val) { $this->geo = $val; return $this; } + private $regions; + /** + * @return Region[] + */ + public function regions() { return $this->regions; } + public function withRegions($val) { $this->regions = $val; return $this; } + + public function __construct($type, $form) { $this->type = $type; diff --git a/src/Clarifai/DTOs/Inputs/ClarifaiURLImage.php b/src/Clarifai/DTOs/Inputs/ClarifaiURLImage.php index 3ce95ef..ad00d94 100644 --- a/src/Clarifai/DTOs/Inputs/ClarifaiURLImage.php +++ b/src/Clarifai/DTOs/Inputs/ClarifaiURLImage.php @@ -3,11 +3,13 @@ namespace Clarifai\DTOs\Inputs; use Clarifai\DTOs\GeoPoint; +use Clarifai\DTOs\Predictions\Region; use Clarifai\Internal\_Image; use Clarifai\Internal\_Input; use Clarifai\DTOs\Crop; use Clarifai\DTOs\Predictions\Concept; use Clarifai\Helpers\ProtobufHelper; +use Clarifai\Internal\_Region; /** * An image at a certain URL. @@ -95,9 +97,8 @@ public static function deserialize($imageResponse) } if (!is_null($data->getMetadata())) { - $protobufHelper = new ProtobufHelper(); - - $image->withMetadata($protobufHelper->structToArray($data->getMetadata())); + $pbh = new ProtobufHelper(); + $image->withMetadata($pbh->structToArray($data->getMetadata())); } if (!is_null($data->getGeo())) { @@ -109,6 +110,15 @@ public static function deserialize($imageResponse) $image->withCreatedAt($imageResponse->getCreatedAt()->toDateTime()); } + if (!is_null($data->getRegions())) { + $regions = []; + /** @var _Region $r */ + foreach ($data->getRegions() as $r) { + array_push($regions, Region::deserialize($r)); + } + $image->withRegions($regions); + } + return $image; } diff --git a/src/Clarifai/DTOs/Outputs/ClarifaiOutput.php b/src/Clarifai/DTOs/Outputs/ClarifaiOutput.php index ee715af..032f059 100644 --- a/src/Clarifai/DTOs/Outputs/ClarifaiOutput.php +++ b/src/Clarifai/DTOs/Outputs/ClarifaiOutput.php @@ -79,6 +79,9 @@ protected function __construct($id, $createdAt, $model, $input, $predictions, $s public static function deserialize(ClarifaiHttpClientInterface $client, ModelType $modelType, $outputResponse) { + if (is_null($outputResponse)) { + return new ClarifaiOutput(null, null, null, null, [], null); + } return new ClarifaiOutput( $outputResponse->getId(), $outputResponse->getCreatedAt()->toDateTime(), diff --git a/src/Clarifai/DTOs/Predictions/Concept.php b/src/Clarifai/DTOs/Predictions/Concept.php index 4003666..4924e37 100644 --- a/src/Clarifai/DTOs/Predictions/Concept.php +++ b/src/Clarifai/DTOs/Predictions/Concept.php @@ -106,4 +106,9 @@ public static function deserializeJson($jsonObject) ->withCreatedAt($createdAt) ->withAppID($jsonObject['app_id']); } + + public function __toString() + { + return "[Concept: (id: $this->id, name: $this->name, value: $this->value)]"; + } } diff --git a/src/Clarifai/DTOs/Predictions/FaceConcepts.php b/src/Clarifai/DTOs/Predictions/FaceConcepts.php index 01e9dfc..c4ac1b4 100644 --- a/src/Clarifai/DTOs/Predictions/FaceConcepts.php +++ b/src/Clarifai/DTOs/Predictions/FaceConcepts.php @@ -3,6 +3,7 @@ namespace Clarifai\DTOs\Predictions; use Clarifai\DTOs\Crop; +use Clarifai\Internal\_Concept; use Clarifai\Internal\_Region; class FaceConcepts implements PredictionInterface @@ -12,6 +13,12 @@ class FaceConcepts implements PredictionInterface */ public function type() { return 'faceConcepts'; } + private $regionId; + /** + * @return string + */ + public function regionId() { return $this->regionId; } + private $crop; /** * @return Crop The crop in which the face is located. @@ -26,11 +33,13 @@ public function concepts() { return $this->concepts; } /** * Ctor. + * @param string $regionId The region ID. * @param Crop $crop The crop. * @param Concept[] $concepts The concepts. */ - private function __construct($crop, $concepts) + private function __construct($regionId, $crop, $concepts) { + $this->regionId = $regionId; $this->crop = $crop; $this->concepts = $concepts; } @@ -44,11 +53,13 @@ public static function deserialize($regionResponse) $face = $regionResponse->getData()->getFace(); $concepts = []; + /** @var _Concept $concept */ foreach ($face->getIdentity()->getConcepts() as $concept) { array_push($concepts, Concept::deserialize($concept)); } return new FaceConcepts( + $regionResponse->getId(), Crop::deserialize($regionResponse->getRegionInfo()->getBoundingBox()), $concepts); } } diff --git a/src/Clarifai/DTOs/Predictions/Region.php b/src/Clarifai/DTOs/Predictions/Region.php index 9388c75..81d8cc2 100644 --- a/src/Clarifai/DTOs/Predictions/Region.php +++ b/src/Clarifai/DTOs/Predictions/Region.php @@ -2,16 +2,65 @@ namespace Clarifai\DTOs\Predictions; +use Clarifai\DTOs\Crop; +use Clarifai\Internal\_Concept; +use Clarifai\Internal\_Region; + class Region { private $id; + /** + * @return string + */ + public function id() { return $this->id; } + private $crop; + /** + * @return Crop + */ + public function crop() { return $this->crop; } + private $concepts; + /** + * @return Concept[] + */ + public function concepts() { return $this->concepts; } + /** + * Ctor. + * @param string $id + * @param Crop $crop + * @param Concept[] $concepts + */ public function __construct($id, $crop, $concepts) { $this->id = $id; $this->crop = $crop; $this->concepts = $concepts; } + + /** + * @param _Region $regionResponse + * @return Region + */ + public static function deserialize($regionResponse) + { + $concepts = []; + if (!is_null($regionResponse->getData()) && + !is_null($regionResponse->getData()->getConcepts())) { + /** @var _Concept $c */ + foreach ($regionResponse->getData()->getConcepts() as $c) { + array_push($concepts, Concept::deserialize($c)); + } + } + $crop = null; + if (!is_null($regionResponse->getRegionInfo()) && + !is_null($regionResponse->getRegionInfo()->getBoundingBox())) { + $crop = Crop::deserialize($regionResponse->getRegionInfo()->getBoundingBox()); + } + return new Region( + $regionResponse->getId(), + $crop, + $concepts); + } }