I am following a face recognition algorithm but I need to rotate all faces to align them vertically to its rectangle.
The face rectangle is not rotated (its angle is 0) and it contains the full face that has been recognised. The face sometimes is rotated "faceAngle" degrees, so what I have implement is a function that rotate it (the face) "-faceAngle" degrees with the center of the face rectangle as pivot point (the point of reference).
Pd: The face is identified by 20 landmarks.
This is how the face rectangle looks like: https://docs.microsoft.com/es-es/azure/cognitive-services/face/images/face.detection.jpg
Here is my code:
function rotateFace(face) {
/*
This function rotate the face to the rectangle based on the head pose attributes
*/
// Get the face information
const { faceRectangle, faceLandmarks, faceAttributes } = face;
// Head pose's roll value acts directly as the face angle.
const faceAngle = faceAttributes.headPose.roll; // In degrees
// The pivot point will be the center of the face rectangle
const pivotPoint = {
x: faceRectangle.width / 2,
y: faceRectangle.height / 2,
};
// Rotate each face landmark '-faceAngle' degrees
const rotatedLandmarks = {};
for (const [landMark, point] of Object.entries(faceLandmarks)) {
// Rotate the point and save it in the new rotated landMarks object
rotatedLandmarks[landMark] = rotatePoint(pivotPoint, point, -faceAngle);
}
// Return the rotated face
return { ...face, faceLandmarks: rotatedLandmarks };
function rotatePoint(pivotPoint, point, angle) {
const { x: px, y: py } = pivotPoint;
const { x, y } = point;
var radians = (Math.PI / 180) * angle,
cos = Math.cos(radians),
sin = Math.sin(radians),
nx = cos * (x - px) + sin * (y - py) + px,
ny = cos * (y - py) - sin * (x - px) + py;
return { x: nx, y: ny };
}
}
The problem I am having is that, sometimes, some parts of the rotated face are outside the face rectangle... Does anybody knows what I am doing bad in my algorithm? Or any ideas how to make this easier?
I think the pivot point shouldn't be the one I choosed but it makes sense for my mind...
Thank you.
EXAMPLE
For this photo https://scstylecaster.files.wordpress.com/2017/03/emma-watson-1.jpg
I get this face rectangle:
faceRectangle: {
top: 90,
left: 309,
width: 510,
height: 510
}
So the relative-to-rectangle face landmarks should be at the range [0, 510] for the X axis, and [0, 510] for the Y axis
But that I get is:
{
"eyebrowRightInner": { "x": 257.16357408506883, "y": 37.89185642687593 },
"underLipTop": { "y": 306.6951578378977, "x": 326.5280833858301 },
"mouthRight": { "x": 413.55677612276986, "y": 257.5870460792551 },
"eyebrowLeftInner": { "y": 67.10580836435113, "x": 168.71276847994784 },
"noseTip": { "y": 206.5354065431846, "x": 289.9445594907593 },
"noseRootLeft": { "y": 112.52684633627678, "x": 204.9452029765821 },
"noseRightAlarTop": { "x": 311.41755898744964, "y": 159.77912041377596 },
"pupilRight": { "x": 315.13546073674706, "y": 48.933158797745136 },
"pupilLeft": { "x": 106.47397872844112, "y": 137.8818851860268 },
"upperLipTop": { "y": 280.73055222306243, "x": 312.3126250651826 },
"eyeRightOuter": { "y": 37.448988851675836, "x": 371.07188751438275 },
"eyebrowRightOuter": { "y": -16.27549040986449, "x": 413.1946880869507 }, // <------------------ error
"eyeLeftOuter": { "y": 154.79417336302782, "x": 82.3579154382175 },
"upperLipBottom": { "y": 302.33231999033967, "x": 324.86506026034 },
"noseLeftAlarOutTip": { "y": 244.55778079547065, "x": 220.11663487446322 },
"noseLeftAlarTop": { "x": 220.08119281608163, "y": 200.35236547267908 },
"eyeLeftBottom": { "y": 154.39022448200217, "x": 120.07378511268632 },
"noseRightAlarOutTip": { "x": 350.8688839396136, "y": 182.97767553082463 },
"eyebrowLeftOuter": { "x": 12.151092571862137, "y": 146.8442033623165 },
"eyeRightBottom": { "x": 337.62439624997774, "y": 64.52859978162735 },
"eyeLeftTop": { "y": 124.33543005444903, "x": 103.84081459224478 },
"underLipBottom": { "y": 332.64619899450827, "x": 341.8614934073455 },
"noseRootRight": { "y": 86.3352712525471, "x": 268.4137100854889 },
"eyeLeftInner": { "x": 154.06657444677165, "y": 128.0195917006581 },
"eyeRightInner": { "x": 294.24199118290403, "y": 71.94256839474764 },
"eyeRightTop": { "x": 320.5652039630463, "y": 34.94002160494745 },
"mouthLeft": { "y": 346.12770549550777, "x": 220.09672435462016 }
}