From 074d315c9fe7cdf3280e475f77bb95948a9c98e4 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 21 May 2024 11:31:53 +0530 Subject: [PATCH] We need both --- .../photos/src/services/face/transform-box.ts | 53 +++++++++++++++++++ web/docs/dependencies.md | 17 ++++-- 2 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 web/apps/photos/src/services/face/transform-box.ts diff --git a/web/apps/photos/src/services/face/transform-box.ts b/web/apps/photos/src/services/face/transform-box.ts new file mode 100644 index 000000000..0a4acb409 --- /dev/null +++ b/web/apps/photos/src/services/face/transform-box.ts @@ -0,0 +1,53 @@ +import { Box, Point } from "services/face/geom"; +import type { FaceDetection } from "services/face/types"; +import { + Matrix, + applyToPoint, + compose, + scale, + translate, +} from "transformation-matrix"; + +/** + * Transform the given {@link faceDetections} from their coordinate system in + * which they were detected ({@link inBox}) back to the coordinate system of the + * original image ({@link toBox}). + */ +export const transformFaceDetections = ( + faceDetections: FaceDetection[], + inBox: Box, + toBox: Box, +): FaceDetection[] => { + const transform = boxTransformationMatrix(inBox, toBox); + return faceDetections.map((f) => ({ + box: transformBox(f.box, transform), + landmarks: f.landmarks.map((p) => transformPoint(p, transform)), + probability: f.probability, + })); +}; + +const boxTransformationMatrix = (inBox: Box, toBox: Box): Matrix => + compose( + translate(toBox.x, toBox.y), + scale(toBox.width / inBox.width, toBox.height / inBox.height), + ); + +const transformPoint = (point: Point, transform: Matrix) => { + const txdPoint = applyToPoint(transform, point); + return new Point(txdPoint.x, txdPoint.y); +}; + +const transformBox = (box: Box, transform: Matrix) => { + const topLeft = transformPoint(new Point(box.x, box.y), transform); + const bottomRight = transformPoint( + new Point(box.x + box.width, box.y + box.height), + transform, + ); + + return new Box({ + x: topLeft.x, + y: topLeft.y, + width: bottomRight.x - topLeft.x, + height: bottomRight.y - topLeft.y, + }); +}; diff --git a/web/docs/dependencies.md b/web/docs/dependencies.md index f5082b9f3..2ff8e4017 100644 --- a/web/docs/dependencies.md +++ b/web/docs/dependencies.md @@ -177,12 +177,19 @@ some cases. ## Face search -- [matrix](https://github.com/mljs/matrix) and - [similarity-transformation](https://github.com/shaileshpandit/similarity-transformation-js) - are used during face alignment. - - [transformation-matrix](https://github.com/chrvadala/transformation-matrix) - is used during face detection. + is used for performing 2D affine transformations using transformation + matrices. It is used during face detection. + +- [matrix](https://github.com/mljs/matrix) is mathematical matrix abstraction. + It is used alongwith + [similarity-transformation](https://github.com/shaileshpandit/similarity-transformation-js) + during face alignment. + + > Note that while both `transformation-matrix` and `matrix` are "matrix" + > libraries, they have different foci and purposes: `transformation-matrix` + > provides affine transforms, while `matrix` is for performing computations + > on matrices, say inverting them or performing their decomposition. - [hdbscan](https://github.com/shaileshpandit/hdbscan-js) is used for face clustering.