4.9 KiB
4.9 KiB
Documentation
- Class name: FaceBoundingBox
- Category: FaceAnalysis
- Output node: False
- Repo Ref: https://github.com/cubiq/ComfyUI_FaceAnalysis.git
该节点旨在分析图像并检测面部边界框,在需要面部检测和分析的图像处理应用中提供关键功能。
Input types
Required
- analysis_models
- 此参数包含用于图像中面部检测的模型和库,对节点处理和分析输入数据的能力有重大影响。
- Comfy dtype: DICT[str, Any]
- Python dtype: Dict[str, Any]
- image
- 图像参数对节点的运行至关重要,因为它是面部边界框检测的主要输入,直接影响分析的准确性和有效性。
- Comfy dtype: torch.Tensor
- Python dtype: torch.Tensor
- padding
- 填充是一个重要的参数,它确保检测到的面部有足够的边界,防止切割问题,提高检测的整体质量。
- Comfy dtype: INT
- Python dtype: int
Optional
- index
- 索引参数允许从多个检测中选择特定的面部,将节点的输出集中在所需的面部边界框上。
- Comfy dtype: INT
- Python dtype: int
Output types
- IMAGE
- 输出图像张量代表检测到的面部的裁剪和处理后的图像,对于进一步分析或显示目的来说是一个重要组成部分。
- Comfy dtype: torch.Tensor
- Python dtype: torch.Tensor
- x
- 边界框左上角的x坐标提供了面部检测的参考点,有助于精确定位图像中的面部。
- Comfy dtype: INT
- Python dtype: int
- y
- 边界框左上角的y坐标对于在图像上下文中准确定位检测到的面部至关重要。
- Comfy dtype: INT
- Python dtype: int
- width
- 边界框的宽度很重要,因为它决定了检测到的面部的大小,影响输出的分辨率和细节水平。
- Comfy dtype: INT
- Python dtype: int
- height
- 边界框的高度对于保持检测到的面部的宽高比和比例至关重要,确保输出中面部特征的完整性。
- Comfy dtype: INT
- Python dtype: int
Usage tips
- Infra type: CPU
Source code
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.')
if len(out_img) == 1:
index = 0
if index > len(out_img) - 1:
index = len(out_img) - 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]
else:
w = out_img[0].shape[1]
h = out_img[0].shape[0]
out_img = [comfy.utils.common_upscale(img.unsqueeze(0).movedim(-1, 1), w, h, 'bilinear', 'center').movedim(1, -1).squeeze(0) for img in out_img]
out_img = torch.stack(out_img)
return (out_img, out_x, out_y, out_w, out_h)