Add a silouhette png instead of hand drawn face
This commit is contained in:
parent
facc140619
commit
105691815d
2 changed files with 16 additions and 102 deletions
BIN
frontend/src/lib/assets/silhouette.png
Normal file
BIN
frontend/src/lib/assets/silhouette.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -1,63 +1,14 @@
|
|||
<script>
|
||||
/**
|
||||
* Visual indicator for alignment settings showing head position and scale.
|
||||
* Displays an anatomically proportioned face with eyes positioned according to eye_distance.
|
||||
*
|
||||
* The eye_distance parameter controls zoom level:
|
||||
* - Smaller values (0.1): zoomed out, head appears smaller, shows more neck
|
||||
* - Larger values (0.5): zoomed in, head appears larger, tighter crop
|
||||
*
|
||||
* Proportions match the processing pipeline (alignment.rs):
|
||||
* - Eye positions calculated with FACE_CENTER_BELOW_EYES = 0.5
|
||||
* - Face center (hairline-to-chin midpoint + neck) positioned at frame center
|
||||
* - This creates a vertical offset showing more neck than forehead
|
||||
* - Inter-pupillary distance (IPD) is ~37% of face width
|
||||
*/
|
||||
import silhouetteUrl from '../../assets/silhouette.png';
|
||||
|
||||
let { eyeDistance = 0.3 } = $props();
|
||||
|
||||
// Frame dimensions (square output image)
|
||||
const frameSize = 120;
|
||||
|
||||
// Calculate eye positions using the same formulas as alignment.rs
|
||||
const FACE_CENTER_BELOW_EYES = 0.5;
|
||||
|
||||
const leftEyeX = $derived((1.0 - eyeDistance) / 2.0);
|
||||
const rightEyeX = $derived(1.0 - leftEyeX);
|
||||
const eyeY = $derived(0.5 - eyeDistance * FACE_CENTER_BELOW_EYES);
|
||||
|
||||
// Convert to pixel coordinates
|
||||
const leftEyePos = $derived({ x: leftEyeX * frameSize, y: eyeY * frameSize });
|
||||
const rightEyePos = $derived({ x: rightEyeX * frameSize, y: eyeY * frameSize });
|
||||
|
||||
// Calculate eye distance in pixels
|
||||
const eyeDistancePx = $derived(eyeDistance * frameSize);
|
||||
|
||||
// Calculate eye center point
|
||||
const eyeCenterX = $derived((leftEyePos.x + rightEyePos.x) / 2);
|
||||
const eyeCenterY = $derived(eyeY * frameSize);
|
||||
|
||||
// Face proportions based on inter-pupillary distance (IPD)
|
||||
// Per crop_utils.rs, IPD is ~0.37 of face width
|
||||
// Face center (hairline-to-chin midpoint + neck) is 0.5 * IPD below eyes
|
||||
|
||||
// Anatomical proportions relative to IPD:
|
||||
// - Eyes to top of head (forehead): ~0.5 IPD
|
||||
// - Eyes to face center: 0.5 IPD (by definition)
|
||||
// - Face center to bottom (lower face + neck): ~0.5 IPD
|
||||
// Total head height: ~1.5 IPD
|
||||
const foreheadHeight = $derived(eyeDistancePx * 0.5);
|
||||
const lowerFaceHeight = $derived(eyeDistancePx * 1.0);
|
||||
|
||||
// Head ellipse dimensions (head is taller than wide)
|
||||
const headCenter = $derived({
|
||||
x: eyeCenterX,
|
||||
y: eyeCenterY + (lowerFaceHeight - foreheadHeight) / 2
|
||||
});
|
||||
const headWidth = $derived(eyeDistancePx * 1.35); // Width relative to IPD
|
||||
const headHeight = $derived(eyeDistancePx * 1.85); // Height > width (ratio ~1.37)
|
||||
|
||||
// Eye rendering parameters (scale with IPD)
|
||||
const eyeRadius = $derived(Math.max(2.5, eyeDistancePx * 0.12));
|
||||
// Scale the silouhette so it fills the frame proportionally to eyeDistance
|
||||
const imgSize = $derived(eyeDistance * frameSize * (1 / 0.12)); // Eye distance approximated to around 12% of the width.
|
||||
const imgX = $derived((frameSize - imgSize) / 2);
|
||||
const imgY = $derived(((frameSize * 1.4) - imgSize) / 2); // slight offset to show more neck
|
||||
</script>
|
||||
|
||||
<svg
|
||||
|
|
@ -76,50 +27,14 @@
|
|||
stroke="none"
|
||||
/>
|
||||
|
||||
<!-- Head ellipse (face shape) -->
|
||||
<ellipse
|
||||
cx={headCenter.x}
|
||||
cy={headCenter.y}
|
||||
rx={headWidth}
|
||||
ry={headHeight}
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
class="head"
|
||||
/>
|
||||
|
||||
<!-- Left eye -->
|
||||
<circle
|
||||
cx={leftEyePos.x}
|
||||
cy={leftEyePos.y}
|
||||
r={eyeRadius}
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
class="eye"
|
||||
/>
|
||||
|
||||
<!-- Right eye -->
|
||||
<circle
|
||||
cx={rightEyePos.x}
|
||||
cy={rightEyePos.y}
|
||||
r={eyeRadius}
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
class="eye"
|
||||
/>
|
||||
|
||||
<!-- Simple mouth curve (positioned between eyes and chin) -->
|
||||
<path
|
||||
d="M {eyeCenterX - eyeDistancePx * 0.35} {eyeCenterY + eyeDistancePx * 0.65}
|
||||
Q {eyeCenterX} {eyeCenterY + eyeDistancePx * 0.75},
|
||||
{eyeCenterX + eyeDistancePx * 0.35} {eyeCenterY + eyeDistancePx * 0.65}"
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
class="mouth"
|
||||
<!-- Silhouette image scaled to head bounding box -->
|
||||
<image
|
||||
href={silhouetteUrl}
|
||||
x={imgX}
|
||||
y={imgY}
|
||||
width={imgSize}
|
||||
height={imgSize}
|
||||
class="silhouette"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
|
|
@ -129,9 +44,8 @@
|
|||
height: 80px;
|
||||
}
|
||||
|
||||
.head,
|
||||
.eye,
|
||||
.mouth {
|
||||
.silhouette {
|
||||
filter: invert(1);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue