face-attendance / main.py
Surya152002's picture
Upload 12 files
e26ddc0
#pytorch
import torch
from torchvision import transforms
#other lib
import sys
import numpy as np
import os
import cv2
from insightface.insight_face import iresnet100
from PIL import Image
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("cuda" if torch.cuda.is_available() else "cpu")
# Get model
# model = attempt_load("yolov5_face/yolov5m-face.pt", map_location=device)
model = attempt_load("yolov5_face/yolov5n-0.5.pt", map_location=device)
weight = torch.load("insightface/16_backbone.pth", map_location = device)
model_emb = iresnet100()
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 = 640
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 = "static/feature/face_features.npz"):
data = np.load(root_fearure_path, allow_pickle=True)
images_name = data["arr1"]
images_emb = data["arr2"]
return images_name, images_emb
def training(input_image, name_persion):
# input_image = cv2.imread(path_image)
# Path to save face
path_database = "faces_database/"
path_persion = os.path.join(path_database, name_persion)
# Create dir
os.makedirs(path_persion, exist_ok=True)
images_name = []
images_emb = []
# Get faces
bboxs = get_face(input_image)
# Get boxs
for i in range(len(bboxs)):
# Get number files in persion path
number_files = len(os.listdir(path_persion))
# Get location face
x1, y1, x2, y2 = bboxs[i]
# Get face from location
face_image = input_image[y1:y2, x1:x2]
# Path save face
path_save_face = path_persion + f"/{number_files}.jpg"
# Save to face database
cv2.imwrite(path_save_face, face_image)
# Get feature from face
images_emb.append(get_feature(face_image, training=True))
images_name.append(name_persion)
# Convert to array
images_emb = np.array(images_emb)
images_name = np.array(images_name)
# Read features
old_images_name, old_images_emb = read_features()
# Add feature and name of image to feature database
new_images_name = np.hstack((old_images_name, images_name))
new_images_emb = np.vstack((old_images_emb, images_emb))
# Save features
path_features = "static/feature/"
np.savez_compressed(path_features + "face_features",
arr1 = new_images_name, arr2 = new_images_emb)
def recognition(image):
# Get faces
bboxs = get_face(image)
# Get boxs
for i in range(len(bboxs)):
# Get location face
x1, y1, x2, y2 = bboxs[i]
# Get face from location
face_image = image[y1:y2, x1:x2]
# Get feature from face
query_emb = (get_feature(face_image, training=False))
print(query_emb.shape)
# Read features
images_names, images_embs = read_features()
scores = (query_emb @ images_embs.T)[0]
id_min = np.argmax(scores)
score = scores[id_min]
name = images_names[id_min]
if score < 0.2:
caption= "UN_KNOWN"
else:
caption = f"{name.split('_')[0].upper()}:{score:.2f}"
t_size = cv2.getTextSize(caption, cv2.FONT_HERSHEY_PLAIN, 2, 2)[0]
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 146, 230), 3)
cv2.rectangle(
image, (x1, y1), (x1 + t_size[0], y1 + t_size[1]), (0, 146, 230), -1)
cv2.putText(image, caption, (x1, y1 + t_size[1]), cv2.FONT_HERSHEY_PLAIN, 2, [255, 255, 255], 2)
return image
if __name__=="__main__":
'''Traning'''
# Input
path_image = "train_image.jpg"
name_persion = "Châu"
image = cv2.imread(path_image)
# Training
training(image, name_persion)
'''Recognition'''
# Input
path_query = "test_image.jpg"
image = cv2.imread(path_query)
# Regnition
result = recognition(image)
cv2.imwrite("result.jpg", result)
# Output
cv2.imshow("Result", result)
cv2.waitKey(0) # waits until a key is pressed
cv2.destroyAllWindows() # destroys the window showing image