Inline
This commit is contained in:
parent
8efe47cffb
commit
77bacc518c
4 changed files with 85 additions and 93 deletions
|
@ -5,15 +5,14 @@ import {
|
|||
Face,
|
||||
MLSyncContext,
|
||||
MLSyncFileContext,
|
||||
type FaceAlignment,
|
||||
type Versioned,
|
||||
} from "services/ml/types";
|
||||
import { imageBitmapToBlob } from "utils/image";
|
||||
import { imageBitmapToBlob, warpAffineFloat32List } from "utils/image";
|
||||
import {
|
||||
areFaceIdsSame,
|
||||
extractFaceImagesToFloat32,
|
||||
getFaceId,
|
||||
getLocalFile,
|
||||
getOriginalImageBitmap,
|
||||
isDifferentOrOld,
|
||||
} from "utils/machineLearning";
|
||||
import mlIDbStorage from "utils/storage/mlIDbStorage";
|
||||
import ReaderService from "./readerService";
|
||||
|
@ -304,3 +303,58 @@ class FaceService {
|
|||
}
|
||||
|
||||
export default new FaceService();
|
||||
|
||||
export function areFaceIdsSame(ofFaces: Array<Face>, toFaces: Array<Face>) {
|
||||
if (
|
||||
(ofFaces === null || ofFaces === undefined) &&
|
||||
(toFaces === null || toFaces === undefined)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return primitiveArrayEquals(
|
||||
ofFaces?.map((f) => f.id),
|
||||
toFaces?.map((f) => f.id),
|
||||
);
|
||||
}
|
||||
|
||||
function primitiveArrayEquals(a, b) {
|
||||
return (
|
||||
Array.isArray(a) &&
|
||||
Array.isArray(b) &&
|
||||
a.length === b.length &&
|
||||
a.every((val, index) => val === b[index])
|
||||
);
|
||||
}
|
||||
|
||||
export function isDifferentOrOld(
|
||||
method: Versioned<string>,
|
||||
thanMethod: Versioned<string>,
|
||||
) {
|
||||
return (
|
||||
!method ||
|
||||
method.value !== thanMethod.value ||
|
||||
method.version < thanMethod.version
|
||||
);
|
||||
}
|
||||
|
||||
async function extractFaceImagesToFloat32(
|
||||
faceAlignments: Array<FaceAlignment>,
|
||||
faceSize: number,
|
||||
image: ImageBitmap,
|
||||
): Promise<Float32Array> {
|
||||
const faceData = new Float32Array(
|
||||
faceAlignments.length * faceSize * faceSize * 3,
|
||||
);
|
||||
for (let i = 0; i < faceAlignments.length; i++) {
|
||||
const alignedFace = faceAlignments[i];
|
||||
const faceDataOffset = i * faceSize * faceSize * 3;
|
||||
warpAffineFloat32List(
|
||||
image,
|
||||
alignedFace,
|
||||
faceSize,
|
||||
faceData,
|
||||
faceDataOffset,
|
||||
);
|
||||
}
|
||||
return faceData;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
import log from "@/next/log";
|
||||
import { Face, MLSyncContext, Person } from "services/ml/types";
|
||||
import {
|
||||
findFirstIfSorted,
|
||||
getAllFacesFromMap,
|
||||
getLocalFile,
|
||||
getOriginalImageBitmap,
|
||||
isDifferentOrOld,
|
||||
} from "utils/machineLearning";
|
||||
import { getLocalFile, getOriginalImageBitmap } from "utils/machineLearning";
|
||||
import mlIDbStorage from "utils/storage/mlIDbStorage";
|
||||
import FaceService from "./faceService";
|
||||
import FaceService, { isDifferentOrOld } from "./faceService";
|
||||
|
||||
class PeopleService {
|
||||
async syncPeopleIndex(syncContext: MLSyncContext) {
|
||||
|
@ -92,3 +86,28 @@ class PeopleService {
|
|||
}
|
||||
|
||||
export default new PeopleService();
|
||||
|
||||
function findFirstIfSorted<T>(
|
||||
elements: Array<T>,
|
||||
comparator: (a: T, b: T) => number,
|
||||
) {
|
||||
if (!elements || elements.length < 1) {
|
||||
return;
|
||||
}
|
||||
let first = elements[0];
|
||||
|
||||
for (let i = 1; i < elements.length; i++) {
|
||||
const comp = comparator(elements[i], first);
|
||||
if (comp < 0) {
|
||||
first = elements[i];
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
function getAllFacesFromMap(allFacesMap: Map<number, Array<Face>>) {
|
||||
const allFaces = [...allFacesMap.values()].flat();
|
||||
|
||||
return allFaces;
|
||||
}
|
||||
|
|
|
@ -11,46 +11,18 @@ import {
|
|||
FaceAlignment,
|
||||
MlFileData,
|
||||
Person,
|
||||
Versioned,
|
||||
} from "services/ml/types";
|
||||
import { EnteFile } from "types/file";
|
||||
import { getRenderableImage } from "utils/file";
|
||||
import { clamp, warpAffineFloat32List } from "utils/image";
|
||||
import mlIDbStorage from "utils/storage/mlIDbStorage";
|
||||
|
||||
export function getAllFacesFromMap(allFacesMap: Map<number, Array<Face>>) {
|
||||
const allFaces = [...allFacesMap.values()].flat();
|
||||
|
||||
return allFaces;
|
||||
}
|
||||
|
||||
export async function getLocalFile(fileId: number) {
|
||||
const localFiles = await getLocalFiles();
|
||||
return localFiles.find((f) => f.id === fileId);
|
||||
}
|
||||
|
||||
export async function extractFaceImagesToFloat32(
|
||||
faceAlignments: Array<FaceAlignment>,
|
||||
faceSize: number,
|
||||
image: ImageBitmap,
|
||||
): Promise<Float32Array> {
|
||||
const faceData = new Float32Array(
|
||||
faceAlignments.length * faceSize * faceSize * 3,
|
||||
);
|
||||
for (let i = 0; i < faceAlignments.length; i++) {
|
||||
const alignedFace = faceAlignments[i];
|
||||
const faceDataOffset = i * faceSize * faceSize * 3;
|
||||
warpAffineFloat32List(
|
||||
image,
|
||||
alignedFace,
|
||||
faceSize,
|
||||
faceData,
|
||||
faceDataOffset,
|
||||
);
|
||||
}
|
||||
return faceData;
|
||||
}
|
||||
|
||||
export function getFaceId(detectedFace: DetectedFace, imageDims: Dimensions) {
|
||||
const xMin = clamp(
|
||||
detectedFace.detection.box.x / imageDims.width,
|
||||
|
@ -192,56 +164,3 @@ export async function getAllPeople(limit: number = undefined) {
|
|||
.sort((p1, p2) => p2.files.length - p1.files.length)
|
||||
.slice(0, limit);
|
||||
}
|
||||
|
||||
export function findFirstIfSorted<T>(
|
||||
elements: Array<T>,
|
||||
comparator: (a: T, b: T) => number,
|
||||
) {
|
||||
if (!elements || elements.length < 1) {
|
||||
return;
|
||||
}
|
||||
let first = elements[0];
|
||||
|
||||
for (let i = 1; i < elements.length; i++) {
|
||||
const comp = comparator(elements[i], first);
|
||||
if (comp < 0) {
|
||||
first = elements[i];
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
export function isDifferentOrOld(
|
||||
method: Versioned<string>,
|
||||
thanMethod: Versioned<string>,
|
||||
) {
|
||||
return (
|
||||
!method ||
|
||||
method.value !== thanMethod.value ||
|
||||
method.version < thanMethod.version
|
||||
);
|
||||
}
|
||||
|
||||
function primitiveArrayEquals(a, b) {
|
||||
return (
|
||||
Array.isArray(a) &&
|
||||
Array.isArray(b) &&
|
||||
a.length === b.length &&
|
||||
a.every((val, index) => val === b[index])
|
||||
);
|
||||
}
|
||||
|
||||
export function areFaceIdsSame(ofFaces: Array<Face>, toFaces: Array<Face>) {
|
||||
if (
|
||||
(ofFaces === null || ofFaces === undefined) &&
|
||||
(toFaces === null || toFaces === undefined)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return primitiveArrayEquals(
|
||||
ofFaces?.map((f) => f.id),
|
||||
toFaces?.map((f) => f.id),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue