FaceLandmarks.js 5.0 KB

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