|
| 1 | +<?php |
| 2 | + |
| 3 | +use CV\Scalar, CV\Size; |
| 4 | +use function CV\{imread, imwrite, rectangle}; |
| 5 | + |
| 6 | +$netDet = \CV\DNN\readNetFromCaffe('models/ssd/res10_300x300_ssd_deploy.prototxt', 'models/ssd/res10_300x300_ssd_iter_140000.caffemodel'); |
| 7 | +$netRecogn = \CV\DNN\readNetFromTorch('models/openface/openface.nn4.small2.v1.t7'); |
| 8 | + |
| 9 | +$image2faces = function ($src) use ($netDet) { |
| 10 | + $size = $src->size(); // 2000x500 |
| 11 | + |
| 12 | + $minSide = min($size->width, $size->height); |
| 13 | + $divider = $minSide / 300; |
| 14 | + \CV\resize($src, $resized, new Size($size->width / $divider, $size->height / $divider)); // 1200x300 |
| 15 | + //var_export($resized); |
| 16 | + $blob = \CV\DNN\blobFromImage($resized, 1, new Size(), new Scalar(104, 177, 123), true, false); |
| 17 | + |
| 18 | + $netDet->setInput($blob); |
| 19 | + $r = $netDet->forward(); |
| 20 | + |
| 21 | + //var_export($r->shape); |
| 22 | + |
| 23 | + $faces = []; |
| 24 | + |
| 25 | + for ($i = 0; $i < $r->shape[2]; $i++) { |
| 26 | + $confidence = $r->atIdx([0,0,$i,2]); |
| 27 | + if ($confidence > 0.9) { |
| 28 | + //var_export($confidence);echo "\n"; |
| 29 | + $startX = $r->atIdx([0,0,$i,3]) * $src->cols; |
| 30 | + $startY = $r->atIdx([0,0,$i,4]) * $src->rows; |
| 31 | + $endX = $r->atIdx([0,0,$i,5]) * $src->cols; |
| 32 | + $endY = $r->atIdx([0,0,$i,6]) * $src->rows; |
| 33 | + |
| 34 | + $faces[] = $src->getImageROI(new \CV\Rect($startX, $startY, $endX - $startX, $endY - $startY)); |
| 35 | + } |
| 36 | + } |
| 37 | + |
| 38 | + return $faces; |
| 39 | +}; |
| 40 | + |
| 41 | +$face2vec = function ($face) use ($netRecogn) { |
| 42 | + $blob = \CV\DNN\blobFromImage($face, 1.0 / 255, new Size(96, 96), new Scalar(), true, false); |
| 43 | + $netRecogn->setInput($blob); |
| 44 | + return $netRecogn->forward(); |
| 45 | +}; |
| 46 | + |
| 47 | +function faceDistance($face1, $face2) { |
| 48 | + $distance = 0; |
| 49 | + foreach ($face1 as $i => $v) { |
| 50 | + $distance += ($face1[$i] - $face2[$i])**2; |
| 51 | + } |
| 52 | + return sqrt($distance); |
| 53 | +} |
| 54 | + |
| 55 | +$src = imread("images/faces.jpg"); |
| 56 | + |
| 57 | +$faces = $image2faces($src); |
| 58 | + |
| 59 | +$faceVectors = []; |
| 60 | +foreach ($faces as $i => $face) { |
| 61 | + $vec = $face2vec($face); |
| 62 | + //imwrite("results/_face.jpg", $face); |
| 63 | + |
| 64 | + //$vec->print(); |
| 65 | + //var_export($vec->data()); |
| 66 | + $faceVectors["me$i"] = $vec->data(); |
| 67 | +} |
| 68 | + |
| 69 | +$src = imread("images/angelina_faces.png"); |
| 70 | + |
| 71 | +$faces = $image2faces($src); |
| 72 | + |
| 73 | +foreach ($faces as $i => $face) { |
| 74 | + $vec = $face2vec($face); |
| 75 | + //imwrite("results/_face.jpg", $face); |
| 76 | + |
| 77 | + //$vec->print(); |
| 78 | + //var_export($vec->data()); |
| 79 | + $faceVectors["angelina$i"] = $vec->data(); |
| 80 | +} |
| 81 | + |
| 82 | +//var_export($faceVectors); |
| 83 | + |
| 84 | +$src = imread("images/angelina_and_me.png"); |
| 85 | + |
| 86 | +$faces = $image2faces($src); |
| 87 | + |
| 88 | +foreach ($faces as $i => $face) { |
| 89 | + $vec = $face2vec($face); |
| 90 | + $minDistance = 0; |
| 91 | + $faceLabel = ''; |
| 92 | + foreach ($faceVectors as $label => $faceVector) { |
| 93 | + $distance = faceDistance($vec->data(), $faceVector); |
| 94 | + |
| 95 | + if (!$minDistance || $distance < $minDistance) { |
| 96 | + $minDistance = $distance; |
| 97 | + $faceLabel = $label; |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + echo "face$i $faceLabel $minDistance\n"; |
| 102 | +} |
0 commit comments