Skip to content

Commit

Permalink
Add type and constant for left and right side
Browse files Browse the repository at this point in the history
  • Loading branch information
utileetdulce committed Jan 27, 2022
1 parent db86d3e commit b120870
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 49 deletions.
39 changes: 20 additions & 19 deletions src/FaceSolver/calcEyes.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import Vector from "../utils/vector";
import { clamp, remap } from "../utils/helpers";
import { Results, XYZ } from "../Types";
import { Results, XYZ, Side } from "../Types";
import { RIGHT, LEFT } from "./../constants";

/**
* Landmark points labeled for eye, brow, and pupils
*/
const points = {
eye: {
left: [130, 133, 160, 159, 158, 144, 145, 153],
right: [263, 362, 387, 386, 385, 373, 374, 380],
[LEFT]: [130, 133, 160, 159, 158, 144, 145, 153],
[RIGHT]: [263, 362, 387, 386, 385, 373, 374, 380],
},
brow: {
left: [35, 244, 63, 105, 66, 229, 230, 231],
right: [265, 464, 293, 334, 296, 449, 450, 451],
[LEFT]: [35, 244, 63, 105, 66, 229, 230, 231],
[RIGHT]: [265, 464, 293, 334, 296, 449, 450, 451],
},
pupil: {
left: [468, 469, 470, 471, 472],
right: [473, 474, 475, 476, 477],
[LEFT]: [468, 469, 470, 471, 472],
[RIGHT]: [473, 474, 475, 476, 477],
},
};

/**
* Calculate eye open ratios and remap to 0-1
* @param {Array} lm : array of results from tfjs or mediapipe
* @param {String} side : designate "left" or "right"
* @param {Side} side : designate left or right
* @param {Number} high : ratio at which eye is considered open
* @param {Number} low : ratio at which eye is comsidered closed
*/
export const getEyeOpen = (lm: Results, side: "left" | "right" = "left", { high = 0.85, low = 0.55 } = {}) => {
export const getEyeOpen = (lm: Results, side: Side = LEFT, { high = 0.85, low = 0.55 } = {}) => {
const eyePoints = points.eye[side];
const eyeDistance = eyeLidRatio(
lm[eyePoints[0]],
Expand Down Expand Up @@ -91,9 +92,9 @@ export const eyeLidRatio = (
/**
* Calculate pupil position [-1,1]
* @param {Results} lm : array of results from tfjs or mediapipe
* @param {"left"| "right"} side : "left" or "right"
* @param {Side} side : left or right
*/
export const pupilPos = (lm: Results, side: "left" | "right" = "left") => {
export const pupilPos = (lm: Results, side: Side = LEFT) => {
const eyeOuterCorner = new Vector(lm[points.eye[side][0]]);
const eyeInnerCorner = new Vector(lm[points.eye[side][1]]);
const eyeWidth = eyeOuterCorner.distance(eyeInnerCorner, 2);
Expand Down Expand Up @@ -206,8 +207,8 @@ export const calcEyes = (
};
}
//open [0,1]
const leftEyeLid = getEyeOpen(lm, "left", { high: high, low: low });
const rightEyeLid = getEyeOpen(lm, "right", { high: high, low: low });
const leftEyeLid = getEyeOpen(lm, LEFT, { high: high, low: low });
const rightEyeLid = getEyeOpen(lm, RIGHT, { high: high, low: low });

return {
l: leftEyeLid.norm || 0,
Expand All @@ -225,8 +226,8 @@ export const calcPupils = (lm: Results) => {
return { x: 0, y: 0 };
} else {
//track pupils using left eye
const pupilL = pupilPos(lm, "left");
const pupilR = pupilPos(lm, "right");
const pupilL = pupilPos(lm, LEFT);
const pupilR = pupilPos(lm, RIGHT);

return {
x: (pupilL.x + pupilR.x) * 0.5 || 0,
Expand All @@ -238,9 +239,9 @@ export const calcPupils = (lm: Results) => {
/**
* Calculate brow raise
* @param {Results} lm : array of results from tfjs or mediapipe
* @param {String} side : designate "left" or "right"
* @param {Side} side : designate left or right
*/
export const getBrowRaise = (lm: Results, side: "left" | "right" = "left") => {
export const getBrowRaise = (lm: Results, side: Side = LEFT) => {
const browPoints = points.brow[side];
const browDistance = eyeLidRatio(
lm[browPoints[0]],
Expand Down Expand Up @@ -269,8 +270,8 @@ export const calcBrow = (lm: Results) => {
if (lm.length !== 478) {
return 0;
} else {
const leftBrow = getBrowRaise(lm, "left");
const rightBrow = getBrowRaise(lm, "right");
const leftBrow = getBrowRaise(lm, LEFT);
const rightBrow = getBrowRaise(lm, RIGHT);
return (leftBrow + rightBrow) / 2 || 0;
}
};
35 changes: 18 additions & 17 deletions src/HandSolver/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import Vector from "../utils/vector";
import { clamp } from "../utils/helpers";
import { Results, THand, THandUnsafe } from "../Types";
import { Results, THand, THandUnsafe, Side } from "../Types";
import { RIGHT, LEFT } from "./../constants";

/** Class representing hand solver. */
export class HandSolver {
/**
* Calculates finger and wrist as euler rotations
* @param {Array} lm : array of 3D hand vectors from tfjs or mediapipe
* @param {String} side: "Left" or "Right"
* @param {Side} side: left or right
*/
static solve(lm: Results, side: "Left" | "Right" = "Right"): THand<typeof side> | undefined {
static solve(lm: Results, side: Side = RIGHT): THand<typeof side> | undefined {
if (!lm) {
console.error("Need Hand Landmarks");
return;
}
const palm = [
new Vector(lm[0]),
new Vector(lm[side === "Right" ? 17 : 5]),
new Vector(lm[side === "Right" ? 5 : 17]),
new Vector(lm[side === RIGHT ? 17 : 5]),
new Vector(lm[side === RIGHT ? 5 : 17]),
];
const handRotation = Vector.rollPitchYaw(palm[0], palm[1], palm[2]);
handRotation.y = handRotation.z;
handRotation.y -= side === "Left" ? 0.4 : 0.4;
handRotation.y -= side === LEFT ? 0.4 : 0.4;

let hand: Record<string, unknown> = {};
hand[side + "Wrist"] = { x: handRotation.x, y: handRotation.y, z: handRotation.z };
Expand Down Expand Up @@ -50,19 +51,19 @@ export class HandSolver {
/**
* Converts normalized rotation values into radians clamped by human limits
* @param {Object} hand : object of labeled joint with normalized rotation values
* @param {String} side : "Left" or "Right"
* @param {Side} side : left or right
*/
const rigFingers = (hand: THandUnsafe<typeof side>, side: "Right" | "Left" = "Right"): THand<typeof side> => {
const rigFingers = (hand: THandUnsafe<typeof side>, side: Side = RIGHT): THand<typeof side> => {
// Invert modifier based on left vs right side
const invert = side === "Right" ? 1 : -1;
const invert = side === RIGHT ? 1 : -1;
const digits = ["Ring", "Index", "Little", "Thumb", "Middle"];
const segments = ["Proximal", "Intermediate", "Distal"];

hand[side + "Wrist"].x = clamp(hand[side + "Wrist"].x * 2 * invert, -0.3, 0.3); // twist
hand[side + "Wrist"].y = clamp(
hand[side + "Wrist"].y * 2.3,
side === "Right" ? -1.2 : -0.6,
side === "Right" ? 0.6 : 1.6
side === RIGHT ? -1.2 : -0.6,
side === RIGHT ? 0.6 : 1.6
);
hand[side + "Wrist"].z = hand[side + "Wrist"].z * -2.3 * invert; //left right

Expand All @@ -86,14 +87,14 @@ const rigFingers = (hand: THandUnsafe<typeof side>, side: "Right" | "Left" = "Ri
if (j === "Proximal") {
newThumb.z = clamp(
startPos.z + trackedFinger.z * -Math.PI * dampener.z * invert,
side === "Right" ? -0.6 : -0.3,
side === "Right" ? 0.3 : 0.6
side === RIGHT ? -0.6 : -0.3,
side === RIGHT ? 0.3 : 0.6
);
newThumb.x = clamp(startPos.x + trackedFinger.z * -Math.PI * dampener.x, -0.6, 0.3);
newThumb.y = clamp(
startPos.y + trackedFinger.z * -Math.PI * dampener.y * invert,
side === "Right" ? -1 : -0.3,
side === "Right" ? 0.3 : 1
side === RIGHT ? -1 : -0.3,
side === RIGHT ? 0.3 : 1
);
} else {
newThumb.z = clamp(startPos.z + trackedFinger.z * -Math.PI * dampener.z * invert, -2, 2);
Expand All @@ -107,8 +108,8 @@ const rigFingers = (hand: THandUnsafe<typeof side>, side: "Right" | "Left" = "Ri
//will document human limits later
trackedFinger.z = clamp(
trackedFinger.z * -Math.PI * invert,
side === "Right" ? -Math.PI : 0,
side === "Right" ? 0 : Math.PI
side === RIGHT ? -PI : 0,
side === RIGHT ? 0 : PI
);
}
});
Expand Down
13 changes: 7 additions & 6 deletions src/PoseSolver/calcArms.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Vector from "../utils/vector";
import { clamp } from "../utils/helpers";
import { Results } from "../Types";
import { Results, Side } from "../Types";
import { RIGHT, LEFT } from "./../constants";

/**
* Calculates arm rotation as euler angles
Expand Down Expand Up @@ -35,8 +36,8 @@ export const calcArms = (lm: Results) => {
};

//Modify Rotations slightly for more natural movement
const rightArmRig = rigArm(UpperArm.r, LowerArm.r, Hand.r, "Right");
const leftArmRig = rigArm(UpperArm.l, LowerArm.l, Hand.l, "Left");
const rightArmRig = rigArm(UpperArm.r, LowerArm.r, Hand.r, RIGHT);
const leftArmRig = rigArm(UpperArm.l, LowerArm.l, Hand.l, LEFT);

return {
//Scaled
Expand Down Expand Up @@ -66,11 +67,11 @@ export const calcArms = (lm: Results) => {
* @param {Object} UpperArm : normalized rotation values
* @param {Object} LowerArm : normalized rotation values
* @param {Object} Hand : normalized rotation values
* @param {String} side : "Left" or "Right"
* @param {Side} side : left or right
*/
export const rigArm = (UpperArm: Vector, LowerArm: Vector, Hand: Vector, side: "Left" | "Right" = "Right") => {
export const rigArm = (UpperArm: Vector, LowerArm: Vector, Hand: Vector, side: Side = RIGHT) => {
// Invert modifier based on left vs right side
const invert = side === "Right" ? 1 : -1;
const invert = side === RIGHT ? 1 : -1;

UpperArm.z *= -2.3 * invert;
//Modify UpperArm rotationY by LowerArm X and Z rotations
Expand Down
9 changes: 5 additions & 4 deletions src/PoseSolver/calcLegs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Vector from "../utils/vector";
import { clamp } from "../utils/helpers";
import { Results } from "../Types";
import { Results, Side } from "../Types";
import { RIGHT, LEFT } from "./../constants";

/**
* Calculates arm rotation as euler angles
Expand Down Expand Up @@ -56,13 +57,13 @@ export const calcLegs = (lm: Results) => {
* Converts normalized rotation values into radians clamped by human limits
* @param {Object} UpperLeg : normalized rotation values
* @param {Object} LowerLeg : normalized rotation values
* @param {String} side : "Left" or "Right"
* @param {Side} side : left or right
*/
export const rigLeg = (UpperLeg: Vector, LowerLeg: Vector, side = "Right") => {
const invert = side === "Right" ? 1 : -1;
UpperLeg.z = UpperLeg.z * -2.3 * invert;
UpperLeg.x = clamp(UpperLeg.z * 0.1 * invert, -0.5, Math.PI);
LowerLeg.x = LowerLeg.x * -2.14 * 1.3;
export const rigLeg = (UpperLeg: Vector, LowerLeg: Vector, side: Side = RIGHT) => {
const invert = side === RIGHT ? 1 : -1;
return {
// do not use. leg values are inaccurate
UpperLeg: UpperLeg,
Expand Down
12 changes: 9 additions & 3 deletions src/Types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Vector from "./utils/vector";

import { RIGHT, LEFT } from "./constants";
export interface ISolveOptions {
/**
* Runtime for the solver.
Expand Down Expand Up @@ -42,6 +43,11 @@ export interface IPoseSolveOptions extends ISolveOptions {
enableLegs: boolean;
}

/**
* The left or the right side
*/
export type Side = typeof RIGHT | typeof LEFT;

export type XYZ = Record<"x" | "y" | "z", number>;

export type LR<T = Vector> = Record<"l" | "r", T>;
Expand All @@ -67,7 +73,7 @@ export type TPose = {
Spine: Vector | XYZ;
};

export type HandKeys<S extends "Right" | "Left"> = `${S}${
export type HandKeys<S extends Side> = `${S}${
| "Wrist"
| "RingProximal"
| "RingIntermediate"
Expand All @@ -84,8 +90,8 @@ export type HandKeys<S extends "Right" | "Left"> = `${S}${
| "LittleProximal"
| "LittleIntermediate"
| "LittleDistal"}`;
export type THand<S extends "Right" | "Left"> = Record<HandKeys<S>, XYZ>;
export type THandUnsafe<S extends "Right" | "Left"> = Record<HandKeys<S> | string, XYZ>;
export type THand<S extends Side> = Record<HandKeys<S>, XYZ>;
export type THandUnsafe<S extends Side> = Record<HandKeys<S> | string, XYZ>;

export type TFace = {
head: {
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const RIGHT = "Right";
export const LEFT = "Left";

0 comments on commit b120870

Please sign in to comment.