FaceLandmarks.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { minBbox } from '../ops';
  2. import { getCenterPoint } from '../utils';
  3. import { Box } from './Box';
  4. import { Dimensions } from './Dimensions';
  5. import { FaceDetection } from './FaceDetection';
  6. import { Point } from './Point';
  7. import { Rect } from './Rect';
  8. // face alignment constants
  9. var relX = 0.5;
  10. var relY = 0.43;
  11. var relScale = 0.45;
  12. var FaceLandmarks = /** @class */ (function () {
  13. function FaceLandmarks(relativeFaceLandmarkPositions, imgDims, shift) {
  14. if (shift === void 0) { shift = new Point(0, 0); }
  15. var width = imgDims.width, height = imgDims.height;
  16. this._imgDims = new Dimensions(width, height);
  17. this._shift = shift;
  18. this._positions = relativeFaceLandmarkPositions.map(function (pt) { return pt.mul(new Point(width, height)).add(shift); });
  19. }
  20. Object.defineProperty(FaceLandmarks.prototype, "shift", {
  21. get: function () { return new Point(this._shift.x, this._shift.y); },
  22. enumerable: true,
  23. configurable: true
  24. });
  25. Object.defineProperty(FaceLandmarks.prototype, "imageWidth", {
  26. get: function () { return this._imgDims.width; },
  27. enumerable: true,
  28. configurable: true
  29. });
  30. Object.defineProperty(FaceLandmarks.prototype, "imageHeight", {
  31. get: function () { return this._imgDims.height; },
  32. enumerable: true,
  33. configurable: true
  34. });
  35. Object.defineProperty(FaceLandmarks.prototype, "positions", {
  36. get: function () { return this._positions; },
  37. enumerable: true,
  38. configurable: true
  39. });
  40. Object.defineProperty(FaceLandmarks.prototype, "relativePositions", {
  41. get: function () {
  42. var _this = this;
  43. return this._positions.map(function (pt) { return pt.sub(_this._shift).div(new Point(_this.imageWidth, _this.imageHeight)); });
  44. },
  45. enumerable: true,
  46. configurable: true
  47. });
  48. FaceLandmarks.prototype.forSize = function (width, height) {
  49. return new this.constructor(this.relativePositions, { width: width, height: height });
  50. };
  51. FaceLandmarks.prototype.shiftBy = function (x, y) {
  52. return new this.constructor(this.relativePositions, this._imgDims, new Point(x, y));
  53. };
  54. FaceLandmarks.prototype.shiftByPoint = function (pt) {
  55. return this.shiftBy(pt.x, pt.y);
  56. };
  57. /**
  58. * Aligns the face landmarks after face detection from the relative positions of the faces
  59. * bounding box, or it's current shift. This function should be used to align the face images
  60. * after face detection has been performed, before they are passed to the face recognition net.
  61. * This will make the computed face descriptor more accurate.
  62. *
  63. * @param detection (optional) The bounding box of the face or the face detection result. If
  64. * no argument was passed the position of the face landmarks are assumed to be relative to
  65. * it's current shift.
  66. * @returns The bounding box of the aligned face.
  67. */
  68. FaceLandmarks.prototype.align = function (detection, options) {
  69. if (options === void 0) { options = {}; }
  70. if (detection) {
  71. var box = detection instanceof FaceDetection
  72. ? detection.box.floor()
  73. : new Box(detection);
  74. return this.shiftBy(box.x, box.y).align(null, options);
  75. }
  76. var _a = Object.assign({}, { useDlibAlignment: false, minBoxPadding: 0.2 }, options), useDlibAlignment = _a.useDlibAlignment, minBoxPadding = _a.minBoxPadding;
  77. if (useDlibAlignment) {
  78. return this.alignDlib();
  79. }
  80. return this.alignMinBbox(minBoxPadding);
  81. };
  82. FaceLandmarks.prototype.alignDlib = function () {
  83. var centers = this.getRefPointsForAlignment();
  84. var leftEyeCenter = centers[0], rightEyeCenter = centers[1], mouthCenter = centers[2];
  85. var distToMouth = function (pt) { return mouthCenter.sub(pt).magnitude(); };
  86. var eyeToMouthDist = (distToMouth(leftEyeCenter) + distToMouth(rightEyeCenter)) / 2;
  87. var size = Math.floor(eyeToMouthDist / relScale);
  88. var refPoint = getCenterPoint(centers);
  89. // TODO: pad in case rectangle is out of image bounds
  90. var x = Math.floor(Math.max(0, refPoint.x - (relX * size)));
  91. var y = Math.floor(Math.max(0, refPoint.y - (relY * size)));
  92. return new Rect(x, y, Math.min(size, this.imageWidth + x), Math.min(size, this.imageHeight + y));
  93. };
  94. FaceLandmarks.prototype.alignMinBbox = function (padding) {
  95. var box = minBbox(this.positions);
  96. return box.pad(box.width * padding, box.height * padding);
  97. };
  98. FaceLandmarks.prototype.getRefPointsForAlignment = function () {
  99. throw new Error('getRefPointsForAlignment not implemented by base class');
  100. };
  101. return FaceLandmarks;
  102. }());
  103. export { FaceLandmarks };
  104. //# sourceMappingURL=FaceLandmarks.js.map