1
0
Fork 0
Face identification and recognition scalable server with multiple face directories. https://github.com/ehp/faceserver
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

170 lines
5.0 KiB

# -*- coding: utf-8 -*-
"""
Copyright 2019 Petr Masopust, Aprar s.r.o.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Adopted code from https://github.com/ronghuaiyang/arcface-pytorch
Created on 18-5-30 下午4:55
@author: ronghuaiyang
"""
import os
import argparse
from torch.utils.data import TensorDataset, DataLoader
from recognition.nets import get_net_by_depth
import torch
import numpy as np
from torch.nn import DataParallel
from PIL import Image
from torchvision import transforms as T
imagesize = 224
batch_size = 20
class Dataset(torch.utils.data.Dataset):
def __init__(self, identity_list, root_path):
self.identity_list = identity_list
self.root_path = root_path
normalize = T.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
self.transforms = T.Compose([
T.Resize(imagesize),
T.ToTensor(),
normalize
])
def __getitem__(self, index):
a, b, label = self.identity_list[index]
a_data = self.load_image(a)
b_data = self.load_image(b)
return a_data, b_data, label
def load_image(self, p):
img_path = os.path.join(self.root_path, p)
data = Image.open(img_path)
if data is None:
return None
data = data.convert(mode="RGB")
data = self.transforms(data)
return data
def __len__(self):
return len(self.identity_list)
def get_pair_list(pair_list):
print('Loading pair list')
with open(pair_list, 'r') as fd:
pairs = fd.readlines()
return [line.split() for line in pairs]
def load_img_data(identity_list, root_path):
dataset = Dataset(identity_list, root_path)
loader = DataLoader(dataset,
batch_size=batch_size,
shuffle=False,
# pin_memory=True,
num_workers=0)
return loader
def lfw_test2(model, identity_list, img_data, is_cuda=True):
print('Converting to features')
sims = []
labels = []
max_size = len(img_data) * batch_size
for i, sample in enumerate(img_data):
if i % 10 == 0:
print('%d of %d' % (i * batch_size, max_size))
a_data, b_data, label = sample
if is_cuda:
a_data = a_data.cuda()
b_data = b_data.cuda()
a_output = model(a_data).detach().cpu().numpy()
b_output = model(b_data).detach().cpu().numpy()
for idx in range(batch_size):
sim = cosin_metric(a_output[idx], b_output[idx])
sims.append(sim)
labels.append(np.bool(label[idx] == '1'))
acc, th = cal_accuracy(sims, labels)
print('lfw face verification accuracy: ', acc, 'threshold: ', th)
return acc
def cosin_metric(x1, x2):
return np.dot(x1, x2) / (np.linalg.norm(x1) * np.linalg.norm(x2))
def cal_accuracy(y_score, y_true):
y_score = np.asarray(y_score)
y_true = np.asarray(y_true)
best_acc = 0
best_th = 0
for i in range(len(y_score)):
th = y_score[i]
y_test = (y_score >= th)
acc = np.mean((y_test == y_true).astype(int))
if acc > best_acc:
best_acc = acc
best_th = th
return best_acc, best_th
def main(args=None):
parser = argparse.ArgumentParser(description='Testing script for face identification.')
parser.add_argument('--depth', help='Resnet depth, must be one of 18, 34, 50, 101, 152 or 20 for sphere', type=int,
default=50)
parser.add_argument('--parallel', help='Run training with DataParallel', dest='parallel',
default=False, action='store_true')
parser.add_argument('--model', help='Path to model')
parser.add_argument('--batch_size', help='Batch size (default 50)', type=int, default=50)
parser.add_argument('--lfw_root', help='Path to LFW dataset')
parser.add_argument('--lfw_pair_list', help='Path to LFW pair list file')
parser = parser.parse_args(args)
is_cuda = torch.cuda.is_available()
print('CUDA available: {}'.format(is_cuda))
model = get_net_by_depth(parser.depth)
if parser.parallel:
model = DataParallel(model)
# load_model(model, opt.test_model_path)
model.load_state_dict(torch.load(parser.model))
if is_cuda:
model.cuda()
identity_list = get_pair_list(parser.lfw_pair_list)
img_data = load_img_data(identity_list, parser.lfw_root)
model.eval()
lfw_test2(model, identity_list, img_data, is_cuda=is_cuda)
if __name__ == '__main__':
main()