Skip to main content

Body Pipes

The body-related modules are implemented in src/autopipeline/components/modules/human_body.py.

They are documented together because both classes operate on body-local crops and body masks, but the scoring targets are different:

  • pose and silhouette consistency
  • appearance consistency
Module Group
Helper

Shared Helpers

pad_face_bbox(...)

pad_face_bbox(
face_bbox: Tuple[int, int, int, int],
pad_ratio: float = 0.3,
image_h: int = None,
image_w: int = None,
) -> Tuple[int, int, int, int] | None

This helper expands a face bbox and clamps it to image boundaries. It is used to remove the face region from body masks before body-only comparison.

get_cleaned_resized_body_mask(...)

get_cleaned_resized_body_mask(
body_mask,
hair_mask=None,
face_bbox=None,
target_h=None,
target_w=None,
) -> np.ndarray

This helper:

  1. starts from the body mask
  2. optionally removes hair pixels
  3. optionally removes the padded face region
  4. optionally resizes the result

It is central to both body-related modules.

Class

BodyPoseAndShapePipe

Registry Entry

FieldValue
Registry keybody-pose-and-shape-pipe
ClassBodyPoseAndShapePipe
Main mixinsHumanSkeletonMixin
Return typefloat or None

Constructor

BodyPoseAndShapePipe(**kwargs)

Supported init kwargs

KeyDefaultMeaning
static_modeTrueMediaPipe Pose inference mode.
model_complexity0MediaPipe Pose model complexity.
min_detection_confidence0.5Pose detection confidence threshold.

Public Methods

MethodPurpose
calc_skeleton_aligned_shape_iou(...)Align body masks through skeleton-derived affine normalization and compute IoU.
calc_pose_position_error(...)Compute normalized keypoint-position error after Procrustes-style normalization.
__call__(...)Dispatch between body-shape and body-pose metrics.

Call Signature

BodyPoseAndShapePipe.__call__(
cropped_ref_human_image: Image.Image,
cropped_edited_human_image: Image.Image,
ref_face_bbox: Tuple[int, int, int, int] = None,
edited_face_bbox: Tuple[int, int, int, int] = None,
ref_hair_mask: np.ndarray = None,
edited_hair_mask: np.ndarray = None,
ref_body_mask: np.ndarray = None,
edited_body_mask: np.ndarray = None,
metric: str = "body_shape_iou",
**kwargs,
)

Supported Metrics

MetricMeaningBetter direction
body_shape_iousilhouette overlap after skeleton-aware alignmenthigher is better
body_pose_position_errornormalized joint-position driftlower is better

Extra runtime kwargs

KeyDefaultMeaning
face_bbox_pad_ratio0.3Padding ratio when removing face from the body mask.
target_canvas_size(512, 512)Target canvas for aligned body-shape IoU.

Return Value

Returns a float score or None.

Failure Semantics

Important soft-failure behavior:

  • missing body mask -> returns None
  • missing pose landmarks -> returns None
  • insufficient valid keypoints:
    • shape metric falls back to direct mask IoU
    • pose metric returns None

Unsupported metrics raise ValueError.

Minimal Config Example

metric_configs:
body_appearance_dino_cosine_sim:
pipe_name: body-appearance-pipe
default_config: ${pipes_default.body-appearance-pipe}
init_config:
scope: edit_area
runtime_params:
face_bbox_pad_ratio: 0.3
patch_mask_threshold: 0.1

For this specific class, a shape-oriented config would look like:

metric_configs:
body_shape_iou:
pipe_name: body-pose-and-shape-pipe
default_config: ${pipes_default.body-pose-and-shape-pipe}
init_config:
static_mode: true
model_complexity: 1
min_detection_confidence: 0.5
scope: edit_area
runtime_params:
face_bbox_pad_ratio: 0.3
target_canvas_size: !tuple [512, 512]
Class

BodyAppearancePipe

Registry Entry

FieldValue
Registry keybody-appearance-pipe
ClassBodyAppearancePipe
Main mixinsDINOv3Mixin, MaskProcessor
Return typefloat or None

Important inheritance note

BodyAppearancePipe is registered and usable, but unlike most module classes it does not explicitly inherit BasePipe. That is a real implementation detail, not just a documentation abstraction. If you extend it, read the class carefully instead of assuming it follows the exact same inheritance pattern as every other module.

Constructor

BodyAppearancePipe(**kwargs)

Supported init kwargs

KeyRequiredMeaning
model_pathYes in practiceDINOv3 checkpoint path.
deviceNoTorch device for DINO inference.

Public Methods

MethodPurpose
calc_dino_aggregation_cosine_similarity(...)Average selected DINO features per image and compare them by cosine similarity.
__call__(...)Build cleaned body patch masks and compute appearance similarity.

Call Signature

BodyAppearancePipe.__call__(
cropped_ref_human_image: Image.Image,
cropped_edited_human_image: Image.Image,
ref_face_bbox: Tuple[int, int, int, int] = None,
edited_face_bbox: Tuple[int, int, int, int] = None,
ref_hair_mask: np.ndarray = None,
edited_hair_mask: np.ndarray = None,
ref_body_mask: np.ndarray = None,
edited_body_mask: np.ndarray = None,
metric: str = "body_appearance_dino_cosine_sim",
**kwargs,
)

Supported Metric

MetricMeaningBetter direction
body_appearance_dino_cosine_simsimilarity of aggregated DINO body-region featureshigher is better

Extra runtime kwargs

KeyDefaultMeaning
face_bbox_pad_ratio0.3Padding ratio when removing face from the body region.
patch_mask_threshold0.1Threshold when converting cleaned body masks into patch masks.

Return Value

Returns a float similarity score clipped with:

max(0.0, score)

Failure Semantics

The main soft-failure branches are:

  • missing body masks -> returns None
  • empty selected patch set on either side -> returns None

Unsupported metrics raise ValueError.

Minimal Config Example

metric_configs:
body_appearance_dino_cosine_sim:
pipe_name: body-appearance-pipe
default_config: ${pipes_default.body-appearance-pipe}
init_config:
scope: edit_area
runtime_params:
face_bbox_pad_ratio: 0.3
patch_mask_threshold: 0.1

Extension Notes

  • Keep shared body-mask cleanup in the helper layer instead of duplicating it inside each metric branch.
  • Document whether a new metric is shape-oriented or appearance-oriented, because the expected score direction differs.
  • If a new metric still depends on cleaned body masks and DINO features, adding a branch to BodyAppearancePipe is usually cleaner than creating a brand new module.