Skip to content

Commit 474a42c

Browse files
authored
Upgrade body segmentation model (#1171)
* Upgrade body segmentation model * remove comments * fix lint * Update to 5.0.4 * fix lint * update
1 parent efe3e6d commit 474a42c

File tree

7 files changed

+215
-257
lines changed

7 files changed

+215
-257
lines changed

body-segmentation/demos/live_video/package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
"@mediapipe/selfie_segmentation": "~0.1.0",
1414
"@tensorflow-models/body-segmentation": "file:../../dist",
1515
"@tensorflow-models/pose-detection": "file:../../../pose-detection/dist",
16-
"@tensorflow/tfjs-backend-wasm": "^3.13.0",
17-
"@tensorflow/tfjs-backend-webgl": "^3.13.0",
18-
"@tensorflow/tfjs-converter": "^3.13.0",
19-
"@tensorflow/tfjs-core": "^3.13.0",
16+
"@tensorflow/tfjs-backend-wasm": "^4.9.0",
17+
"@tensorflow/tfjs-backend-webgl": "^4.9.0",
18+
"@tensorflow/tfjs-converter": "^4.9.0",
2019
"scatter-gl": "0.0.8"
2120
},
2221
"scripts": {

body-segmentation/demos/live_video/yarn.lock

Lines changed: 30 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -996,62 +996,43 @@
996996
"@tensorflow-models/pose-detection@file:../../../pose-detection/dist":
997997
version "0.0.0"
998998

999-
"@tensorflow/tfjs-backend-cpu@3.13.0":
1000-
version "3.13.0"
1001-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.13.0.tgz#2a141256fe0a5de0670c31a9ba6990465708dee4"
1002-
integrity sha512-POmzUoAP8HooYYTZ72O1ZYkpVZB0f+8PeAkbTxIG0oahcJccj6a0Vovp1A6xWKfljUoPlJb3jWVC++S603ZL8w==
999+
"@tensorflow/tfjs-backend-cpu@4.9.0":
1000+
version "4.9.0"
1001+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.9.0.tgz#76ce8f4e83814293b662404f16d70f65926195a2"
1002+
integrity sha512-AHIfI3iD1fyQgQKeoQmtkI3exPWRfOo+W0Ws/bxOdapTXcAYWGg0179t52j8XPDwsl8WopfaTINNgYNG6FnP3Q==
10031003
dependencies:
1004-
"@types/seedrandom" "2.4.27"
1005-
seedrandom "2.4.3"
1004+
"@types/seedrandom" "^2.4.28"
1005+
seedrandom "^3.0.5"
10061006

1007-
"@tensorflow/tfjs-backend-wasm@^3.13.0":
1008-
version "3.13.0"
1009-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-wasm/-/tfjs-backend-wasm-3.13.0.tgz#3465c6040542752d2632df7e0c4ac0e5a9ef801a"
1010-
integrity sha512-h5kNS4xvljoySzfcFwqbdFB6QZGR06IA9/Xq/PjBeZt18XEoJGqKHbOCYupmUlr5pxo/gnXzPhAC2h4SfZXPXw==
1007+
"@tensorflow/tfjs-backend-wasm@^4.9.0":
1008+
version "4.9.0"
1009+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-wasm/-/tfjs-backend-wasm-4.9.0.tgz#1e1fec3406b312efc814f8238c5c25052e01650e"
1010+
integrity sha512-HsRr9qyu/1pdpkmSoF+1QMtpuE61QOVpH55j6HGNcN+DGuF8TSh80imzZa9JC+A7DXyQdHBKCbUqytuisBQDaA==
10111011
dependencies:
1012-
"@tensorflow/tfjs-backend-cpu" "3.13.0"
1012+
"@tensorflow/tfjs-backend-cpu" "4.9.0"
10131013
"@types/emscripten" "~0.0.34"
10141014

1015-
"@tensorflow/tfjs-backend-webgl@^3.13.0":
1016-
version "3.13.0"
1017-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.13.0.tgz#f99df51253de21e20dae195991d332195ab30b4b"
1018-
integrity sha512-ZuJS11tCoZx2F1Eq7wqiqu8euJpPW/JV0qOKBehlRpV2qQrR+wHMpBT1hhDl4qU4LdgFTtSggKIRg/L8b0ScUQ==
1015+
"@tensorflow/tfjs-backend-webgl@^4.9.0":
1016+
version "4.9.0"
1017+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.9.0.tgz#272812af5c61d02af3b541ed543c3484f5eb8618"
1018+
integrity sha512-lSEOjR9zi6vb1V9yhrby8jWt6SS+wWBXRa3sDE5GCbpcHMWHv41wZktB2WQyIXDqJQcw1lRZBDoYneibMqr2uQ==
10191019
dependencies:
1020-
"@tensorflow/tfjs-backend-cpu" "3.13.0"
1020+
"@tensorflow/tfjs-backend-cpu" "4.9.0"
10211021
"@types/offscreencanvas" "~2019.3.0"
1022-
"@types/seedrandom" "2.4.27"
1022+
"@types/seedrandom" "^2.4.28"
10231023
"@types/webgl-ext" "0.0.30"
1024-
"@types/webgl2" "0.0.6"
1025-
seedrandom "2.4.3"
1024+
seedrandom "^3.0.5"
10261025

1027-
"@tensorflow/tfjs-converter@^3.13.0":
1028-
version "3.13.0"
1029-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.13.0.tgz#3affc86d94c3948b01673a91309a35feb10e5eac"
1030-
integrity sha512-H2VpDTv9Ve0HBt7ttzz46DmnsPaiT0B+yJjVH3NebGZbgY9C8boBgJIsdyqfiqEWBS3WxF8h4rh58Hv5XXMgaQ==
1031-
1032-
"@tensorflow/tfjs-core@^3.13.0":
1033-
version "3.13.0"
1034-
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.13.0.tgz#0cfd707c668250969564991c5c101fb52e51e1aa"
1035-
integrity sha512-18qBEVIB/4u2OUK9nA5P1XT3e3LyarElD1UKNSNDpnMLxhLTUVZaCR71eHJcpl9wP2Q0cciaTJCTpJdPv1tNDQ==
1036-
dependencies:
1037-
"@types/long" "^4.0.1"
1038-
"@types/offscreencanvas" "~2019.3.0"
1039-
"@types/seedrandom" "2.4.27"
1040-
"@types/webgl-ext" "0.0.30"
1041-
long "4.0.0"
1042-
node-fetch "~2.6.1"
1043-
seedrandom "2.4.3"
1026+
"@tensorflow/tfjs-converter@^4.9.0":
1027+
version "4.9.0"
1028+
resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-4.9.0.tgz#7958f563043b3c54f757f47d2b5b08e963f466ad"
1029+
integrity sha512-mRlzdG3jVsxMkFfHFgDNY10HMoh+vtfPPIghtY+Fc4U/ZnBUFvSfZqwEFyXfOJAewn4fY4BX8+6RE4a0kRXqGA==
10441030

10451031
"@types/emscripten@~0.0.34":
10461032
version "0.0.34"
10471033
resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-0.0.34.tgz#12b4a344274fb102ff2f6c877b37587bc3e46008"
10481034
integrity sha512-QSb9ojDincskc+uKMI0KXp8e1NALFINCrMlp8VGKGcTSxeEyRTTKyjWw75NYrCZHUsVEEEpr1tYHpbtaC++/sQ==
10491035

1050-
"@types/long@^4.0.1":
1051-
version "4.0.1"
1052-
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
1053-
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
1054-
10551036
"@types/offscreencanvas@~2019.3.0":
10561037
version "2019.3.0"
10571038
resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553"
@@ -1062,21 +1043,16 @@
10621043
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
10631044
integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==
10641045

1065-
"@types/[email protected].27":
1066-
version "2.4.27"
1067-
resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41"
1068-
integrity sha1-nbVjk33YaRX2kJK8QyWdL0hXjkE=
1046+
"@types/seedrandom@^2.4.28":
1047+
version "2.4.30"
1048+
resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.30.tgz#d2efe425869b84163c2d56e779dddadb9372cbfa"
1049+
integrity sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==
10691050

10701051
10711052
version "0.0.30"
10721053
resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d"
10731054
integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==
10741055

1075-
1076-
version "0.0.6"
1077-
resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.6.tgz#1ea2db791362bd8521548d664dbd3c5311cdf4b6"
1078-
integrity sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ==
1079-
10801056
abab@^2.0.0:
10811057
version "2.0.5"
10821058
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
@@ -4250,11 +4226,6 @@ log-symbols@^2.2.0:
42504226
dependencies:
42514227
chalk "^2.0.1"
42524228

4253-
4254-
version "4.0.0"
4255-
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
4256-
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
4257-
42584229
loose-envify@^1.0.0:
42594230
version "1.4.0"
42604231
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -4468,13 +4439,6 @@ node-addon-api@^1.7.1:
44684439
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d"
44694440
integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
44704441

4471-
node-fetch@~2.6.1:
4472-
version "2.6.6"
4473-
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89"
4474-
integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==
4475-
dependencies:
4476-
whatwg-url "^5.0.0"
4477-
44784442
node-forge@^0.10.0:
44794443
version "0.10.0"
44804444
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
@@ -5736,10 +5700,10 @@ [email protected]:
57365700
dependencies:
57375701
three "^0.113"
57385702

5739-
seedrandom@2.4.3:
5740-
version "2.4.3"
5741-
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc"
5742-
integrity sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=
5703+
seedrandom@^3.0.5:
5704+
version "3.0.5"
5705+
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
5706+
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
57435707

57445708
57455709
version "7.0.0"
@@ -6314,11 +6278,6 @@ tr46@^1.0.1:
63146278
dependencies:
63156279
punycode "^2.1.0"
63166280

6317-
tr46@~0.0.3:
6318-
version "0.0.3"
6319-
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
6320-
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
6321-
63226281
63236282
version "0.0.0"
63246283
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
@@ -6565,11 +6524,6 @@ wcwidth@^1.0.1:
65656524
dependencies:
65666525
defaults "^1.0.3"
65676526

6568-
webidl-conversions@^3.0.0:
6569-
version "3.0.1"
6570-
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
6571-
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
6572-
65736527
webidl-conversions@^4.0.2:
65746528
version "4.0.2"
65756529
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@@ -6587,14 +6541,6 @@ whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0:
65876541
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
65886542
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
65896543

6590-
whatwg-url@^5.0.0:
6591-
version "5.0.0"
6592-
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
6593-
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
6594-
dependencies:
6595-
tr46 "~0.0.3"
6596-
webidl-conversions "^3.0.0"
6597-
65986544
whatwg-url@^7.0.0:
65996545
version "7.1.0"
66006546
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"

body-segmentation/package.json

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,21 @@
1414
},
1515
"peerDependencies": {
1616
"@mediapipe/selfie_segmentation": "~0.1.0",
17-
"@tensorflow/tfjs-backend-webgl": "^3.13.0",
18-
"@tensorflow/tfjs-converter": "^3.13.0",
19-
"@tensorflow/tfjs-core": "^3.13.0"
17+
"@tensorflow/tfjs-backend-webgl": "^4.9.0",
18+
"@tensorflow/tfjs-converter": "^4.9.0",
19+
"@tensorflow/tfjs-core": "^4.9.0"
2020
},
2121
"devDependencies": {
2222
"@babel/polyfill": "^7.10.4",
2323
"@mediapipe/selfie_segmentation": "^0.1.0",
2424
"@rollup/plugin-commonjs": "^11.0.2",
2525
"@rollup/plugin-node-resolve": "^7.1.1",
2626
"@rollup/plugin-typescript": "^3.0.0",
27-
"@tensorflow/tfjs-backend-cpu": "^3.13.0",
28-
"@tensorflow/tfjs-backend-webgl": "^3.13.0",
29-
"@tensorflow/tfjs-converter": "^3.13.0",
30-
"@tensorflow/tfjs-core": "^3.13.0",
27+
"@tensorflow/tfjs-backend-cpu": "^4.9.0",
28+
"@tensorflow/tfjs-backend-webgl": "^4.9.0",
29+
"@tensorflow/tfjs-converter": "^4.9.0",
30+
"@tensorflow/tfjs-backend-webgpu": "4.9.0",
31+
"@tensorflow/tfjs-core": "^4.9.0",
3132
"@types/jasmine": "~3.4.0",
3233
"babel-core": "~6.26.0",
3334
"babel-plugin-transform-runtime": "~6.23.0",
@@ -46,7 +47,7 @@
4647
"ts-node": "~8.8.2",
4748
"tslint": "~6.1.3",
4849
"tslint-no-circular-imports": "~0.7.0",
49-
"typescript": "~3.9.9",
50+
"typescript": "~4.4.0",
5051
"yalc": "~1.0.0-pre.21"
5152
},
5253
"scripts": {

body-segmentation/src/body_pix/body_pix_test.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@
1616
*/
1717

1818
// tslint:disable-next-line: no-imports-from-dist
19-
import {BROWSER_ENVS, describeWithFlags} from '@tensorflow/tfjs-core/dist/jasmine_util';
19+
import { BROWSER_ENVS, describeWithFlags } from '@tensorflow/tfjs-core/dist/jasmine_util';
2020

2121
import * as bodySegmentation from '../index';
22-
import {Mask} from '../shared/calculators/interfaces/common_interfaces';
23-
import {toImageDataLossy, toTensorLossy} from '../shared/calculators/mask_util';
22+
import { Mask } from '../shared/calculators/interfaces/common_interfaces';
23+
import { toImageDataLossy, toTensorLossy } from '../shared/calculators/mask_util';
2424
import * as renderUtil from '../shared/calculators/render_util';
25-
import {loadImage} from '../shared/test_util';
26-
import {BodyPixSegmentationConfig} from './types';
25+
import { loadImage } from '../shared/test_util';
26+
import { BodyPixSegmentationConfig } from './types';
2727

2828
// Measured in channels.
29-
const DIFF_IMAGE = 30;
29+
const DIFF_IMAGE_RATIO = 0.001;
3030

3131
class CanvasImageSourceMask implements Mask {
32-
constructor(private mask: CanvasImageSource) {}
32+
constructor(private mask: CanvasImageSource) { }
3333

3434
async toCanvasImageSource() {
3535
return this.mask;
@@ -44,28 +44,28 @@ class CanvasImageSourceMask implements Mask {
4444
}
4545

4646
getUnderlyingType() {
47-
return 'canvasimagesource' as const ;
47+
return 'canvasimagesource' as const;
4848
}
4949
}
5050

5151
async function getSegmentation(
52-
image: HTMLImageElement, config: BodyPixSegmentationConfig) {
52+
image: HTMLImageElement, config: BodyPixSegmentationConfig) {
5353
const segmenter = await bodySegmentation.createSegmenter(
54-
bodySegmentation.SupportedModels.BodyPix);
54+
bodySegmentation.SupportedModels.BodyPix);
5555

5656
const segmentations = await segmenter.segmentPeople(image, config);
5757
return Promise.all(segmentations.map(async segmentation => {
5858
return {
5959
maskValueToLabel: segmentation.maskValueToLabel,
6060
// Convert to canvas image source to apply alpha-premultiplication.
6161
mask: new CanvasImageSourceMask(
62-
await segmentation.mask.toCanvasImageSource())
62+
await segmentation.mask.toCanvasImageSource())
6363
};
6464
}));
6565
}
6666

6767
async function getBinaryMask(
68-
image: HTMLImageElement, expectedNumSegmentations?: number) {
68+
image: HTMLImageElement, expectedNumSegmentations?: number) {
6969
const segmentation = await getSegmentation(image, {
7070
multiSegmentation: expectedNumSegmentations != null,
7171
segmentBodyParts: false
@@ -76,13 +76,13 @@ async function getBinaryMask(
7676
}
7777

7878
const binaryMask = await renderUtil.toBinaryMask(
79-
segmentation, {r: 255, g: 255, b: 255, a: 255},
80-
{r: 0, g: 0, b: 0, a: 255});
79+
segmentation, { r: 255, g: 255, b: 255, a: 255 },
80+
{ r: 0, g: 0, b: 0, a: 255 });
8181
return binaryMask;
8282
}
8383

8484
async function getColoredMask(
85-
image: HTMLImageElement, expectedNumSegmentations?: number) {
85+
image: HTMLImageElement, expectedNumSegmentations?: number) {
8686
const segmentation = await getSegmentation(image, {
8787
multiSegmentation: expectedNumSegmentations != null,
8888
segmentBodyParts: true
@@ -93,8 +93,8 @@ async function getColoredMask(
9393
}
9494

9595
const coloredMask = await renderUtil.toColoredMask(
96-
segmentation, bodySegmentation.bodyPixMaskValueToRainbowColor,
97-
{r: 255, g: 255, b: 255, a: 255});
96+
segmentation, bodySegmentation.bodyPixMaskValueToRainbowColor,
97+
{ r: 255, g: 255, b: 255, a: 255 });
9898

9999
return coloredMask;
100100
}
@@ -104,12 +104,13 @@ const HEIGHT = 861;
104104

105105
async function expectImage(actual: ImageData, imageName: string) {
106106
const expectedImage = await loadImage(imageName, WIDTH, HEIGHT)
107-
.then(async image => toImageDataLossy(image));
107+
.then(async image => toImageDataLossy(image));
108108
const mismatchedChannels = actual.data.reduce(
109-
(mismatched, channel, i) =>
110-
mismatched + +(channel !== expectedImage.data[i]),
111-
0);
112-
expect(mismatchedChannels).toBeLessThanOrEqual(DIFF_IMAGE);
109+
(mismatched, channel, i) =>
110+
mismatched + +(channel !== expectedImage.data[i]),
111+
0);
112+
expect(mismatchedChannels)
113+
.toBeLessThanOrEqual(expectedImage.data.length * DIFF_IMAGE_RATIO);
113114
}
114115

115116
describeWithFlags('renderUtil', BROWSER_ENVS, () => {

0 commit comments

Comments
 (0)