提交 668d6c74 编写于 作者: Eric.Lee2021's avatar Eric.Lee2021 🚴🏻

add face au

上级 d551c7bb
......@@ -28,6 +28,7 @@ import shutil
from face_detect.yolo_v3_face import yolo_v3_face_model
from face_multi_task.face_multi_task_component import FaceMuitiTask_Model
from face_euler_angle.face_euler_angle_component import FaceAngle_Model
from face_au.face_au_c import FaceAu_Model
# 加载工具库
import sys
sys.path.append("./lib/face_bioassay_lib/")
......@@ -47,6 +48,8 @@ def main_face_bioassay(video_path,cfg_file):
face_euler_model = FaceAngle_Model(model_path = config["face_euler_model_path"])
face_au_model = FaceAu_Model(model_path = config["face_au_model_path"])
cap = cv2.VideoCapture(video_path)
frame_idx = 0
while cap.isOpened():
......@@ -58,9 +61,10 @@ def main_face_bioassay(video_path,cfg_file):
faces_bboxes =face_detect_model.predict(img,vis = False) # 检测手,获取手的边界框
faces_message = get_faces_batch_attribute(
face_multitask_model,face_euler_model,faces_bboxes,img,use_cuda = True,vis = True)
face_multitask_model,face_euler_model,face_au_model,faces_bboxes,img,use_cuda = True,vis = True)
if faces_message is not None:
print("faces_message : {} \n".format(faces_message))
pass
cv2.namedWindow("DriverFatigueMonitor",0)
cv2.imshow("DriverFatigueMonitor",img)
......
#-*-coding:utf-8-*-
# date:2021-03-09
# Author: Eric.Lee
# function: handpose_x 21 keypoints 2D
import os
import torch
import cv2
import numpy as np
import json
import torch
import torch.nn as nn
import time
import math
from datetime import datetime
from face_au.models.resnet import resnet18, resnet34, resnet50, resnet101
from face_au.models.mobilenetv2 import MobileNetV2
#
class FaceAu_Model(object):
def __init__(self,
model_path = './components/face_au/weights/face_au-resnet50-size256-20210427.pth',
img_size= 256,
num_classes = 24,
model_arch = "resnet_50",
):
# print("face au loading : ",model_path)
self.use_cuda = torch.cuda.is_available()
self.device = torch.device("cuda:0" if self.use_cuda else "cpu") # 可选的设备类型及序号
self.img_size = img_size
#-----------------------------------------------------------------------
if model_arch == 'resnet_50':
model_ = resnet50(num_classes = num_classes,img_size = self.img_size)
elif model_arch == 'resnet_18':
model_ = resnet18(num_classes = num_classes,img_size = self.img_size)
elif model_arch == 'resnet_34':
model_ = resnet34(num_classes = num_classes,img_size = self.img_size)
elif model_arch == 'resnet_101':
model_ = resnet101(num_classes = num_classes,img_size = self.img_size)
#-----------------------------------------------------------------------
model_ = model_.to(self.device)
# 加载测试模型
if os.access(model_path,os.F_OK):# checkpoint
chkpt = torch.load(model_path, map_location=self.device)
model_.load_state_dict(chkpt)
print('face au model loading : {}'.format(model_path))
model_.eval() # 设置为前向推断模式
self.model_au = model_
def predict(self, img, vis = False):
with torch.no_grad():
# img_ = img_ - [123.67, 116.28, 103.53]
img_ = torch.from_numpy(img)
# img_ = img_.unsqueeze_(0)
if self.use_cuda:
img_ = img_.cuda() # (bs, 3, h, w)
output_ = self.model_au(img_.float())
# print(pre_.size())
output_ = output_.cpu().detach().numpy()
return output_
import torch
import torch.nn as nn
import math
# A PyTorch implementation of MobileNet V2 architecture and pretrained model.
# from https://github.com/tonylins/pytorch-mobilenet-v2
def conv_bn(inp, oup, stride):
return nn.Sequential(
nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
nn.BatchNorm2d(oup),
nn.ReLU6(inplace=True)
)
def conv_1x1_bn(inp, oup):
return nn.Sequential(
nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
nn.ReLU6(inplace=True)
)
class InvertedResidual(nn.Module):
def __init__(self, inp, oup, stride, expand_ratio):
super(InvertedResidual, self).__init__()
self.stride = stride
assert stride in [1, 2]
hidden_dim = round(inp * expand_ratio)
self.use_res_connect = self.stride == 1 and inp == oup
if expand_ratio == 1:
self.conv = nn.Sequential(
# dw
nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
nn.BatchNorm2d(hidden_dim),
nn.ReLU6(inplace=True),
# pw-linear
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
else:
self.conv = nn.Sequential(
# pw
nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
nn.BatchNorm2d(hidden_dim),
nn.ReLU6(inplace=True),
# dw
nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
nn.BatchNorm2d(hidden_dim),
nn.ReLU6(inplace=True),
# pw-linear
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
def forward(self, x):
if self.use_res_connect:
return x + self.conv(x)
else:
return self.conv(x)
class MobileNetV2(nn.Module):
def __init__(self, n_class=1000, input_size=224,dropout_factor=0.5, width_mult=1.):
super(MobileNetV2, self).__init__()
block = InvertedResidual
input_channel = 32
last_channel = 1280
self.dropout_factor = dropout_factor
self.dropout = nn.Dropout(self.dropout_factor)
interverted_residual_setting = [
# t, c, n, s
[1, 16, 1, 1],
[6, 24, 2, 2],
[6, 32, 3, 2],
[6, 64, 4, 2],
[6, 96, 3, 1],
[6, 160, 3, 2],
[6, 320, 1, 1],
]
# building first layer
assert input_size % 32 == 0
input_channel = int(input_channel * width_mult)
self.last_channel = int(last_channel * width_mult) if width_mult > 1.0 else last_channel
self.features = [conv_bn(3, input_channel, 2)]
# building inverted residual blocks
for t, c, n, s in interverted_residual_setting:
output_channel = int(c * width_mult)
for i in range(n):
if i == 0:
self.features.append(block(input_channel, output_channel, s, expand_ratio=t))
else:
self.features.append(block(input_channel, output_channel, 1, expand_ratio=t))
input_channel = output_channel
# building last several layers
self.features.append(conv_1x1_bn(input_channel, self.last_channel))
# make it nn.Sequential
self.features = nn.Sequential(*self.features)
# building classifier
self.classifier = nn.Sequential(
# nn.Dropout(0.2),
nn.Linear(self.last_channel, n_class),
)
self._initialize_weights()
def forward(self, x):
x = self.features(x)
# print("1 x.size()", x.size()) # bs,1280,7,7
x = x.mean(3).mean(2)
# print("2 x.size()", x.size()) # bs,1280
x = self.dropout(x)
x = self.classifier(x)
# print("3 x.size()", x.size()) # bs,num_classes
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
n = m.weight.size(1)
m.weight.data.normal_(0, 0.01)
m.bias.data.zero_()
if __name__ == "__main__":
img = torch.rand((9, 3, 160, 160))
net = MobileNetV2(n_class=120)
print(net)
print("***"*50)
pred = net(img)
print(pred.size())
import torch
import torch.nn as nn
import math
import torch.utils.model_zoo as model_zoo
__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',
'resnet152']
model_urls = {
'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
}
def conv3x3(in_planes, out_planes, stride=1):
"""3x3 convolution with padding"""
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
padding=1, bias=False)
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None):
super(BasicBlock, self).__init__()
self.conv1 = conv3x3(inplanes, planes, stride)
self.bn1 = nn.BatchNorm2d(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = conv3x3(planes, planes)
self.bn2 = nn.BatchNorm2d(planes)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
residual = self.downsample(x)
out += residual
out = self.relu(out)
return out
class Bottleneck(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, stride=1, downsample=None):
super(Bottleneck, self).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(planes)
self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
self.bn3 = nn.BatchNorm2d(planes * 4)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out = self.relu(out)
out = self.conv3(out)
out = self.bn3(out)
if self.downsample is not None:
residual = self.downsample(x)
out += residual
out = self.relu(out)
return out
class ResNet(nn.Module):
def __init__(self, block, layers, num_classes=1000, img_size=224,dropout_factor = 1.):
self.inplanes = 64
self.dropout_factor = dropout_factor
super(ResNet, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
# see this issue: https://github.com/xxradon/PytorchToCaffe/issues/16
# self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
self.layer1 = self._make_layer(block, 64, layers[0])
self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
assert img_size % 32 == 0
pool_kernel = int(img_size / 32)
self.avgpool = nn.AvgPool2d(pool_kernel, stride=1, ceil_mode=True)
self.dropout = nn.Dropout(self.dropout_factor)
self.fc = nn.Linear(512 * block.expansion, num_classes)
for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
def _make_layer(self, block, planes, blocks, stride=1):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
nn.Conv2d(self.inplanes, planes * block.expansion,
kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(planes * block.expansion),
)
layers = []
layers.append(block(self.inplanes, planes, stride, downsample))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes))
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
x = self.dropout(x)
x = self.fc(x)
return x
def load_model(model, pretrained_state_dict):
model_dict = model.state_dict()
pretrained_dict = {k: v for k, v in pretrained_state_dict.items() if
k in model_dict and model_dict[k].size() == pretrained_state_dict[k].size()}
model.load_state_dict(pretrained_dict, strict=False)
if len(pretrained_dict) == 0:
print("[INFO] No params were loaded ...")
else:
for k, v in pretrained_state_dict.items():
if k in pretrained_dict:
print("==>> Load {} {}".format(k, v.size()))
else:
print("[INFO] Skip {} {}".format(k, v.size()))
return model
def resnet18(pretrained=False, **kwargs):
"""Constructs a ResNet-18 model.
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet
"""
model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)
if pretrained:
# model.load_state_dict(model_zoo.load_url(model_urls['resnet18']))
print("Load pretrained model from {}".format(model_urls['resnet18']))
pretrained_state_dict = model_zoo.load_url(model_urls['resnet18'])
model = load_model(model, pretrained_state_dict)
return model
def resnet34(pretrained=False, **kwargs):
"""Constructs a ResNet-34 model.
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet
"""
model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs)
if pretrained:
# model.load_state_dict(model_zoo.load_url(model_urls['resnet34']))
print("Load pretrained model from {}".format(model_urls['resnet34']))
pretrained_state_dict = model_zoo.load_url(model_urls['resnet34'])
model = load_model(model, pretrained_state_dict)
return model
def resnet50(pretrained=False, **kwargs):
"""Constructs a ResNet-50 model.
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet
"""
model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs)
if pretrained:
# model.load_state_dict(model_zoo.load_url(model_urls['resnet50']))
print("Load pretrained model from {}".format(model_urls['resnet50']))
pretrained_state_dict = model_zoo.load_url(model_urls['resnet50'])
model = load_model(model, pretrained_state_dict)
return model
def resnet101(pretrained=False, **kwargs):
"""Constructs a ResNet-101 model.
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet
"""
model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs)
if pretrained:
# model.load_state_dict(model_zoo.load_url(model_urls['resnet101']))
print("Load pretrained model from {}".format(model_urls['resnet101']))
pretrained_state_dict = model_zoo.load_url(model_urls['resnet101'])
model = load_model(model, pretrained_state_dict)
return model
def resnet152(pretrained=False, **kwargs):
"""Constructs a ResNet-152 model.
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet
"""
model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs)
if pretrained:
# model.load_state_dict(model_zoo.load_url(model_urls['resnet152']))
print("Load pretrained model from {}".format(model_urls['resnet152']))
pretrained_state_dict = model_zoo.load_url(model_urls['resnet152'])
model = load_model(model, pretrained_state_dict)
return model
if __name__ == "__main__":
input = torch.randn([32, 3, 256,256])
model = resnet34(False, num_classes=2, img_size=256)
output = model(input)
print(output.size())
#-*-coding:utf-8-*-
# date:2020-04-11
# Author: Eric.Lee
# function: common utils
import os
import shutil
import cv2
import numpy as np
import json
def mkdir_(path, flag_rm=False):
if os.path.exists(path):
if flag_rm == True:
shutil.rmtree(path)
os.mkdir(path)
print('remove {} done ~ '.format(path))
else:
os.mkdir(path)
def plot_box(bbox, img, color=None, label=None, line_thickness=None):
tl = line_thickness or round(0.002 * max(img.shape[0:2])) + 1
color = color or [random.randint(0, 255) for _ in range(3)]
c1, c2 = (int(bbox[0]), int(bbox[1])), (int(bbox[2]), int(bbox[3]))
cv2.rectangle(img, c1, c2, color, thickness=tl)# 目标的bbox
if label:
tf = max(tl - 2, 1)
t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0] # label size
c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3 # 字体的bbox
cv2.rectangle(img, c1, c2, color, -1) # label 矩形填充
# 文本绘制
cv2.putText(img, label, (c1[0], c1[1] - 2), 0, tl / 4, [225, 255, 255],thickness=tf, lineType=cv2.LINE_AA)
class JSON_Encoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
elif isinstance(obj, np.floating):
return float(obj)
elif isinstance(obj, np.ndarray):
return obj.tolist()
else:
return super(JSON_Encoder, self).default(obj)
def draw_landmarks(img,output,draw_circle):
img_width = img.shape[1]
img_height = img.shape[0]
dict_landmarks = {}
for i in range(int(output.shape[0]/2)):
x = output[i*2+0]*float(img_width)
y = output[i*2+1]*float(img_height)
if 41>= i >=33:
if 'left_eyebrow' not in dict_landmarks.keys():
dict_landmarks['left_eyebrow'] = []
dict_landmarks['left_eyebrow'].append([int(x),int(y),(0,255,0)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (0,255,0),-1)
elif 50>= i >=42:
if 'right_eyebrow' not in dict_landmarks.keys():
dict_landmarks['right_eyebrow'] = []
dict_landmarks['right_eyebrow'].append([int(x),int(y),(0,255,0)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (0,255,0),-1)
elif 67>= i >=60:
if 'left_eye' not in dict_landmarks.keys():
dict_landmarks['left_eye'] = []
dict_landmarks['left_eye'].append([int(x),int(y),(255,0,255)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (255,0,255),-1)
elif 75>= i >=68:
if 'right_eye' not in dict_landmarks.keys():
dict_landmarks['right_eye'] = []
dict_landmarks['right_eye'].append([int(x),int(y),(255,0,255)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (255,0,255),-1)
elif 97>= i >=96:
cv2.circle(img, (int(x),int(y)), 2, (0,0,255),-1)
elif 54>= i >=51:
if 'bridge_nose' not in dict_landmarks.keys():
dict_landmarks['bridge_nose'] = []
dict_landmarks['bridge_nose'].append([int(x),int(y),(0,170,255)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (0,170,255),-1)
elif 32>= i >=0:
if 'basin' not in dict_landmarks.keys():
dict_landmarks['basin'] = []
dict_landmarks['basin'].append([int(x),int(y),(255,30,30)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (255,30,30),-1)
elif 59>= i >=55:
if 'wing_nose' not in dict_landmarks.keys():
dict_landmarks['wing_nose'] = []
dict_landmarks['wing_nose'].append([int(x),int(y),(0,255,255)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (0,255,255),-1)
elif 87>= i >=76:
if 'out_lip' not in dict_landmarks.keys():
dict_landmarks['out_lip'] = []
dict_landmarks['out_lip'].append([int(x),int(y),(255,255,0)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (255,255,0),-1)
elif 95>= i >=88:
if 'in_lip' not in dict_landmarks.keys():
dict_landmarks['in_lip'] = []
dict_landmarks['in_lip'].append([int(x),int(y),(50,220,255)])
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (50,220,255),-1)
else:
if draw_circle:
cv2.circle(img, (int(x),int(y)), 2, (255,0,255),-1)
return dict_landmarks
def draw_contour(image,dict):
for key in dict.keys():
# print(key)
_,_,color = dict[key][0]
if 'basin' == key or 'wing_nose' == key:
pts = np.array([[dict[key][i][0],dict[key][i][1]] for i in range(len(dict[key]))],np.int32)
# print(pts)
cv2.polylines(image,[pts],False,color)
else:
points_array = np.zeros((1,len(dict[key]),2),dtype = np.int32)
for i in range(len(dict[key])):
x,y,_ = dict[key][i]
points_array[0,i,0] = x
points_array[0,i,1] = y
# cv2.fillPoly(image, points_array, color)
cv2.drawContours(image,points_array,-1,color,thickness=1)
#-*-coding:utf-8-*-
# date:2020-04-11
# Author: Eric.Lee
# function: model utils
import os
import numpy as np
import torch
import torch.backends.cudnn as cudnn
import random
def get_acc(output, label):
total = output.shape[0]
_, pred_label = output.max(1)
num_correct = (pred_label == label).sum().item()
return num_correct / float(total)
def set_learning_rate(optimizer, lr):
for param_group in optimizer.param_groups:
param_group['lr'] = lr
def set_seed(seed = 666):
np.random.seed(seed)
random.seed(seed)
torch.manual_seed(seed)
if torch.cuda.is_available():
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
cudnn.deterministic = True
def split_trainval_datasets(ops):
print(' --------------->>> split_trainval_datasets ')
train_split_datasets = []
train_split_datasets_label = []
val_split_datasets = []
val_split_datasets_label = []
for idx,doc in enumerate(sorted(os.listdir(ops.train_path), key=lambda x:int(x.split('.')[0]), reverse=False)):
# print(' %s label is %s \n'%(doc,idx))
data_list = os.listdir(ops.train_path+doc)
random.shuffle(data_list)
cal_split_num = int(len(data_list)*ops.val_factor)
for i,file in enumerate(data_list):
if '.jpg' in file:
if i < cal_split_num:
val_split_datasets.append(ops.train_path+doc + '/' + file)
val_split_datasets_label.append(idx)
else:
train_split_datasets.append(ops.train_path+doc + '/' + file)
train_split_datasets_label.append(idx)
print(ops.train_path+doc + '/' + file,idx)
print('\n')
print('train_split_datasets len {}'.format(len(train_split_datasets)))
print('val_split_datasets len {}'.format(len(val_split_datasets)))
return train_split_datasets,train_split_datasets_label,val_split_datasets,val_split_datasets_label
......@@ -163,7 +163,6 @@ def draw_contour(image,dict,vis = False):
if vis:
cv2.drawContours(image,points_array,-1,color,thickness=2)
def plot_box(x, img, color=None, label=None, line_thickness=None):
# Plots one bounding box on image img
tl = line_thickness or round(0.002 * max(img.shape[0:2])) + 1 # line thickness
......@@ -259,7 +258,7 @@ def refine_face_bbox(bbox,img_shape):
return (x1,y1,x2,y2)
def get_faces_batch_attribute(face_multitask_model,face_euler_model,dets,img_raw,use_cuda,face_size = 256,vis = False):
def get_faces_batch_attribute(face_multitask_model,face_euler_model,face_au_model,dets,img_raw,use_cuda,face_size = 256,vis = False):
if len(dets) == 0:
return None
img_align = img_raw.copy()
......@@ -291,6 +290,7 @@ def get_faces_batch_attribute(face_multitask_model,face_euler_model,dets,img_raw
euler_angles = face_euler_model.predict(image_batch)
faces_message = None
faces_align_batch = None
for i in range(len(dets)):
x0,y0 = r_bboxes[i][0],r_bboxes[i][1]
face_w = r_bboxes[i][2]-r_bboxes[i][0]
......@@ -318,10 +318,22 @@ def get_faces_batch_attribute(face_multitask_model,face_euler_model,dets,img_raw
if abs(yaw)<45.:
face_align_output = face_alignment(img_align,eyes_center[0],eyes_center[1],
desiredLeftEye=(0.365, 0.38),desiredFaceWidth=112, desiredFaceHeight=None)
desiredLeftEye=(0.365, 0.38),desiredFaceWidth=256, desiredFaceHeight=None)
else:
face_align_output = face_alignment(img_align,eyes_center[0],eyes_center[1],
desiredLeftEye=(0.38, 0.40),desiredFaceWidth=112, desiredFaceHeight=None)
desiredLeftEye=(0.38, 0.40),desiredFaceWidth=256, desiredFaceHeight=None)
# au 输入 预处理
face_align_output_ = cv2.cvtColor(face_align_output, cv2.COLOR_BGR2RGB).astype(np.float32)
face_align_output_ = face_align_output_ - [123.67, 116.28, 103.53]
face_align_output_ = face_align_output_.transpose(2, 0, 1)
face_align_output_ = np.expand_dims(face_align_output_,0)
if faces_align_batch is None:
faces_align_batch = face_align_output_
else:
faces_align_batch = np.concatenate((faces_align_batch,face_align_output_),axis=0)
#
if faces_message is None:
faces_message = []
faces_message.append(
......@@ -329,12 +341,30 @@ def get_faces_batch_attribute(face_multitask_model,face_euler_model,dets,img_raw
"xyxy":r_bboxes[i],
"age":age_pre[i][0],
"gender":gender_str,
"head_3d_angle":{"yaw":yaw,"pitch":pitch,"roll":roll}
"head_3d_angle":{"yaw":yaw,"pitch":pitch,"roll":roll},
"open_mouth":None,
"eye_close":None
}
)
# plot_box(r_bboxes[i][0:4], img_raw,label="{}, age: {:.1f}, unblur:{}".format(gender_str,age_pre[i][0],int(blur_)), color=(255,90,90), line_thickness=2)
if vis:
plot_box(r_bboxes[i][0:4], img_raw,label="{}, age: {:.1f}".format(gender_str,age_pre[i][0]), color=(255,90,90), line_thickness=2)
# print("faces_align_batch shape : ",faces_align_batch.shape)
au_features = face_au_model.predict(faces_align_batch)
for i in range(len(dets)):
# print("au_features : ",au_features[i])
open_mouth = np.clip(au_features[i][8],0.,1.)
close_eye_r = np.clip(au_features[i][0],0.,1.)
close_eye_l = np.clip(au_features[i][1],0.,1.)
print("open_mouth : {:.2f},eye_close: {:.3f} , {:.3f}".format(open_mouth,close_eye_r,close_eye_l))
faces_message[i]["open_mouth"] = open_mouth
faces_message[i]["eye_close"] = (close_eye_r,close_eye_l)
cv2.putText(img_raw, "{:.2f}".format(open_mouth),(int(r_bboxes[i][0]-1),int(r_bboxes[i][3]+15)),cv2.FONT_HERSHEY_DUPLEX, 0.65, (20,185,25), 3)
cv2.putText(img_raw, "{:.2f}".format(open_mouth),(int(r_bboxes[i][0]-1),int(r_bboxes[i][3]+15)),cv2.FONT_HERSHEY_DUPLEX, 0.65, (20,185,255), 1)
cv2.putText(img_raw, "{:.2f},{:.2f}".format(close_eye_r,close_eye_l),(int(r_bboxes[i][0]-1),int(r_bboxes[i][3]+35)),cv2.FONT_HERSHEY_DUPLEX, 0.65, (20,33,255), 3)
cv2.putText(img_raw, "{:.2f},{:.2f}".format(close_eye_r,close_eye_l),(int(r_bboxes[i][0]-1),int(r_bboxes[i][3]+35)),cv2.FONT_HERSHEY_DUPLEX, 0.65, (20,185,255), 1)
return faces_message
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册