Skip to content

Commit

Permalink
Implement Harman's earlobe calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
Valkryst committed Dec 6, 2023
1 parent d30e048 commit d10dc02
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 22 deletions.
32 changes: 32 additions & 0 deletions js/detector/face_detector.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ export class FaceDetector extends Detector {
name = "top_edge_face";
break;
}
case 93: {
name = "93";
break;
}
case 132: {
name = "132";
break;
}
case 137: {
name = "137";
break;
}
case 152: {
name = "bottom_edge_face";
break;
Expand All @@ -102,10 +114,30 @@ export class FaceDetector extends Detector {
name = "midpoint_between_nose_and_mouth";
break;
}
case 177: {
name = "177";
break;
}
case 234: {
name = "right_edge_face";
break;
}
case 323: {
name = "323";
break;
}
case 361: {
name = "361";
break;
}
case 366: {
name = "366";
break;
}
case 401: {
name = "401";
break;
}
case 454: {
name = "left_edge_face";
break;
Expand Down
88 changes: 66 additions & 22 deletions js/mesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,46 @@ export class Mesh {
return this.earlobeKeypoints;
}

const k93 = this.getKeypointByLabel("93");
if (k93 == null) {
return this.earlobeKeypoints;
}

const k132 = this.getKeypointByLabel("132");
if (k132 == null) {
return this.earlobeKeypoints;
}

const k137 = this.getKeypointByLabel("137");
if (k137 == null) {
return this.earlobeKeypoints;
}

const k177 = this.getKeypointByLabel("177");
if (k177 == null) {
return this.earlobeKeypoints;
}

const k323 = this.getKeypointByLabel("323");
if (k323 == null) {
return this.earlobeKeypoints;
}

const k361 = this.getKeypointByLabel("361");
if (k361 == null) {
return this.earlobeKeypoints;
}

const k366 = this.getKeypointByLabel("366");
if (k366 == null) {
return this.earlobeKeypoints;
}

const k401 = this.getKeypointByLabel("401");
if (k401 == null) {
return this.earlobeKeypoints;
}

/**
* If an earring asset is being displayed on the an earlobe, we need to ensure that it is scaled correctly as
* the user moves towards or away from the camera.
Expand Down Expand Up @@ -359,22 +399,17 @@ export class Mesh {
* coordinates of the earlobes to be closer to edges of the face.
*/
let leftEarlobeX;
if (isRotatedLeft) {
leftEarlobeX = leftEar.getX();
leftEarlobeX -= this.earlobeKeypoints[0].getWidth() / 2;
leftEarlobeX += (Math.abs(leftEar.getX() - leftEdgeFace.getX()) / 2);
} else {
leftEarlobeX = leftEdgeFace.getX();
}
leftEarlobeX = k323.getX() + Math.abs(k366.getX() - k323.getX());
leftEarlobeX += k361.getX() + Math.abs(k401.getX() - k361.getX());
leftEarlobeX /= 2;
leftEarlobeX -= this.earlobeKeypoints[0].getWidth() / 2;


let rightEarlobeX;
if (isRotatedRight) {
rightEarlobeX = rightEar.getX();
rightEarlobeX -= this.earlobeKeypoints[1].getWidth() / 2;
rightEarlobeX += (Math.abs(rightEar.getX() - rightEdgeFace.getX()) / 2);
} else {
rightEarlobeX = rightEdgeFace.getX();
}
rightEarlobeX = k132.getX() - Math.abs(k132.getX() - k177.getX());
rightEarlobeX += k93.getX() - Math.abs(k93.getX() - k137.getX());
rightEarlobeX /= 2;
rightEarlobeX += this.earlobeKeypoints[1].getWidth() / 2;

/*
* We assume that the Y-Axis of each earlobe is the same as the midpoint between the nose and mouth.
Expand All @@ -383,27 +418,36 @@ export class Mesh {
* the Y-Axis coordinates of the ears or eyes. Generally, Keypoints closer to the middle of the face are more
* accurate, so we use the difference between the Y-Axis coordinates of the eyes.
*/
let leftEarlobeY = midPointBetweenNoseAndMouth.y + (leftEye.y - rightEye.y);
let rightEarlobeY = midPointBetweenNoseAndMouth.y + (rightEye.y - leftEye.y);
let leftEarlobeY = 0;
leftEarlobeY = k323.getY() + Math.abs(k366.getY() - k323.getY());
leftEarlobeY += k361.getY() + Math.abs(k401.getY() - k361.getY());
leftEarlobeY /= 2;
leftEarlobeY += this.earlobeKeypoints[0].getHeight() / 2;

let rightEarlobeY;
rightEarlobeY = k132.getY() - Math.abs(k132.getY() - k177.getY());
rightEarlobeY += k93.getY() - Math.abs(k93.getY() - k137.getY());
rightEarlobeY /= 2;
rightEarlobeY += this.earlobeKeypoints[1].getHeight() / 2;

// If the head is tilted up or down, we need to apply an offset to negate the tilt.
leftEarlobeY += isRotatedUp ? topEdgeFace.z: 0;
leftEarlobeY += isRotatedDown ? -bottomEdgeFace.z : 0;
// leftEarlobeY += isRotatedUp ? topEdgeFace.z: 0;
// leftEarlobeY += isRotatedDown ? -bottomEdgeFace.z : 0;

rightEarlobeY += isRotatedUp ? topEdgeFace.z : 0;
rightEarlobeY += isRotatedDown ? -bottomEdgeFace.z : 0;
// rightEarlobeY += isRotatedUp ? topEdgeFace.z : 0;
// rightEarlobeY += isRotatedDown ? -bottomEdgeFace.z : 0;

/*
* We assume that the X-Axis coordinate of the earlobe is the same as the X-Axis coordinate of the ear.
*
* We assume that head rotation is accounted for by the ear Keypoints, as their coordinates are updated by the
* model.
*/
this.earlobeKeypoints[0].setConfidence(1);
this.earlobeKeypoints[0].setConfidence(isRotatedRight ? 0 : 1);
this.earlobeKeypoints[0].setPosition(leftEarlobeX, leftEarlobeY, leftEar.z);
this.earlobeKeypoints[0].setColour(Mesh.defaultEarlobeKeypointColour);

this.earlobeKeypoints[1].setConfidence(1);
this.earlobeKeypoints[1].setConfidence(isRotatedLeft ? 0 : 1);
this.earlobeKeypoints[1].setPosition(rightEarlobeX, rightEarlobeY, rightEar.z);
this.earlobeKeypoints[1].setColour(Mesh.defaultEarlobeKeypointColour);

Expand Down

0 comments on commit d10dc02

Please sign in to comment.