Passed
Push — main ( def15a...da0044 )
by Chris
12:51
created

Recognizable::recognition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Meema\MediaRecognition\Traits;
4
5
use Meema\MediaRecognition\Facades\Recognize;
6
use Meema\MediaRecognition\Models\MediaRecognition;
7
8
trait Recognizable
9
{
10
    /**
11
     * Get all of the media items' conversions.
12
     *
13
     * @return \Illuminate\Database\Eloquent\Relations\MorphOne
14
     */
15
    public function recognition(): \Illuminate\Database\Eloquent\Relations\MorphOne
16
    {
17
        return $this->morphOne(MediaRecognition::class, 'model');
0 ignored issues
show
Bug introduced by
It seems like morphOne() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

17
        return $this->/** @scrutinizer ignore-call */ morphOne(MediaRecognition::class, 'model');
Loading history...
18
    }
19
20
    /**
21
     * Start a media "recognition".
22
     *
23
     * @param string $path
24
     * @param string|null $mimeType
25
     * @return \Meema\MediaRecognition\Contracts\MediaRecognition
26
     */
27
    public function recognize(string $path, string $mimeType = null)
28
    {
29
        return Recognize::source($path, $mimeType, $this->id);
30
    }
31
32
    /**
33
     * Return all recognition data.
34
     * The return value "null" indicates that a recognition has been ran, but it just has no results.
35
     * Please note, the Rekognition response is different from a "video" to an "image".
36
     *
37
     * @return array
38
     */
39
    public function recognitionData(): array
40
    {
41
        $recognition = $this->recognition()->first();
42
43
        if (! $recognition) {
44
            return [
45
                'labels' => null,
46
                'faces' => null,
47
                'moderation' => null,
48
                'texts' => null,
49
            ];
50
        }
51
52
        // null indicates that the "recognition" has not been ran for the category
53
        $labels = $faces = $moderation = $texts = null;
54
55
        if ($recognition->labels && is_array($recognition->labels['Labels'])) {
56
            $labels = $recognition->labels['Labels'];
57
        }
58
59
        if ($recognition->faces && is_array($recognition->faces['FaceDetails'])) {
60
            $faces = $recognition->faces['FaceDetails'];
61
        } elseif ($recognition->faces && is_array($recognition->faces['Faces'])) {
62
            $faces = $recognition->faces['Faces'];
63
        }
64
65
        if ($recognition->moderation && is_array($recognition->moderation['ModerationLabels'])) {
66
            $moderation = $recognition->moderation['ModerationLabels'];
67
        }
68
69
        if ($recognition->ocr && is_array($recognition->ocr['TextDetections'])) {
70
            $texts = $recognition->ocr['TextDetections'];
71
        }
72
73
        return [
74
            'labels' => $labels,
75
            'faces' => $faces,
76
            'moderation' => $moderation,
77
            'texts' => $texts,
78
        ];
79
    }
80
81
    public function minimalRecognitionData(
82
        bool $includeLabels = true,
83
        bool $includeFaces = true,
84
        bool $includeModeration = true,
85
        bool $includeTexts = true,
86
        int $limit = 50
87
    ): array {
88
        $data = $this->recognitionData();
89
90
        if (! $data) {
91
            return [
92
                'labels' => null,
93
                'faces' => null,
94
                'moderation' => null,
95
                'texts' => null,
96
            ];
97
        }
98
99
        $array = [];
100
101
        if ($includeLabels) {
102
            $array['labels'] = collect($data['labels'])->map(function ($label) {
103
                return $this->generateLabelElement($label);
104
            })->unique('name')->sortByDesc('confidence')->take($limit)->values()->toArray();
105
        }
106
107
        if ($includeFaces) {
108
            $array['faces'] = collect($data['faces'])->map(function ($face) {
109
                return $this->generateFaceElement($face);
110
            })->sortByDesc('confidence')->take($limit)->values()->toArray();
111
        }
112
113
        if ($includeModeration) {
114
            $array['moderation'] = collect($data['moderation'])->map(function ($moderation) {
115
                return $this->generateModerationElement($moderation);
116
            })->unique('name')->sortByDesc('confidence')->take($limit)->values()->toArray();
117
        }
118
119
        if ($includeTexts) {
120
            $array['texts'] = collect($data['texts'])->map(function ($text) {
121
                return $this->generateTextElement($text);
122
            })->unique('text')->sortByDesc('confidence')->take($limit)->values()->toArray();
123
        }
124
125
        return $array;
126
    }
127
128
    public function generateLabelElement($label): array
129
    {
130
        // image element
131
        if ($label['Name']) {
132
            return [
133
                'name' => $label['Name'],
134
                'confidence' => $label['Confidence'],
135
                'timestamp' => null, // timestamps are only available in videos
136
            ];
137
        }
138
139
        // video element
140
        return [
141
            'name' => $label['Label']['Name'],
142
            'confidence' => $label['Label']['Confidence'],
143
            'timestamp' => $label['Timestamp'],
144
        ];
145
    }
146
147
    public function generateFaceElement($face): array
148
    {
149
        // image element
150
        if ($face['BoundingBox']) {
151
            return [
152
                'bounding_box' => $face['BoundingBox'],
153
                'confidence' => $face['Confidence'],
154
                'timestamp' => null, // timestamps are only available in videos
155
            ];
156
        }
157
158
        // video element
159
        return [
160
            'bounding_box' => $face['Face']['BoundingBox'],
161
            'confidence' => $face['Face']['Confidence'],
162
            'timestamp' => $face['Timestamp'],
163
        ];
164
    }
165
166
    public function generateModerationElement($moderation): array
167
    {
168
        // image element
169
        if ($moderation['Name']) {
170
            return [
171
                'name' => $moderation['Name'],
172
                'confidence' => $moderation['Confidence'],
173
                'timestamp' => null, // timestamps are only available in videos
174
            ];
175
        }
176
177
        // video element
178
        return [
179
            'name' => $moderation['ModerationLabel']['Name'],
180
            'confidence' => $moderation['ModerationLabel']['Confidence'],
181
            'timestamp' => $moderation['Timestamp'],
182
        ];
183
    }
184
185
    public function generateTextElement($text): array
186
    {
187
        // image element
188
        if ($text['DetectedText']) {
189
            return [
190
                'text' => $text['DetectedText'],
191
                'confidence' => $text['Confidence'],
192
                'timestamp' => null, // timestamps are only available in videos
193
            ];
194
        }
195
196
        // video element
197
        return [
198
            'text' => $text['TextDetection']['DetectedText'],
199
            'confidence' => $text['TextDetection']['Confidence'],
200
            'timestamp' => $text['Timestamp'],
201
        ];
202
    }
203
}
204