FaceForge / backend /slider_mapper.py
Tomastarau's picture
feat: initial deployment setup
21947c8
import json
import os
import numpy as np
from ratio_calculator import FacialRatios
CALIBRATION_PATH = os.path.join(os.path.dirname(__file__), "calibration.json")
SLIDER_MIN = -100
SLIDER_MAX = 100
RATIO_FIELD = {
"eye_spacing": "eye_spacing_ratio",
"eye_size": "eye_size_ratio",
"nose_width": "nose_width_ratio",
"nose_length": "nose_length_ratio",
"mouth_width": "mouth_width_ratio",
"mouth_corner": "mouth_corner_ratio",
"jaw_width": "jaw_width_ratio",
"jaw_position": "jaw_position_ratio",
"chin_width": "chin_width_ratio",
"face_length": "face_length_ratio",
"brow_spacing": "brow_spacing_ratio",
"brow_height": "brow_height_ratio",
"brow_angle": "brow_angle_ratio",
"brow_curve": "brow_curve_ratio",
"lip_thickness": "lip_thickness_ratio",
"eye_tilt": "eye_tilt_ratio",
"eye_height": "eye_height_ratio",
"mouth_height": "mouth_height_ratio",
}
SLIDER_META = {
"eye_spacing": {
"label": "Eye Spacing",
"description": "Distance between the inner corners of both eyes relative to the total outer-to-outer width. A high value means widely spaced eyes.",
},
"eye_size": {
"label": "Eye Size",
"description": "Vertical opening of the eye between the upper and lower eyelid, normalized by eye width.",
},
"nose_width": {
"label": "Nose Width",
"description": "Width of the nostrils relative to eye width. Measured at the outermost points of the nose wings.",
},
"nose_length": {
"label": "Nose Length",
"description": "Distance from the nose bridge (between the eyes) to the tip, normalized by eye width.",
},
"mouth_width": {
"label": "Mouth Width",
"description": "Distance between the two mouth corners, relative to eye width.",
},
"mouth_corner": {
"label": "Mouth Corner",
"description": "Vertical position of the mouth corners relative to the lip center. Positive = corners lifted.",
},
"jaw_width": {
"label": "Jaw Width",
"description": "Width of the lower face at jaw level, normalized by eye width. Reflects overall face squareness.",
},
"jaw_position": {
"label": "Jaw Position",
"description": "Vertical distance between the mouth corners and the bottom of the jaw, normalized by eye width.",
},
"chin_width": {
"label": "Chin Width",
"description": "Width-to-height ratio of the chin — wide and square vs narrow and pointed.",
},
"face_length": {
"label": "Face Length",
"description": "Total face height from the top of the forehead to the chin, normalized by eye width. Maps to the chin height slider in DD2.",
},
"brow_spacing": {
"label": "Brow Spacing",
"description": "Distance between the inner corners of both eyebrows, normalized by eye width.",
},
"brow_height": {
"label": "Brow Height",
"description": "Vertical distance between the eye line and the eyebrows. Higher value means higher brows.",
},
"brow_angle": {
"label": "Brow Angle",
"description": "Slope of the eyebrow from inner to outer corner. Positive = outer corner higher (raised brow).",
},
"brow_curve": {
"label": "Brow Curve",
"description": "Height of the eyebrow arch above the line connecting its inner and outer corners.",
},
"lip_thickness": {
"label": "Lip Thickness",
"description": "Total vertical height of the lips from the upper edge to the lower edge, normalized by eye width.",
},
"eye_tilt": {
"label": "Eye Tilt",
"description": "Angle of the eye between inner and outer corners. Negative = outer corner higher (cat eyes). Positive = outer corner lower (drooping eyes).",
},
"eye_height": {
"label": "Eye Height",
"description": "Vertical position of the eyes on the face from the top of the skull, normalized by eye width.",
},
"mouth_height": {
"label": "Mouth Height",
"description": "Vertical position of the mouth on the face from the top of the skull, normalized by eye width.",
},
}
_calibration: dict | None = None
def _load_calibration() -> dict:
global _calibration
if _calibration is None:
with open(CALIBRATION_PATH) as f:
_calibration = json.load(f)
return _calibration
def map_to_sliders(ratios: FacialRatios) -> list[dict]:
calibration = _load_calibration()
result = []
for feature, field in RATIO_FIELD.items():
if feature not in calibration:
continue
anchors = sorted(calibration[feature]["anchors"], key=lambda a: a["ratio"])
xs = [a["ratio"] for a in anchors]
ys = [a["slider"] for a in anchors]
ratio_value = getattr(ratios, field)
raw = float(np.interp(ratio_value, xs, ys))
value = max(SLIDER_MIN, min(SLIDER_MAX, round(raw)))
meta = SLIDER_META[feature]
result.append({
"key": feature,
"label": meta["label"],
"description": meta["description"],
"value": value,
})
return result