VanFace
Esse commit está contido em:
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use CV\Scalar, CV\Size;
|
||||
use function CV\{imread, imwrite, cvtColor, circle};
|
||||
|
||||
$netDet = \CV\DNN\readNetFromCaffe('models/ssd/res10_300x300_ssd_deploy.prototxt', 'models/ssd/res10_300x300_ssd_iter_140000.caffemodel');
|
||||
$netRecogn = \CV\DNN\readNetFromCaffe('models/VanFace/VanFace.prototxt', 'models/VanFace/VanFace.caffemodel');
|
||||
|
||||
$src = imread("images/faces.jpg");
|
||||
$size = $src->size(); // 2000x500
|
||||
|
||||
$minSide = min($size->width, $size->height);
|
||||
$divider = $minSide / 300;
|
||||
\CV\resize($src, $resized, new Size($size->width / $divider, $size->height / $divider)); // 1200x300
|
||||
|
||||
//var_export($resized);
|
||||
|
||||
$blob = \CV\DNN\blobFromImage($resized, 1, new Size(), new Scalar(104, 177, 123), true, false);
|
||||
|
||||
$netDet->setInput($blob);
|
||||
|
||||
$r = $netDet->forward();
|
||||
|
||||
//var_export($r->shape);
|
||||
|
||||
$faces = [];
|
||||
$scalar = new Scalar(0, 0, 255);
|
||||
for ($i = 0; $i < $r->shape[2]; $i++) {
|
||||
$confidence = $r->atIdx([0,0,$i,2]);
|
||||
if ($confidence > 0.9) {
|
||||
var_export($confidence);echo "\n";
|
||||
$startX = $r->atIdx([0,0,$i,3]) * $src->cols;
|
||||
$startY = $r->atIdx([0,0,$i,4]) * $src->rows;
|
||||
$endX = $r->atIdx([0,0,$i,5]) * $src->cols;
|
||||
$endY = $r->atIdx([0,0,$i,6]) * $src->rows;
|
||||
|
||||
$face = $src->getImageROI(new \CV\Rect($startX, $startY, $endX - $startX, $endY - $startY));
|
||||
\CV\resize($face, $resized, new Size(60,60));
|
||||
$resized = cvtColor($resized, \CV\COLOR_BGR2GRAY, 2);
|
||||
\CV\meanStdDev($resized, $mean, $sdv);
|
||||
|
||||
$m = $mean->data()[0];
|
||||
$s = $sdv->data()[0];
|
||||
|
||||
$blob = \CV\DNN\blobFromImage($resized, 1 / (0.000001 + $s), new Size(60,60), new Scalar($m, $m, $m));
|
||||
$netRecogn->setInput($blob);
|
||||
//var_export($blob);die();
|
||||
$out = $netRecogn->forward();
|
||||
$data = $out->data();
|
||||
|
||||
for ($j=0;$j<68;$j++) {
|
||||
$point = new \CV\Point($startX + $data[$j*2] * $face->cols, $startY + $data[$j*2+1] * $face->rows);
|
||||
circle($src, $point, 2, new Scalar(0, 0, 255), 2);
|
||||
//var_export($point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imwrite("results/_detect_facemarks_by_dnn_vanface.jpg", $src);
|
||||
@@ -10,3 +10,4 @@ Sources:
|
||||
* ssdlite_mobilenet_v2_coco - https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
|
||||
* ssd_mobilenet_v2_coco - https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
|
||||
* insightface - https://github.com/axinc-ai/ailia-models/tree/master/face_identification/insightface
|
||||
* VanFace - https://github.com/lsy17096535/face-landmark
|
||||
|
||||
Arquivo binário não exibido.
@@ -0,0 +1,290 @@
|
||||
name: "landmark"
|
||||
input: "data"
|
||||
input_dim: 1
|
||||
input_dim: 1
|
||||
input_dim: 60
|
||||
input_dim: 60
|
||||
########################################
|
||||
# the actual net
|
||||
# layer 1
|
||||
layer {
|
||||
name: "Conv1"
|
||||
type: "Convolution"
|
||||
bottom: "data"
|
||||
top: "Conv1"
|
||||
param {
|
||||
lr_mult: 1
|
||||
decay_mult: 1
|
||||
}
|
||||
param {
|
||||
lr_mult: 2
|
||||
decay_mult: 0
|
||||
}
|
||||
convolution_param {
|
||||
num_output: 20
|
||||
pad: 2
|
||||
kernel_size: 5
|
||||
stride: 1
|
||||
weight_filler {
|
||||
type: "xavier"
|
||||
std: 0.1
|
||||
}
|
||||
bias_filler {
|
||||
type: "constant"
|
||||
value: 0.2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationTangH1"
|
||||
bottom: "Conv1"
|
||||
top: "ActivationTangH1"
|
||||
type: "TanH"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationAbs1"
|
||||
bottom: "ActivationTangH1"
|
||||
top: "Abs1"
|
||||
type: "AbsVal"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "Pool1"
|
||||
type: "Pooling"
|
||||
bottom: "Abs1"
|
||||
top: "Pool1"
|
||||
pooling_param {
|
||||
pool: MAX
|
||||
kernel_size: 2
|
||||
stride: 2
|
||||
}
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "Conv2"
|
||||
type: "Convolution"
|
||||
bottom: "Pool1"
|
||||
top: "Conv2"
|
||||
param {
|
||||
lr_mult: 1
|
||||
decay_mult: 1
|
||||
}
|
||||
param {
|
||||
lr_mult: 2
|
||||
decay_mult: 0
|
||||
}
|
||||
convolution_param {
|
||||
num_output: 48
|
||||
pad: 2
|
||||
kernel_size: 5
|
||||
stride: 1
|
||||
weight_filler {
|
||||
type: "xavier"
|
||||
std: 0.1
|
||||
}
|
||||
bias_filler {
|
||||
type: "constant"
|
||||
value: 0.2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationTangH2"
|
||||
bottom: "Conv2"
|
||||
top: "ActivationTangH2"
|
||||
type: "TanH"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationAbs2"
|
||||
bottom: "ActivationTangH2"
|
||||
top: "Abs2"
|
||||
type: "AbsVal"
|
||||
}
|
||||
|
||||
|
||||
layer {
|
||||
name: "Pool2"
|
||||
type: "Pooling"
|
||||
bottom: "Abs2"
|
||||
top: "Pool2"
|
||||
pooling_param {
|
||||
pool: MAX
|
||||
kernel_size: 2
|
||||
stride: 2
|
||||
}
|
||||
}
|
||||
|
||||
# layer 3
|
||||
layer {
|
||||
name: "Conv3"
|
||||
type: "Convolution"
|
||||
bottom: "Pool2"
|
||||
top: "Conv3"
|
||||
param {
|
||||
lr_mult: 1
|
||||
decay_mult: 1
|
||||
}
|
||||
param {
|
||||
lr_mult: 2
|
||||
decay_mult: 0
|
||||
}
|
||||
convolution_param {
|
||||
num_output: 64
|
||||
pad: 0
|
||||
kernel_size: 3
|
||||
stride: 1
|
||||
weight_filler {
|
||||
type: "xavier"
|
||||
std: 0.1
|
||||
}
|
||||
bias_filler {
|
||||
type: "constant"
|
||||
value: 0.2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layer {
|
||||
name: "ActivationTangH3"
|
||||
bottom: "Conv3"
|
||||
top: "ActivationTangH3"
|
||||
type: "TanH"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationAbs3"
|
||||
bottom: "ActivationTangH3"
|
||||
top: "Abs3"
|
||||
type: "AbsVal"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "Pool3"
|
||||
type: "Pooling"
|
||||
bottom: "Abs3"
|
||||
top: "Pool3"
|
||||
pooling_param {
|
||||
pool: MAX
|
||||
kernel_size: 3
|
||||
stride: 2
|
||||
}
|
||||
}
|
||||
|
||||
# layer 4
|
||||
layer {
|
||||
name: "Conv4"
|
||||
type: "Convolution"
|
||||
bottom: "Pool3"
|
||||
top: "Conv4"
|
||||
param {
|
||||
lr_mult: 1
|
||||
decay_mult: 1
|
||||
}
|
||||
param {
|
||||
lr_mult: 2
|
||||
decay_mult: 0
|
||||
}
|
||||
convolution_param {
|
||||
num_output: 80
|
||||
pad: 0
|
||||
kernel_size: 3
|
||||
stride: 1
|
||||
weight_filler {
|
||||
type: "xavier"
|
||||
std: 0.1
|
||||
}
|
||||
bias_filler {
|
||||
type: "constant"
|
||||
value: 0.2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layer {
|
||||
name: "ActivationTangH4"
|
||||
bottom: "Conv4"
|
||||
top: "ActivationTangH4"
|
||||
type: "TanH"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationAbs4"
|
||||
bottom: "ActivationTangH4"
|
||||
top: "Abs4"
|
||||
type: "AbsVal"
|
||||
}
|
||||
|
||||
|
||||
########################################
|
||||
|
||||
layer {
|
||||
name: "Dense1"
|
||||
type: "InnerProduct"
|
||||
bottom: "Abs4"
|
||||
top: "Dense1"
|
||||
param {
|
||||
lr_mult: 1
|
||||
decay_mult: 1
|
||||
}
|
||||
param {
|
||||
lr_mult: 2
|
||||
decay_mult: 0
|
||||
}
|
||||
inner_product_param {
|
||||
num_output: 512
|
||||
weight_filler {
|
||||
type: "xavier"
|
||||
}
|
||||
bias_filler {
|
||||
type: "constant"
|
||||
value: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layer {
|
||||
name: "ActivationTangH5"
|
||||
bottom: "Dense1"
|
||||
top: "ActivationTangH5"
|
||||
type: "TanH"
|
||||
}
|
||||
|
||||
layer {
|
||||
name: "ActivationAbs5"
|
||||
bottom: "ActivationTangH5"
|
||||
top: "Abs5"
|
||||
type: "AbsVal"
|
||||
}
|
||||
|
||||
|
||||
layer {
|
||||
name: "Dense3"
|
||||
type: "InnerProduct"
|
||||
bottom: "Abs5"
|
||||
top: "Dense3"
|
||||
param {
|
||||
lr_mult: 1
|
||||
decay_mult: 1
|
||||
}
|
||||
param {
|
||||
lr_mult: 2
|
||||
decay_mult: 0
|
||||
}
|
||||
inner_product_param {
|
||||
num_output: 136
|
||||
weight_filler {
|
||||
type: "xavier"
|
||||
}
|
||||
bias_filler {
|
||||
type: "constant"
|
||||
value: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 292 KiB |
Referência em uma Nova Issue
Bloquear um usuário