Skip to content

Commit 7823443

Browse files
authored
[pose-detection]Update BlazePose OneEuro filter config. (#740)
FEATURE
1 parent 544804b commit 7823443

File tree

12 files changed

+70
-59
lines changed

12 files changed

+70
-59
lines changed

pose-detection/src/blazepose_mediapipe/mediapipe_test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ const MEDIAPIPE_MODEL_CONFIG: BlazePoseMediaPipeModelConfig = {
3030
};
3131

3232
const EPSILON_IMAGE = 10;
33-
const EPSILON_VIDEO = 18;
33+
// TODO(lina128): Reduce video tolerance once MP Web Solution publishes new
34+
// version.
35+
const EPSILON_VIDEO = 42;
3436
// ref:
3537
// https://github.com/google/mediapipe/blob/7c331ad58b2cca0dca468e342768900041d65adc/mediapipe/python/solutions/pose_test.py#L31-L51
3638
const EXPECTED_LANDMARKS = [

pose-detection/src/blazepose_tfjs/blazepose_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import * as poseDetection from '../index';
2525
import {getXYPerFrame, KARMA_SERVER, loadImage, loadVideo} from '../test_util';
2626

2727
const EPSILON_IMAGE = 10;
28-
const EPSILON_VIDEO = 15;
28+
const EPSILON_VIDEO = 18;
2929

3030
// ref:
3131
// https://github.com/google/mediapipe/blob/7c331ad58b2cca0dca468e342768900041d65adc/mediapipe/python/solutions/pose_test.py#L31-L51

pose-detection/src/blazepose_tfjs/constants.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ export const BLAZEPOSE_VISIBILITY_SMOOTHING_CONFIG = {
109109
export const BLAZEPOSE_LANDMARKS_SMOOTHING_CONFIG_ACTUAL = {
110110
oneEuroFilter: {
111111
frequency: 30,
112-
minCutOff: 0.1, // minCutOff 0.1 results into ~0.02 alpha in landmark EMA
113-
// filter when landmark is static.
114-
beta: 40, // beta 40 in combination with minCutOff 0.1 results into ~0.8
112+
minCutOff: 0.05, // minCutOff 0.05 results into ~0.01 alpha in landmark EMA
113+
// filter when landmark is static.
114+
beta: 80, // beta 80 in combination with minCutOff 0.05 results into ~0.94
115115
// alpha in landmark EMA filter when landmark is moving fast.
116116
derivateCutOff: 1.0, // derivativeCutOff 1.0 results into ~0.17 alpha in
117117
// landmark velocity EMA filter.,
@@ -126,8 +126,9 @@ export const BLAZEPOSE_LANDMARKS_SMOOTHING_CONFIG_AUXILIARY = {
126126
frequency: 30,
127127
minCutOff: 0.01, // minCutOff 0.01 results into ~0.002 alpha in landmark
128128
// EMA filter when landmark is static.
129-
beta: 1.0, // beta 1.0 in combination with minCutOff 0.01 results into ~0.2
130-
// alpha in landmark EMA filter when landmark is moving fast.
129+
beta: 10.0, // beta 10.0 in combination with minCutOff 0.01 results into
130+
// ~0.68 alpha in landmark EMA filter when landmark is moving
131+
// fast.
131132
derivateCutOff: 1.0, // derivateCutOff 1.0 results into ~0.17 alpha in
132133
// landmark velocity EMA filter.
133134
minAllowedObjectScale: 1e-6

pose-detection/src/blazepose_tfjs/detector.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,14 @@ class BlazePoseTfjsDetector implements PoseDetector {
439439
actualLandmarksFiltered = actualLandmarks;
440440
auxiliaryLandmarksFiltered = auxiliaryLandmarks;
441441
} else {
442+
const auxDetection = landmarksToDetection(auxiliaryLandmarks);
443+
const objectScaleROI =
444+
calculateAlignmentPointsRects(auxDetection, imageSize, {
445+
rotationVectorEndKeypointIndex: 0,
446+
rotationVectorStartKeypointIndex: 1,
447+
rotationVectorTargetAngleDegree: 90
448+
});
449+
442450
// Smoothes pose landmark visibilities to reduce jitter.
443451
if (this.visibilitySmoothingFilterActual == null) {
444452
this.visibilitySmoothingFilterActual = new LowPassVisibilityFilter(
@@ -461,15 +469,15 @@ class BlazePoseTfjsDetector implements PoseDetector {
461469
}
462470
actualLandmarksFiltered = this.landmarksSmoothingFilterActual.apply(
463471
actualLandmarksFiltered, this.timestamp, imageSize,
464-
true /* normalized */);
472+
true /* normalized */, objectScaleROI);
465473

466474
if (this.landmarksSmoothingFilterAuxiliary == null) {
467475
this.landmarksSmoothingFilterAuxiliary = new KeypointsSmoothingFilter(
468476
constants.BLAZEPOSE_LANDMARKS_SMOOTHING_CONFIG_AUXILIARY);
469477
}
470478
auxiliaryLandmarksFiltered = this.landmarksSmoothingFilterAuxiliary.apply(
471479
auxiliaryLandmarksFiltered, this.timestamp, imageSize,
472-
true /* normalized */);
480+
true /* normalized */, objectScaleROI);
473481
}
474482

475483
return {actualLandmarksFiltered, auxiliaryLandmarksFiltered};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
* =============================================================================
16+
*/
17+
import {ImageSize} from './interfaces/common_interfaces';
18+
import {Rect} from './interfaces/shape_interfaces';
19+
20+
/**
21+
* Estimate object scale to allow filter work similarly on nearer or futher
22+
* objects.
23+
* @param roi Normalized rectangle.
24+
* @param imageSize An object that contains width and height.
25+
* @returns A number representing the object scale.
26+
*/
27+
export function getObjectScale(roi: Rect, imageSize: ImageSize): number {
28+
const objectWidth = roi.width * imageSize.width;
29+
const objectHeight = roi.height * imageSize.height;
30+
31+
return (objectWidth + objectHeight) / 2;
32+
}

pose-detection/src/calculators/interfaces/common_interfaces.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export interface WindowElement {
3939
}
4040

4141
export interface KeypointsFilter {
42-
apply(landmarks: Keypoint[], microSeconds: number): Keypoint[];
42+
apply(landmarks: Keypoint[], microSeconds: number, objectScale: number):
43+
Keypoint[];
4344
reset(): void;
4445
}

pose-detection/src/calculators/keypoints_one_euro_filter.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {Keypoint} from '../types';
2020
import {KeypointsFilter} from './interfaces/common_interfaces';
2121
import {OneEuroFilterConfig} from './interfaces/config_interfaces';
2222
import {OneEuroFilter} from './one_euro_filter';
23-
import {getObjectScale} from './velocity_filter_utils';
2423

2524
/**
2625
* A stateful filter that smoothes keypoints values overtime.
@@ -38,7 +37,8 @@ export class KeypointsOneEuroFilter implements KeypointsFilter {
3837

3938
constructor(private readonly config: OneEuroFilterConfig) {}
4039

41-
apply(keypoints: Keypoint[], microSeconds: number): Keypoint[] {
40+
apply(keypoints: Keypoint[], microSeconds: number, objectScale: number):
41+
Keypoint[] {
4242
if (keypoints == null) {
4343
this.reset();
4444
return null;
@@ -52,7 +52,6 @@ export class KeypointsOneEuroFilter implements KeypointsFilter {
5252
// returned as is.
5353
let valueScale = 1;
5454
if (this.config.minAllowedObjectScale != null) {
55-
const objectScale = getObjectScale(keypoints);
5655
if (objectScale < this.config.minAllowedObjectScale) {
5756
return [...keypoints];
5857
}

pose-detection/src/calculators/keypoints_smoothing.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
import {Keypoint} from '../types';
1919

20+
import {getObjectScale} from './get_object_scale';
2021
import {ImageSize, KeypointsFilter} from './interfaces/common_interfaces';
2122
import {KeypointsSmoothingConfig} from './interfaces/config_interfaces';
23+
import {Rect} from './interfaces/shape_interfaces';
2224
import {KeypointsOneEuroFilter} from './keypoints_one_euro_filter';
2325
import {keypointsToNormalizedKeypoints} from './keypoints_to_normalized_keypoints';
2426
import {KeypointsVelocityFilter} from './keypoints_velocity_filter';
@@ -53,20 +55,25 @@ export class KeypointsSmoothingFilter {
5355
* normalized.
5456
* @param normalized Optional. Whether the keypoints are normalized. Default
5557
* to false.
58+
* @param objectScaleROI Optional. The auxiliary ROI to calculate object
59+
* scale. If not set, objectScale defaults to 1.
5660
*/
5761
apply(
5862
keypoints: Keypoint[], timestamp: number, imageSize?: ImageSize,
59-
normalized = false): Keypoint[] {
63+
normalized = false, objectScaleROI?: Rect): Keypoint[] {
6064
if (keypoints == null) {
6165
this.keypointsFilter.reset();
6266
return null;
6367
}
6468

69+
const objectScale =
70+
objectScaleROI != null ? getObjectScale(objectScaleROI, imageSize) : 1;
71+
6572
const scaledKeypoints = normalized ?
6673
normalizedKeypointsToKeypoints(keypoints, imageSize) :
6774
keypoints;
6875
const scaledKeypointsFiltered =
69-
this.keypointsFilter.apply(scaledKeypoints, timestamp);
76+
this.keypointsFilter.apply(scaledKeypoints, timestamp, objectScale);
7077

7178
return normalized ?
7279
keypointsToNormalizedKeypoints(scaledKeypointsFiltered, imageSize) :

pose-detection/src/calculators/keypoints_velocity_filter.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {Keypoint} from '../types';
1919
import {KeypointsFilter} from './interfaces/common_interfaces';
2020
import {VelocityFilterConfig} from './interfaces/config_interfaces';
2121
import {RelativeVelocityFilter} from './relative_velocity_filter';
22-
import {getObjectScale} from './velocity_filter_utils';
2322

2423
/**
2524
* A stateful filter that smoothes landmark values overtime.
@@ -37,7 +36,8 @@ export class KeypointsVelocityFilter implements KeypointsFilter {
3736

3837
constructor(private readonly config: VelocityFilterConfig) {}
3938

40-
apply(keypoints: Keypoint[], microSeconds: number): Keypoint[] {
39+
apply(keypoints: Keypoint[], microSeconds: number, objectScale: number):
40+
Keypoint[] {
4141
if (keypoints == null) {
4242
this.reset();
4343
return null;
@@ -47,7 +47,6 @@ export class KeypointsVelocityFilter implements KeypointsFilter {
4747
// returned as is.
4848
let valueScale = 1;
4949
if (!this.config.disableValueScaling) {
50-
const objectScale = getObjectScale(keypoints);
5150
if (objectScale < this.config.minAllowedObjectScale) {
5251
return [...keypoints];
5352
}

pose-detection/src/calculators/velocity_filter_utils.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)