exclude impossible detected face boxes
parent
6cafeafba1
commit
2fce7338dc
|
@ -9,11 +9,12 @@
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### **HEAD -> master** 2022/04/01 mandic00@live.com
|
||||||
|
|
||||||
|
|
||||||
### **1.6.7** 2022/04/01 mandic00@live.com
|
### **1.6.7** 2022/04/01 mandic00@live.com
|
||||||
|
|
||||||
|
- fixed typo error (#97)
|
||||||
### **origin/master** 2022/03/10 45914394+abdemirza@users.noreply.github.com
|
|
||||||
|
|
||||||
|
|
||||||
### **1.6.6** 2022/03/04 mandic00@live.com
|
### **1.6.6** 2022/03/04 mandic00@live.com
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -57,15 +57,15 @@
|
||||||
"@tensorflow/tfjs-node-gpu": "^3.15.0",
|
"@tensorflow/tfjs-node-gpu": "^3.15.0",
|
||||||
"@types/node": "^17.0.23",
|
"@types/node": "^17.0.23",
|
||||||
"@types/offscreencanvas": "^2019.6.4",
|
"@types/offscreencanvas": "^2019.6.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
"@typescript-eslint/eslint-plugin": "^5.18.0",
|
||||||
"@typescript-eslint/parser": "^5.17.0",
|
"@typescript-eslint/parser": "^5.18.0",
|
||||||
"@vladmandic/build": "^0.7.2",
|
"@vladmandic/build": "^0.7.2",
|
||||||
"@vladmandic/pilogger": "^0.4.4",
|
"@vladmandic/pilogger": "^0.4.4",
|
||||||
"@vladmandic/tfjs": "github:vladmandic/tfjs",
|
"@vladmandic/tfjs": "github:vladmandic/tfjs",
|
||||||
"canvas": "^2.9.1",
|
"canvas": "^2.9.1",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"dayjs": "^1.11.0",
|
"dayjs": "^1.11.0",
|
||||||
"esbuild": "^0.14.29",
|
"esbuild": "^0.14.31",
|
||||||
"eslint": "^8.12.0",
|
"eslint": "^8.12.0",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
|
|
|
@ -128,9 +128,7 @@ export class Box<BoxType = any> implements IBoundingBox, IRect {
|
||||||
this.width + padX,
|
this.width + padX,
|
||||||
this.height + padY,
|
this.height + padY,
|
||||||
];
|
];
|
||||||
return new Box({
|
return new Box({ x, y, width, height });
|
||||||
x, y, width, height,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public clipAtImageBorders(imgWidth: number, imgHeight: number): Box<BoxType> {
|
public clipAtImageBorders(imgWidth: number, imgHeight: number): Box<BoxType> {
|
||||||
|
@ -143,9 +141,7 @@ export class Box<BoxType = any> implements IBoundingBox, IRect {
|
||||||
const clippedWidth = Math.min(newWidth, imgWidth - clippedX);
|
const clippedWidth = Math.min(newWidth, imgWidth - clippedX);
|
||||||
const clippedHeight = Math.min(newHeight, imgHeight - clippedY);
|
const clippedHeight = Math.min(newHeight, imgHeight - clippedY);
|
||||||
|
|
||||||
return (new Box({
|
return (new Box({ x: clippedX, y: clippedY, width: clippedWidth, height: clippedHeight })).floor();
|
||||||
x: clippedX, y: clippedY, width: clippedWidth, height: clippedHeight,
|
|
||||||
})).floor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public shift(sx: number, sy: number): Box<BoxType> {
|
public shift(sx: number, sy: number): Box<BoxType> {
|
||||||
|
@ -153,9 +149,7 @@ export class Box<BoxType = any> implements IBoundingBox, IRect {
|
||||||
const x = this.x + sx;
|
const x = this.x + sx;
|
||||||
const y = this.y + sy;
|
const y = this.y + sy;
|
||||||
|
|
||||||
return new Box({
|
return new Box({ x, y, width, height });
|
||||||
x, y, width, height,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public padAtBorders(imageHeight: number, imageWidth: number) {
|
public padAtBorders(imageHeight: number, imageWidth: number) {
|
||||||
|
@ -189,9 +183,7 @@ export class Box<BoxType = any> implements IBoundingBox, IRect {
|
||||||
y = 1;
|
y = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return { dy, edy, dx, edx, y, ey, x, ex, w, h };
|
||||||
dy, edy, dx, edx, y, ey, x, ex, w, h,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public calibrate(region: Box) {
|
public calibrate(region: Box) {
|
||||||
|
|
|
@ -25,17 +25,11 @@ export async function extractFaceTensors(imageTensor: tf.Tensor3D | tf.Tensor4D,
|
||||||
|
|
||||||
return tf.tidy(() => {
|
return tf.tidy(() => {
|
||||||
const [imgHeight, imgWidth, numChannels] = imageTensor.shape.slice(isTensor4D(imageTensor) ? 1 : 0);
|
const [imgHeight, imgWidth, numChannels] = imageTensor.shape.slice(isTensor4D(imageTensor) ? 1 : 0);
|
||||||
|
const boxes = detections.map((det) => (det instanceof FaceDetection ? det.forSize(imgWidth, imgHeight).box : det))
|
||||||
const boxes = detections
|
|
||||||
.map((det) => (det instanceof FaceDetection
|
|
||||||
? det.forSize(imgWidth, imgHeight).box
|
|
||||||
: det))
|
|
||||||
.map((box) => box.clipAtImageBorders(imgWidth, imgHeight));
|
.map((box) => box.clipAtImageBorders(imgWidth, imgHeight));
|
||||||
|
const faceTensors = boxes
|
||||||
const faceTensors = boxes.map(({
|
.filter((box) => box.width > 0 && box.height > 0)
|
||||||
x, y, width, height,
|
.map(({ x, y, width, height }) => tf.slice3d(imageTensor.as3D(imgHeight, imgWidth, numChannels), [y, x, 0], [height, width, numChannels]));
|
||||||
}) => tf.slice3d(imageTensor.as3D(imgHeight, imgWidth, numChannels), [y, x, 0], [height, width, numChannels]));
|
|
||||||
|
|
||||||
return faceTensors;
|
return faceTensors;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,12 +57,9 @@ function calculateFaceAngle(mesh) {
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extendWithFaceLandmarks<
|
export function extendWithFaceLandmarks<TSource extends WithFaceDetection<{}>, TFaceLandmarks extends FaceLandmarks = FaceLandmarks68 >(sourceObj: TSource, unshiftedLandmarks: TFaceLandmarks): WithFaceLandmarks<TSource, TFaceLandmarks> {
|
||||||
TSource extends WithFaceDetection<{}>,
|
|
||||||
TFaceLandmarks extends FaceLandmarks = FaceLandmarks68 >(sourceObj: TSource, unshiftedLandmarks: TFaceLandmarks): WithFaceLandmarks<TSource, TFaceLandmarks> {
|
|
||||||
const { box: shift } = sourceObj.detection;
|
const { box: shift } = sourceObj.detection;
|
||||||
const landmarks = unshiftedLandmarks.shiftBy<TFaceLandmarks>(shift.x, shift.y);
|
const landmarks = unshiftedLandmarks.shiftBy<TFaceLandmarks>(shift.x, shift.y);
|
||||||
|
|
||||||
const rect = landmarks.align();
|
const rect = landmarks.align();
|
||||||
const { imageDims } = sourceObj.detection;
|
const { imageDims } = sourceObj.detection;
|
||||||
const alignedRect = new FaceDetection(sourceObj.detection.score, rect.rescale(imageDims.reverse()), imageDims);
|
const alignedRect = new FaceDetection(sourceObj.detection.score, rect.rescale(imageDims.reverse()), imageDims);
|
||||||
|
|
|
@ -39,11 +39,12 @@ export class DetectAllFaceLandmarksTask<TSource extends WithFaceDetection<{}>> e
|
||||||
const faces: Array<HTMLCanvasElement | tf.Tensor3D> = this.input instanceof tf.Tensor
|
const faces: Array<HTMLCanvasElement | tf.Tensor3D> = this.input instanceof tf.Tensor
|
||||||
? await extractFaceTensors(this.input, detections)
|
? await extractFaceTensors(this.input, detections)
|
||||||
: await extractFaces(this.input, detections);
|
: await extractFaces(this.input, detections);
|
||||||
const faceLandmarksByFace = await Promise.all(
|
const faceLandmarksByFace = await Promise.all(faces.map((face) => this.landmarkNet.detectLandmarks(face))) as FaceLandmarks68[];
|
||||||
faces.map((face) => this.landmarkNet.detectLandmarks(face)),
|
|
||||||
) as FaceLandmarks68[];
|
|
||||||
faces.forEach((f) => f instanceof tf.Tensor && f.dispose());
|
faces.forEach((f) => f instanceof tf.Tensor && f.dispose());
|
||||||
return parentResults.map((parentResult, i) => extendWithFaceLandmarks<TSource>(parentResult, faceLandmarksByFace[i]));
|
const result = parentResults
|
||||||
|
.filter((_parentResult, i) => faceLandmarksByFace[i])
|
||||||
|
.map((parentResult, i) => extendWithFaceLandmarks<TSource>(parentResult, faceLandmarksByFace[i]));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
withFaceExpressions() {
|
withFaceExpressions() {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue