Total Complexity | 159 |
Total Lines | 558 |
Duplicated Lines | 0 % |
Changes | 3 | ||
Bugs | 1 | Features | 0 |
Complex classes like core often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use core, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class core { |
||
15 | |||
16 | protected const LIBDIR = '/home/ghost/bin/c-lib/darknet/'; |
||
17 | protected const CFG_FASTEST_YOLO = __DIR__.'/cfg/yolo-fastest.cfg'; |
||
18 | protected const WEIGHT_FASTEST_YOLO = __DIR__.'/weight/yolo-fastest.weights'; |
||
19 | protected const CFG_FASTEST_YOLO_XL = __DIR__.'/cfg/yolo-fastest-xl.cfg'; |
||
20 | protected const WEIGHT_FASTEST_YOLO_XL = __DIR__.'/weight/yolo-fastest-xl.weights'; |
||
21 | protected const CFG_MOBILENET_V2_LITE = self::LIBDIR.'cfg/MobileNetV2-YOLOv3-Lite-coco.cfg'; |
||
22 | protected const WEIGHT_MOBILENET_V2_LITE = self::LIBDIR.'backup/MobileNetV2-YOLOv3-Lite-coco.weights'; |
||
23 | protected const CFG_MOBILENET_V2_VOC = self::LIBDIR.'cfg/MobileNetV2-yolo-Fastest-voc-v2.cfg'; |
||
24 | protected const WEIGHT_MOBILENET_V2_VOC = self::LIBDIR.'backup/MobileNetV2-YOLO-Fastest-voc-v2.weights'; |
||
25 | protected const CFG_VOC_TINY_2 = self::LIBDIR.'cfg/yolov2-tiny-voc.cfg'; |
||
26 | protected const WEIGHT_VOC_TINY_2 = self::LIBDIR.'backup/yolov2-tiny-voc.weights'; |
||
27 | protected const CFG_TINY_2 = self::LIBDIR.'cfg/yolov2-tiny.cfg'; |
||
28 | protected const WEIGHT_TINY_2 = self::LIBDIR . 'backup/yolov2-tiny.weights'; |
||
29 | protected const CFG_TINY_3 = self::LIBDIR . 'cfg/yolov3-tiny.cfg'; |
||
30 | protected const WEIGHT_TINY_3 = self::LIBDIR . 'backup/yolov3-tiny.weights'; |
||
31 | protected const CFG_TINY_4 = self::LIBDIR . 'cfg/yolov4-tiny.cfg'; |
||
32 | protected const WEIGHT_TINY_4 = self::LIBDIR . 'backup/yolov4-tiny.weights'; |
||
33 | protected const CFG_MAIN = self::LIBDIR . 'cfg/yolov3.cfg'; |
||
34 | protected const WEIGHT_MAIN = self::LIBDIR . 'backup/yolov3.weights'; |
||
35 | public const DATA_COCO = self::LIBDIR . 'cfg/coco.data'; |
||
36 | public const DATA_IMGNET1k = self::LIBDIR . 'cfg/imagenet1k.data'; |
||
37 | public const DATA_OPNIMG = self::LIBDIR . 'cfg/openimages.data'; |
||
38 | public const DATA_COBIN9k = self::LIBDIR . 'cfg/combine9k.data'; |
||
39 | public const DATA_VOC = self::LIBDIR . 'cfg/voc.data'; |
||
40 | protected const OUTFILE_DIR = __DIR__ . '/../temp/out/'; |
||
41 | public const YOLO4TINY = 4; |
||
42 | public const YOLO3TINY = 3; |
||
43 | public const YOLO3MAIN = 2; |
||
44 | public const YOLO2TINY = 1; |
||
45 | public const YOLOFASTEST = 7; |
||
46 | public const YOLOFASTEST_XL = 8; |
||
47 | public const YOLO_VOC_TINY = 5; |
||
48 | public const MOBILE_NET_V2_LITE_YOLO = 6; |
||
49 | public const MOBILE_NET_V2_VOC = 9; |
||
50 | |||
51 | protected $image, $itme, $net, $outPut, $pathInfo, $rawImage, $temp_name, $dets, $imgInfo; |
||
52 | public $darknetFFI, $meta, $classes, $numBox; |
||
53 | |||
54 | public function __construct($netType = self::YOLO4TINY, $metaData = self::DATA_COCO) { |
||
55 | $this->numBox = FFI::new('int32_t'); |
||
56 | $this->darknetFFI = FFI::load(__DIR__ . '/dn_api_4.h'); |
||
57 | $this->getMeta($metaData); |
||
58 | $this->classes(); |
||
59 | $this->loadNetwork($netType); |
||
60 | } |
||
61 | |||
62 | public function classify($img) { |
||
63 | $this->loadImage($img); |
||
64 | $out = $this->predictImg(); |
||
65 | $res = []; |
||
66 | for ($i = 0; $i < $this->meta->classes; ++$i) { |
||
67 | $res[$i] = (FFI::string($this->meta->names[$i], $out[$i])); |
||
68 | } |
||
69 | return $res; |
||
70 | } |
||
71 | |||
72 | public function detect($img, $remote = false, $thresh = .25, $hier_thresh = .5, $nms = .45) { |
||
73 | $time = microtime(true); |
||
74 | if ($remote) { |
||
75 | $img = $this->img4base64($img); |
||
76 | $this->loadImage($img); |
||
77 | } else { |
||
78 | $this->loadImage($img); |
||
79 | } |
||
80 | |||
81 | $this->imgInfo($img); |
||
82 | $this->predictImg(); |
||
83 | $this->getNetworkBoxes($this->net, $this->image->w, $this->image->h, $thresh, $hier_thresh, null, 0, $this->numBox); |
||
84 | $this->doNmsSort($this->dets, $this->numBox, $this->meta, $nms); |
||
85 | |||
86 | for ($obj = 0; $obj < $this->numBox->cdata; ++$obj) { |
||
|
|||
87 | foreach ($this->classes as $key => $val) { |
||
88 | if ($this->dets[$obj]->prob[$key]) { |
||
89 | $res[] = $this->detectObject($this->dets[$obj], $key, $val); |
||
90 | } |
||
91 | } |
||
92 | } |
||
93 | if ($remote) { |
||
94 | $msg = $this->drawBbox($res); |
||
95 | echo PHP_EOL; |
||
96 | echo "FPS:{$this->fps($time)}".PHP_EOL; |
||
97 | echo "Execution time:" . $this->consumedTime($time) . PHP_EOL; |
||
98 | unlink($img); |
||
99 | $this->freeImage($this->image); |
||
100 | $this->freeDetections($this->dets, $this->numBox); |
||
101 | unset($res); |
||
102 | return $msg; |
||
103 | } else { |
||
104 | $this->drawBbox($res, self::OUTFILE_DIR . $this->imgInfo->name); |
||
105 | unset($res); |
||
106 | } |
||
107 | echo PHP_EOL; |
||
108 | echo "FPS:{$this->fps($time)}".PHP_EOL; |
||
109 | echo "Execution time:" . $this->consumedTime($time) . PHP_EOL; |
||
110 | $this->freeImage($this->image); |
||
111 | $this->freeDetections($this->dets, $this->numBox); |
||
112 | unset($time); |
||
113 | } |
||
114 | |||
115 | public function remotePR($client, $frame, $server = '') { |
||
116 | if ($server !== '') { |
||
117 | $msg = $this->detect($frame->data, true); |
||
118 | $data = ['id' => $frame->fd, 'msg' => $msg]; |
||
119 | $server->push($client, json_encode($data)); |
||
120 | } else { |
||
121 | $msg = $this->detect($frame, true); |
||
122 | $data = ['id' => $client->resourceId, 'msg' => $msg]; |
||
123 | $client->send(json_encode($data)); |
||
124 | } |
||
125 | unset($msg); |
||
126 | unset($data); |
||
127 | } |
||
128 | |||
129 | protected function loadNetwork($yolov) { |
||
130 | switch ($yolov) { |
||
131 | case self::YOLO4TINY: |
||
132 | $this->net = $this->darknetFFI->load_network(self::CFG_TINY_4, self::WEIGHT_TINY_4, 0); |
||
133 | break; |
||
134 | case self::YOLO3TINY: |
||
135 | $this->net = $this->darknetFFI->load_network(self::CFG_TINY_3, self::WEIGHT_TINY_3, 0); |
||
136 | break; |
||
137 | case self::YOLO2TINY; |
||
138 | $this->net = $this->darknetFFI->load_network(self::CFG_TINY_2, self::WEIGHT_TINY_2, 0); |
||
139 | break; |
||
140 | case self::YOLO_VOC_TINY; |
||
141 | $this->net = $this->darknetFFI->load_network(self::CFG_VOC_TINY_2, self::WEIGHT_VOC_TINY_2, 0); |
||
142 | break; |
||
143 | case self::MOBILE_NET_V2_LITE_YOLO; |
||
144 | $this->net = $this->darknetFFI->load_network(self::CFG_MOBILENET_V2_LITE, self::WEIGHT_MOBILENET_V2_LITE, 0); |
||
145 | break; |
||
146 | case self::MOBILE_NET_V2_VOC; |
||
147 | $this->net = $this->darknetFFI->load_network(self::CFG_MOBILENET_V2_VOC, self::WEIGHT_MOBILENET_V2_VOC, 0); |
||
148 | break; |
||
149 | case self::YOLOFASTEST; |
||
150 | $this->net = $this->darknetFFI->load_network(self::CFG_FASTEST_YOLO, self::WEIGHT_FASTEST_YOLO, 0); |
||
151 | break; |
||
152 | case self::YOLOFASTEST_XL; |
||
153 | $this->net = $this->darknetFFI->load_network(self::CFG_FASTEST_YOLO_XL, self::WEIGHT_FASTEST_YOLO_XL, 0); |
||
154 | break; |
||
155 | case self::YOLO3MAIN; |
||
156 | $this->net = $this->darknetFFI->load_network(self::CFG_MAIN, self::WEIGHT_MAIN, 0); |
||
157 | break; |
||
158 | default: |
||
159 | throw new coreException("Not a valid version of yolo!\n"); |
||
160 | break; |
||
161 | } |
||
162 | } |
||
163 | |||
164 | protected function loadImage($imgfile) { |
||
165 | return $this->image = $this->darknetFFI->load_image_color($imgfile, 0, 0); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * [make_image description] |
||
170 | * @param int $w [description] |
||
171 | * @param int $h [description] |
||
172 | * @param int $c [description] |
||
173 | * @return [type] [description] |
||
174 | */ |
||
175 | public function makeImg(int $w, int $h, int $c) { |
||
176 | return $this->darknetFFI->make_image($w, $h, $c); |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * [resize_image description] |
||
181 | * @param FFI\CData $im [image] |
||
182 | * @return [type] [description] |
||
183 | */ |
||
184 | public function resizeImg(FFI\CData $im) { |
||
185 | return $this->darknetFFI->resize_image($im, $this->net->w, $this->net->h); |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * [letterbox_image description] |
||
190 | * @param FFI\CData $im [description] |
||
191 | * @param int $w [description] |
||
192 | * @param int $h [description] |
||
193 | * @return [type] [description] |
||
194 | */ |
||
195 | protected function letterBoxImg(FFI\CData $im, int $w, int $h) { |
||
196 | return $this->darknetFFI->letterbox_image($im, $w, $h); |
||
197 | } |
||
198 | |||
199 | protected function predictImg() { |
||
200 | return $this->darknetFFI->network_predict_image($this->net, $this->image); |
||
201 | } |
||
202 | |||
203 | protected function getMeta($data) { |
||
204 | return $this->meta = $this->darknetFFI->get_metadata($data); |
||
205 | } |
||
206 | |||
207 | protected function classes() { |
||
208 | for ($i = 0; $i < $this->meta->classes; ++$i) { |
||
209 | $this->classes[$i] = \FFI::string($this->meta->names[$i]); |
||
210 | } |
||
211 | return $this->classes; |
||
212 | } |
||
213 | |||
214 | protected function getNetworkBoxes(FFI\CData $net, int $w, int $h, float $thresh, float $hier, $map, int $relative, $num) { |
||
215 | return $this->dets = $this->darknetFFI->get_network_boxes($net, $w, $h, $thresh, $hier, $map, $relative, FFI::addr($num), 0); |
||
216 | } |
||
217 | |||
218 | protected function doNmsSort(FFI\CData $dects, FFI\CData $nmBox, FFI\CData $meta, float $nms) { |
||
219 | return $this->darknetFFI->do_nms_sort($dects, $nmBox->cdata, $meta->classes, $nms); |
||
220 | } |
||
221 | |||
222 | protected function freeImage(FFI\CData $im) { |
||
223 | return $this->darknetFFI->free_image($im); |
||
224 | } |
||
225 | |||
226 | protected function freeDetections(FFI\CData $dets, $num) { |
||
227 | return $this->darknetFFI->free_detections($dets, $num->cdata); |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * [free_network description] |
||
232 | * @return [type] [description] |
||
233 | */ |
||
234 | protected function freeNetwork() { |
||
235 | return $this->darknetFFI->free_network($this->net); |
||
236 | } |
||
237 | |||
238 | protected function detectObject(FFI\CData $det, $key, $val) { |
||
239 | return (object) ['label' => $val, 'confidence' => $det->prob[$key], 'box' => $this->bbox2obj($det->bbox)]; |
||
240 | } |
||
241 | |||
242 | protected function bbox2Obj(FFI\CData $t) { |
||
243 | return (object) ['x' => $t->x, 'y' => $t->y, 'w' => $t->w, 'h' => $t->h]; |
||
244 | } |
||
245 | |||
246 | protected function gbBox(object $b) { |
||
247 | $h = $b->h / 2; |
||
248 | $w = $b->w / 2; |
||
249 | $x = $b->x; |
||
250 | $y = $b->y; |
||
251 | return (object) ['x1' => $x - $w, 'y1' => $y - $h, 'x2' => $x + $w, 'y2' => $y + $h]; |
||
252 | } |
||
253 | |||
254 | protected function drawBbox($inp, $outFile = null) { |
||
255 | $this->rawImage = $this->createImg(); |
||
256 | imagesetthickness($this->rawImage, 2); |
||
257 | if ($inp !== null) { |
||
258 | foreach ($inp as $i) { |
||
259 | $box = $this->gbBox($i->box); |
||
260 | $label = $i->label . '-' . round($i->confidence, 2) . '%'; |
||
261 | switch ($i->label) { |
||
262 | case 'bear': |
||
263 | case 'cat': |
||
264 | case 'cow': |
||
265 | case 'dog': |
||
266 | case 'elephant': |
||
267 | case 'giraffe': |
||
268 | case 'horse': |
||
269 | case 'sheep': |
||
270 | case 'zebra': |
||
271 | $this->truthLabel($box, $label, 'yellow', 'black'); |
||
272 | break; |
||
273 | |||
274 | case 'bird': |
||
275 | $this->truthLabel($box, $label, 'teal', 'white'); |
||
276 | break; |
||
277 | |||
278 | case 'cake': |
||
279 | case 'donut': |
||
280 | case 'pizza': |
||
281 | case 'hot dog': |
||
282 | case 'carrot': |
||
283 | case 'broccoli': |
||
284 | case 'orange': |
||
285 | case 'sandwich': |
||
286 | case 'apple': |
||
287 | case 'banana': |
||
288 | $this->truthLabel($box, $label, 'magenta', 'white'); |
||
289 | break; |
||
290 | |||
291 | case 'toaster': |
||
292 | case 'oven': |
||
293 | case 'microwave': |
||
294 | case 'cell phone': |
||
295 | case 'keyboard': |
||
296 | case 'remote': |
||
297 | case 'mouse': |
||
298 | case 'laptop': |
||
299 | case 'tvmonitor': |
||
300 | case 'refrigerator': |
||
301 | $this->truthLabel($box, $label, 'blue', 'white'); |
||
302 | break; |
||
303 | |||
304 | case 'toothbrush': |
||
305 | case 'hair drier': |
||
306 | case 'vase': |
||
307 | case 'clock': |
||
308 | case 'bottle': |
||
309 | case 'spoon': |
||
310 | case 'cup': |
||
311 | case 'suitcase': |
||
312 | case 'tie': |
||
313 | case 'handbag': |
||
314 | case 'umbrella': |
||
315 | case 'book': |
||
316 | case 'backpack': |
||
317 | case 'wine glass': |
||
318 | case 'fork': |
||
319 | case 'bowl': |
||
320 | case 'knife': |
||
321 | $this->truthLabel($box, $label, 'purple', 'white'); |
||
322 | break; |
||
323 | |||
324 | case 'diningtable': |
||
325 | case 'bed': |
||
326 | case 'bench': |
||
327 | case 'sofa': |
||
328 | case 'chair': |
||
329 | case 'sink': |
||
330 | case 'scissors': |
||
331 | $this->truthLabel($box, $label, 'cyan', 'black'); |
||
332 | break; |
||
333 | |||
334 | case 'car': |
||
335 | case 'bus': |
||
336 | case 'boat': |
||
337 | case 'truck': |
||
338 | case 'bicycle': |
||
339 | case 'motorbike': |
||
340 | case 'aeroplane': |
||
341 | $this->truthLabel($box, $label, 'red', 'white'); |
||
342 | break; |
||
343 | case 'person': |
||
344 | $this->truthLabel($box, $label, 'green', 'black'); |
||
345 | break; |
||
346 | |||
347 | case 'skis': |
||
348 | case 'snowboard': |
||
349 | case 'sports ball': |
||
350 | case 'kite': |
||
351 | case 'baseball bat': |
||
352 | case 'baseball glove': |
||
353 | case 'skateboard': |
||
354 | case 'surfboard': |
||
355 | case 'tennis racket': |
||
356 | case 'teddy bear': |
||
357 | $this->truthLabel($box, $label, 'purple', 'white'); |
||
358 | break; |
||
359 | |||
360 | case 'traffic light': |
||
361 | case 'fire hydrant': |
||
362 | case 'stop sign': |
||
363 | case 'parking meter': |
||
364 | $this->truthLabel($box, $label, 'blueViolet', 'white'); |
||
365 | break; |
||
366 | |||
367 | default : |
||
368 | $this->truthLabel($box, $label, 'black', 'white'); |
||
369 | break; |
||
370 | } |
||
371 | } |
||
372 | } else { |
||
373 | imagestring($this->rawImage, 5, 0, 20, "NULL [ Accuracy:- 00.00% ]", $this->color('black')); |
||
374 | } |
||
375 | if (is_null($outFile)) { |
||
376 | return $this->img64Encode(); |
||
377 | } else { |
||
378 | imagejpeg($this->rawImage, $outFile); |
||
379 | } |
||
380 | imagedestroy($this->rawImage); |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | * [color description] |
||
385 | * @param string $Colorname [description] |
||
386 | * @return [type] [description] |
||
387 | */ |
||
388 | protected function color($Colorname = 'yellow') { |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * [load_file description] |
||
472 | * @param [type] $filename [description] |
||
473 | * @return [type] [description] |
||
474 | */ |
||
475 | protected function createImg() { |
||
495 | } |
||
496 | |||
497 | public function img4base64($url) { |
||
498 | $url64 = $this->base64ImgDecode($url); |
||
499 | if (!empty($url64)) { |
||
500 | $im = imagecreatefromstring($url64); |
||
501 | imagejpeg($im, __DIR__ . '/../temp/in/' . $this->tempImgName() . '.jpg', 100); |
||
502 | imagedestroy($im); |
||
503 | return __DIR__ . '/../temp/in/' . $this->temp_name . '.jpg'; |
||
504 | } else { |
||
505 | return false; |
||
506 | } |
||
507 | } |
||
508 | |||
509 | public function base64ImgDecode($url) { |
||
510 | if ($url == 'data:,') { |
||
511 | return null; |
||
512 | } else { |
||
513 | $data = str_replace("data:image/webp;base64", "", $url); |
||
514 | return base64_decode($data); |
||
515 | } |
||
516 | } |
||
517 | |||
518 | protected function img64Encode() { |
||
519 | ob_start(); |
||
520 | imagewebp($this->rawImage, null, 100); |
||
521 | $res = ob_get_contents(); |
||
522 | imagedestroy($this->rawImage); |
||
523 | ob_end_clean(); |
||
524 | return "data:image/webp;base64," . base64_encode($res); |
||
525 | } |
||
526 | |||
527 | /** |
||
528 | * [temp_imgName description] |
||
529 | * @return [type] [description] |
||
530 | */ |
||
531 | protected function tempImgName() { |
||
532 | return $this->temp_name = ++$this->temp_name; |
||
533 | } |
||
534 | |||
535 | protected function consumedTime($startTime) { |
||
537 | } |
||
538 | |||
539 | protected function fps($startTime) { |
||
540 | return (1.0/(microtime(true) - $startTime)); |
||
541 | } |
||
542 | |||
543 | protected function imgInfo($img) { |
||
544 | list($w, $h) = getimagesize($img); |
||
545 | $info = pathinfo($img); |
||
546 | return $this->imgInfo = (object) ['w' => $w, 'h' => $h, 'name' => $info['basename'], 'type' => $info['extension'], 'dir' => $info['dirname']]; |
||
547 | } |
||
548 | |||
549 | protected function imgResizeGD($img, $w = 416, $h = 416) { |
||
550 | $ratio_orig = $this->image->w / $this->image->h; |
||
551 | if ($w / $h > $ratio_orig) { |
||
552 | $w = $h * $ratio_orig; |
||
553 | } else { |
||
554 | $h = $w / $ratio_orig; |
||
555 | } |
||
556 | |||
557 | $image_p = imagecreatetruecolor($w, $h); |
||
558 | $image = imagecreatefromjpeg($img); |
||
559 | imagecopyresampled($image_p, $image, 0, 0, 0, 0, $w, $h, imagesx($img), imagesy($img)); |
||
560 | imagejpeg($image, __DIR__ . '/../temp/in/' . $this->tempImgName() . '.jpg', 100); |
||
561 | imagedestroy($image_p); |
||
562 | imagedestroy($image); |
||
563 | } |
||
564 | |||
565 | protected function truthLabel($box, $label, $bbcolor, $fncolor) { |
||
572 | ; |
||
573 | } |
||
574 | |||
575 | } |
||
576 |