FaceLandmark68NetBase.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { __awaiter, __extends, __generator } from "tslib";
  2. import * as tf from '@tensorflow/tfjs-core';
  3. import { Point } from '../classes';
  4. import { FaceLandmarks68 } from '../classes/FaceLandmarks68';
  5. import { toNetInput } from '../dom';
  6. import { FaceProcessor } from '../faceProcessor/FaceProcessor';
  7. import { isEven } from '../utils';
  8. var FaceLandmark68NetBase = /** @class */ (function (_super) {
  9. __extends(FaceLandmark68NetBase, _super);
  10. function FaceLandmark68NetBase() {
  11. return _super !== null && _super.apply(this, arguments) || this;
  12. }
  13. FaceLandmark68NetBase.prototype.postProcess = function (output, inputSize, originalDimensions) {
  14. var inputDimensions = originalDimensions.map(function (_a) {
  15. var width = _a.width, height = _a.height;
  16. var scale = inputSize / Math.max(height, width);
  17. return {
  18. width: width * scale,
  19. height: height * scale
  20. };
  21. });
  22. var batchSize = inputDimensions.length;
  23. return tf.tidy(function () {
  24. var createInterleavedTensor = function (fillX, fillY) {
  25. return tf.stack([
  26. tf.fill([68], fillX),
  27. tf.fill([68], fillY)
  28. ], 1).as2D(1, 136).as1D();
  29. };
  30. var getPadding = function (batchIdx, cond) {
  31. var _a = inputDimensions[batchIdx], width = _a.width, height = _a.height;
  32. return cond(width, height) ? Math.abs(width - height) / 2 : 0;
  33. };
  34. var getPaddingX = function (batchIdx) { return getPadding(batchIdx, function (w, h) { return w < h; }); };
  35. var getPaddingY = function (batchIdx) { return getPadding(batchIdx, function (w, h) { return h < w; }); };
  36. var landmarkTensors = output
  37. .mul(tf.fill([batchSize, 136], inputSize))
  38. .sub(tf.stack(Array.from(Array(batchSize), function (_, batchIdx) {
  39. return createInterleavedTensor(getPaddingX(batchIdx), getPaddingY(batchIdx));
  40. })))
  41. .div(tf.stack(Array.from(Array(batchSize), function (_, batchIdx) {
  42. return createInterleavedTensor(inputDimensions[batchIdx].width, inputDimensions[batchIdx].height);
  43. })));
  44. return landmarkTensors;
  45. });
  46. };
  47. FaceLandmark68NetBase.prototype.forwardInput = function (input) {
  48. var _this = this;
  49. return tf.tidy(function () {
  50. var out = _this.runNet(input);
  51. return _this.postProcess(out, input.inputSize, input.inputDimensions.map(function (_a) {
  52. var height = _a[0], width = _a[1];
  53. return ({ height: height, width: width });
  54. }));
  55. });
  56. };
  57. FaceLandmark68NetBase.prototype.forward = function (input) {
  58. return __awaiter(this, void 0, void 0, function () {
  59. var _a;
  60. return __generator(this, function (_b) {
  61. switch (_b.label) {
  62. case 0:
  63. _a = this.forwardInput;
  64. return [4 /*yield*/, toNetInput(input)];
  65. case 1: return [2 /*return*/, _a.apply(this, [_b.sent()])];
  66. }
  67. });
  68. });
  69. };
  70. FaceLandmark68NetBase.prototype.detectLandmarks = function (input) {
  71. return __awaiter(this, void 0, void 0, function () {
  72. var netInput, landmarkTensors, landmarksForBatch;
  73. var _this = this;
  74. return __generator(this, function (_a) {
  75. switch (_a.label) {
  76. case 0: return [4 /*yield*/, toNetInput(input)];
  77. case 1:
  78. netInput = _a.sent();
  79. landmarkTensors = tf.tidy(function () { return tf.unstack(_this.forwardInput(netInput)); });
  80. return [4 /*yield*/, Promise.all(landmarkTensors.map(function (landmarkTensor, batchIdx) { return __awaiter(_this, void 0, void 0, function () {
  81. var landmarksArray, _a, _b, xCoords, yCoords;
  82. return __generator(this, function (_c) {
  83. switch (_c.label) {
  84. case 0:
  85. _b = (_a = Array).from;
  86. return [4 /*yield*/, landmarkTensor.data()];
  87. case 1:
  88. landmarksArray = _b.apply(_a, [_c.sent()]);
  89. xCoords = landmarksArray.filter(function (_, i) { return isEven(i); });
  90. yCoords = landmarksArray.filter(function (_, i) { return !isEven(i); });
  91. return [2 /*return*/, new FaceLandmarks68(Array(68).fill(0).map(function (_, i) { return new Point(xCoords[i], yCoords[i]); }), {
  92. height: netInput.getInputHeight(batchIdx),
  93. width: netInput.getInputWidth(batchIdx),
  94. })];
  95. }
  96. });
  97. }); }))];
  98. case 2:
  99. landmarksForBatch = _a.sent();
  100. landmarkTensors.forEach(function (t) { return t.dispose(); });
  101. return [2 /*return*/, netInput.isBatchInput
  102. ? landmarksForBatch
  103. : landmarksForBatch[0]];
  104. }
  105. });
  106. });
  107. };
  108. FaceLandmark68NetBase.prototype.getClassifierChannelsOut = function () {
  109. return 136;
  110. };
  111. return FaceLandmark68NetBase;
  112. }(FaceProcessor));
  113. export { FaceLandmark68NetBase };
  114. //# sourceMappingURL=FaceLandmark68NetBase.js.map