test / train.py
Surya152002's picture
Upload 12 files
40f2021
import argparse
#pytorch
from concurrent.futures import thread
from xmlrpc.client import Boolean
from sqlalchemy import null
import torch
from torchvision import transforms
from threading import Thread
#other lib
import sys
import numpy as np
import os
import cv2
import shutil
sys.path.insert(0, "yolov5_face")
from models.experimental import attempt_load
from utils.datasets import letterbox
from utils.general import check_img_size, non_max_suppression_face, scale_coords
# Check device
device = torch.device("cpu")
# Get model detect
## Case 1:
model = attempt_load("yolov5_face/yolov5m-face.pt", map_location=device)
## Case 2:
#model = attempt_load("yolov5_face/yolov5n-0.5.pt", map_location=device)
# Get model recognition
## Case 1:
from insightface.insight_face import iresnet100
weight = torch.load("insightface/resnet100_backbone.pth", map_location = device)
model_emb = iresnet100()
## Case 2:
# from insightface.insight_face import iresnet18
# weight = torch.load("insightface/resnet18_backbone.pth", map_location = device)
# model_emb = iresnet18()
model_emb.load_state_dict(weight)
model_emb.to(device)
model_emb.eval()
face_preprocess = transforms.Compose([
transforms.ToTensor(), # input PIL => (3,56,56), /255.0
transforms.Resize((112, 112)),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
def resize_image(img0, img_size):
h0, w0 = img0.shape[:2] # orig hw
r = img_size / max(h0, w0) # resize image to img_size
if r != 1: # always resize down, only resize up if training with augmentation
interp = cv2.INTER_AREA if r < 1 else cv2.INTER_LINEAR
img0 = cv2.resize(img0, (int(w0 * r), int(h0 * r)), interpolation=interp)
imgsz = check_img_size(img_size, s=model.stride.max()) # check img_size
img = letterbox(img0, new_shape=imgsz)[0]
# Convert
img = img[:, :, ::-1].transpose(2, 0, 1).copy() # BGR to RGB, to 3x416x416
img = torch.from_numpy(img).to(device)
img = img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
return img
def get_face(input_image):
# Parameters
size_convert = 256
conf_thres = 0.4
iou_thres = 0.5
# Resize image
img = resize_image(input_image.copy(), size_convert)
# Via yolov5-face
with torch.no_grad():
pred = model(img[None, :])[0]
# Apply NMS
det = non_max_suppression_face(pred, conf_thres, iou_thres)[0]
bboxs = np.int32(scale_coords(img.shape[1:], det[:, :4], input_image.shape).round().cpu().numpy())
return bboxs
def get_feature(face_image, training = True):
# Convert to RGB
face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB)
# Preprocessing image BGR
face_image = face_preprocess(face_image).to(device)
# Via model to get feature
with torch.no_grad():
if training:
emb_img_face = model_emb(face_image[None, :])[0].cpu().numpy()
else:
emb_img_face = model_emb(face_image[None, :]).cpu().numpy()
# Convert to array
images_emb = emb_img_face/np.linalg.norm(emb_img_face)
return images_emb
def read_features(root_fearure_path):
try:
data = np.load(root_fearure_path + ".npz", allow_pickle=True)
images_name = data["arr1"]
images_emb = data["arr2"]
return images_name, images_emb
except:
return null
def training(full_training_dir, additional_training_dir,
faces_save_dir, features_save_dir, is_add_user):
# Init results output
images_name = []
images_emb = []
# Check mode full training or additional
if is_add_user == True:
source = additional_training_dir
else:
source = full_training_dir
# Read training folders, get and save faces
for name_person in os.listdir(source):
if name_person.startswith('.'):
continue # Skip hidden files/directories
person_image_path = os.path.join(source, name_person)
# Create path to save a person's face
person_face_path = os.path.join(faces_save_dir, name_person)
os.makedirs(person_face_path, exist_ok=True)
for image_name in os.listdir(person_image_path):
if image_name.endswith(("png", 'jpg', 'jpeg')):
image_path = os.path.join(person_image_path, image_name)
input_image = cv2.imread(image_path) # BGR
# Get faces
bboxs = get_face(input_image)
# Get boxes
for i in range(len(bboxs)):
# Get the number of files in the person's path
number_files = len(os.listdir(person_face_path))
# Get the location of the face
x1, y1, x2, y2 = bboxs[i]
# Get the face from the location
face_image = input_image[y1:y2, x1:x2]
# Path to save the face
path_save_face = os.path.join(person_face_path, f"{number_files}.jpg")
# Save the face to the database
cv2.imwrite(path_save_face, face_image)
# Get feature from the face
images_emb.append(get_feature(face_image, training=True))
images_name.append(name_person)
# Convert to arrays
images_emb = np.array(images_emb)
images_name = np.array(images_name)
features = read_features(features_save_dir)
if features == null or is_add_user == False:
pass
else:
# Read features
old_images_name, old_images_emb = features
# Add features and names of images to the feature database
images_name = np.hstack((old_images_name, images_name))
images_emb = np.vstack((old_images_emb, images_emb))
print("Update feature!")
# Save features
np.savez_compressed(features_save_dir,
arr1=images_name, arr2=images_emb)
# Move additional data to full train data
if is_add_user == True:
for sub_dir in os.listdir(additional_training_dir):
if sub_dir.startswith('.'):
continue # Skip hidden files/directories
dir_to_move = os.path.join(additional_training_dir, sub_dir)
shutil.move(dir_to_move, full_training_dir, copy_function=shutil.copytree)
def parse_opt():
parser = argparse.ArgumentParser()
parser.add_argument('--full-training-dir', type=str, default='./database/full-training-datasets/', help='dir folder full training')
parser.add_argument('--additional-training-dir', type=str, default='./database/additional-training-datasets/', help='dir folder additional training')
parser.add_argument('--faces-save-dir', type=str, default='./database/face-datasets/', help='dir folder save face features')
parser.add_argument('--features-save-dir', type=str, default='./static/feature/face_features', help='dir folder save face features')
parser.add_argument('--is-add-user', type=bool, default=True, help='Mode add user or full training')
opt = parser.parse_args()
return opt
def main(opt):
training(**vars(opt))
if __name__ == "__main__":
opt = parse_opt()
main(opt)