add face bounding box

This commit is contained in:
matt3o
2024-02-27 17:20:23 +01:00
parent 0cac8f7650
commit 5b6a5ef59f
2 changed files with 92 additions and 0 deletions
+2
View File
@@ -12,6 +12,8 @@ Please read the results as follow:
Please download the DLIB [Shape Predictor](https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/shape_predictor_68_face_landmarks.dat?download=true) and the [Face Recognition](https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/dlib_face_recognition_resnet_model_v1.dat?download=true) models and place them into the `dlib` directory.
Precompiled Dlib for windows can be found [here](https://github.com/z-mahmud22/Dlib_Windows_Python3.x).
In this repository you also find a workflow that uses IPAdapter to generate a few images and return the distance to the reference face.
![face analysis](./face_analysis.jpg)
+90
View File
@@ -59,9 +59,97 @@ class FaceAnalysisModels:
"shape_predict": dlib.shape_predictor(os.path.join(DLIB_DIR, "shape_predictor_68_face_landmarks.dat")),
"face_recog": dlib.face_recognition_model_v1(os.path.join(DLIB_DIR, "dlib_face_recognition_resnet_model_v1.dat")),
}
return (out, )
def crop_face(image, x, y, w, h, padding=0):
x = max(0, x - padding)
y = max(0, y - padding)
w = min(image.width, w + 2 * padding)
h = min(image.height, h + 2 * padding)
return image.crop((x, y, x + w, y + h))
class FaceBoundingBox:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"analysis_models": ("ANALYSIS_MODELS", ),
"image": ("IMAGE", ),
"padding": ("INT", { "default": 0, "min": 0, "max": 4096, "step": 1 }),
"index": ("INT", { "default": -1, "min": -1, "max": 4096, "step": 1 }),
},
}
RETURN_TYPES = ("IMAGE", "INT", "INT", "INT", "INT")
RETURN_NAMES = ("IMAGE", "x", "y", "width", "height")
FUNCTION = "bbox"
CATEGORY = "FaceAnalysis"
def bbox(self, analysis_models, image, padding, index=-1):
out_img = []
out_x = []
out_y = []
out_w = []
out_h = []
for i in image:
img = T.ToPILImage()(i.permute(2, 0, 1)).convert('RGB')
if analysis_models["library"] == "insightface":
faces = analysis_models["detector"].get(np.array(img))
for face in faces:
x, y, w, h = face.bbox.astype(int)
w = w - x
h = h - y
x = max(0, x - padding)
y = max(0, y - padding)
w = min(img.width, w + 2 * padding)
h = min(img.height, h + 2 * padding)
crop = img.crop((x, y, x + w, y + h))
out_img.append(T.ToTensor()(crop).permute(1, 2, 0))
out_x.append(x)
out_y.append(y)
out_w.append(w)
out_h.append(h)
else:
faces = analysis_models["detector"](np.array(img), 1)
for face in faces:
x, y, w, h = face.left(), face.top(), face.width(), face.height()
x = max(0, x - padding)
y = max(0, y - padding)
w = min(img.width, w + 2 * padding)
h = min(img.height, h + 2 * padding)
crop = img.crop((x, y, x + w, y + h))
out_img.append(T.ToTensor()(crop).permute(1, 2, 0))
out_x.append(x)
out_y.append(y)
out_w.append(w)
out_h.append(h)
if not out_img:
raise Exception('No face detected in image.')
out_img = torch.stack(out_img)
if out_img.shape[0] == 1:
index = 0
if index > out_img.shape[0] - 1:
index = out_img.shape[0] - 1
if index != -1:
out_img = out_img[index].unsqueeze(0)
out_x = out_x[index]
out_y = out_y[index]
out_w = out_w[index]
out_h = out_h[index]
return (out_img, out_x, out_y, out_w, out_h,)
class FaceEmbedDistance:
@classmethod
def INPUT_TYPES(s):
@@ -173,9 +261,11 @@ class FaceEmbedDistance:
NODE_CLASS_MAPPINGS = {
"FaceEmbedDistance": FaceEmbedDistance,
"FaceAnalysisModels": FaceAnalysisModels,
"FaceBoundingBox": FaceBoundingBox,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"FaceEmbedDistance": "Face Embeds Distance",
"FaceAnalysisModels": "Face Analysis Models",
"FaceBoundingBox": "Face Bounding Box",
}