Invoke the FaceStylizer callback even if no faces are detected
PiperOrigin-RevId: 527008261
This commit is contained in:
parent
3bc8276678
commit
9e30b00685
10
mediapipe/tasks/web/vision/core/types.d.ts
vendored
10
mediapipe/tasks/web/vision/core/types.d.ts
vendored
|
@ -25,16 +25,6 @@ import {NormalizedKeypoint} from '../../../../tasks/web/components/containers/ke
|
||||||
*/
|
*/
|
||||||
export type SegmentationMask = Uint8ClampedArray|Float32Array|WebGLTexture;
|
export type SegmentationMask = Uint8ClampedArray|Float32Array|WebGLTexture;
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback that receives an `ImageData` object from a Vision task. The
|
|
||||||
* lifetime of the underlying data is limited to the duration of the callback.
|
|
||||||
* If asynchronous processing is needed, all data needs to be copied before the
|
|
||||||
* callback returns.
|
|
||||||
*
|
|
||||||
* The `WebGLTexture` output type is reserved for future usage.
|
|
||||||
*/
|
|
||||||
export type ImageCallback =
|
|
||||||
(image: ImageData|WebGLTexture, width: number, height: number) => void;
|
|
||||||
|
|
||||||
/** A Region-Of-Interest (ROI) to represent a region within an image. */
|
/** A Region-Of-Interest (ROI) to represent a region within an image. */
|
||||||
export declare interface RegionOfInterest {
|
export declare interface RegionOfInterest {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import {BaseOptions as BaseOptionsProto} from '../../../../tasks/cc/core/proto/b
|
||||||
import {FaceStylizerGraphOptions as FaceStylizerGraphOptionsProto} from '../../../../tasks/cc/vision/face_stylizer/proto/face_stylizer_graph_options_pb';
|
import {FaceStylizerGraphOptions as FaceStylizerGraphOptionsProto} from '../../../../tasks/cc/vision/face_stylizer/proto/face_stylizer_graph_options_pb';
|
||||||
import {WasmFileset} from '../../../../tasks/web/core/wasm_fileset';
|
import {WasmFileset} from '../../../../tasks/web/core/wasm_fileset';
|
||||||
import {ImageProcessingOptions} from '../../../../tasks/web/vision/core/image_processing_options';
|
import {ImageProcessingOptions} from '../../../../tasks/web/vision/core/image_processing_options';
|
||||||
import {ImageCallback} from '../../../../tasks/web/vision/core/types';
|
|
||||||
import {VisionGraphRunner, VisionTaskRunner} from '../../../../tasks/web/vision/core/vision_task_runner';
|
import {VisionGraphRunner, VisionTaskRunner} from '../../../../tasks/web/vision/core/vision_task_runner';
|
||||||
import {ImageSource, WasmModule} from '../../../../web/graph_runner/graph_runner';
|
import {ImageSource, WasmModule} from '../../../../web/graph_runner/graph_runner';
|
||||||
// Placeholder for internal dependency on trusted resource url
|
// Placeholder for internal dependency on trusted resource url
|
||||||
|
@ -39,11 +38,20 @@ const FACE_STYLIZER_GRAPH =
|
||||||
// The OSS JS API does not support the builder pattern.
|
// The OSS JS API does not support the builder pattern.
|
||||||
// tslint:disable:jspb-use-builder-pattern
|
// tslint:disable:jspb-use-builder-pattern
|
||||||
|
|
||||||
export {ImageCallback};
|
/**
|
||||||
|
* A callback that receives an image from the face stylizer, or `null` if no
|
||||||
|
* face was detected. The lifetime of the underlying data is limited to the
|
||||||
|
* duration of the callback. If asynchronous processing is needed, all data
|
||||||
|
* needs to be copied before the callback returns.
|
||||||
|
*
|
||||||
|
* The `WebGLTexture` output type is reserved for future usage.
|
||||||
|
*/
|
||||||
|
export type FaceStylizerCallback =
|
||||||
|
(image: ImageData|WebGLTexture|null, width: number, height: number) => void;
|
||||||
|
|
||||||
/** Performs face stylization on images. */
|
/** Performs face stylization on images. */
|
||||||
export class FaceStylizer extends VisionTaskRunner {
|
export class FaceStylizer extends VisionTaskRunner {
|
||||||
private userCallback: ImageCallback = () => {};
|
private userCallback: FaceStylizerCallback = () => {};
|
||||||
private readonly options: FaceStylizerGraphOptionsProto;
|
private readonly options: FaceStylizerGraphOptionsProto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,7 +142,7 @@ export class FaceStylizer extends VisionTaskRunner {
|
||||||
* lifetime of the returned data is only guaranteed for the duration of the
|
* lifetime of the returned data is only guaranteed for the duration of the
|
||||||
* callback.
|
* callback.
|
||||||
*/
|
*/
|
||||||
stylize(image: ImageSource, callback: ImageCallback): void;
|
stylize(image: ImageSource, callback: FaceStylizerCallback): void;
|
||||||
/**
|
/**
|
||||||
* Performs face stylization on the provided single image. The method returns
|
* Performs face stylization on the provided single image. The method returns
|
||||||
* synchronously once the callback returns. Only use this method when the
|
* synchronously once the callback returns. Only use this method when the
|
||||||
|
@ -158,11 +166,12 @@ export class FaceStylizer extends VisionTaskRunner {
|
||||||
*/
|
*/
|
||||||
stylize(
|
stylize(
|
||||||
image: ImageSource, imageProcessingOptions: ImageProcessingOptions,
|
image: ImageSource, imageProcessingOptions: ImageProcessingOptions,
|
||||||
callback: ImageCallback): void;
|
callback: FaceStylizerCallback): void;
|
||||||
stylize(
|
stylize(
|
||||||
image: ImageSource,
|
image: ImageSource,
|
||||||
imageProcessingOptionsOrCallback: ImageProcessingOptions|ImageCallback,
|
imageProcessingOptionsOrCallback: ImageProcessingOptions|
|
||||||
callback?: ImageCallback): void {
|
FaceStylizerCallback,
|
||||||
|
callback?: FaceStylizerCallback): void {
|
||||||
const imageProcessingOptions =
|
const imageProcessingOptions =
|
||||||
typeof imageProcessingOptionsOrCallback !== 'function' ?
|
typeof imageProcessingOptionsOrCallback !== 'function' ?
|
||||||
imageProcessingOptionsOrCallback :
|
imageProcessingOptionsOrCallback :
|
||||||
|
@ -191,7 +200,7 @@ export class FaceStylizer extends VisionTaskRunner {
|
||||||
*/
|
*/
|
||||||
stylizeForVideo(
|
stylizeForVideo(
|
||||||
videoFrame: ImageSource, timestamp: number,
|
videoFrame: ImageSource, timestamp: number,
|
||||||
callback: ImageCallback): void;
|
callback: FaceStylizerCallback): void;
|
||||||
/**
|
/**
|
||||||
* Performs face stylization on the provided video frame. Only use this
|
* Performs face stylization on the provided video frame. Only use this
|
||||||
* method when the FaceStylizer is created with the video running mode.
|
* method when the FaceStylizer is created with the video running mode.
|
||||||
|
@ -219,12 +228,12 @@ export class FaceStylizer extends VisionTaskRunner {
|
||||||
*/
|
*/
|
||||||
stylizeForVideo(
|
stylizeForVideo(
|
||||||
videoFrame: ImageSource, imageProcessingOptions: ImageProcessingOptions,
|
videoFrame: ImageSource, imageProcessingOptions: ImageProcessingOptions,
|
||||||
timestamp: number, callback: ImageCallback): void;
|
timestamp: number, callback: FaceStylizerCallback): void;
|
||||||
stylizeForVideo(
|
stylizeForVideo(
|
||||||
videoFrame: ImageSource,
|
videoFrame: ImageSource,
|
||||||
timestampOrImageProcessingOptions: number|ImageProcessingOptions,
|
timestampOrImageProcessingOptions: number|ImageProcessingOptions,
|
||||||
timestampOrCallback: number|ImageCallback,
|
timestampOrCallback: number|FaceStylizerCallback,
|
||||||
callback?: ImageCallback): void {
|
callback?: FaceStylizerCallback): void {
|
||||||
const imageProcessingOptions =
|
const imageProcessingOptions =
|
||||||
typeof timestampOrImageProcessingOptions !== 'number' ?
|
typeof timestampOrImageProcessingOptions !== 'number' ?
|
||||||
timestampOrImageProcessingOptions :
|
timestampOrImageProcessingOptions :
|
||||||
|
@ -272,6 +281,7 @@ export class FaceStylizer extends VisionTaskRunner {
|
||||||
});
|
});
|
||||||
this.graphRunner.attachEmptyPacketListener(
|
this.graphRunner.attachEmptyPacketListener(
|
||||||
STYLIZED_IMAGE_STREAM, timestamp => {
|
STYLIZED_IMAGE_STREAM, timestamp => {
|
||||||
|
this.userCallback(null, /* width= */ 0, /* height= */ 0);
|
||||||
this.setLatestOutputTimestamp(timestamp);
|
this.setLatestOutputTimestamp(timestamp);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ class FaceStylizerFake extends FaceStylizer implements MediapipeTasksFake {
|
||||||
|
|
||||||
fakeWasmModule: SpyWasmModule;
|
fakeWasmModule: SpyWasmModule;
|
||||||
imageListener: ((images: WasmImage, timestamp: number) => void)|undefined;
|
imageListener: ((images: WasmImage, timestamp: number) => void)|undefined;
|
||||||
|
emptyPacketListener: ((timestamp: number) => void)|undefined;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(createSpyWasmModule(), /* glCanvas= */ null);
|
super(createSpyWasmModule(), /* glCanvas= */ null);
|
||||||
|
@ -42,6 +43,12 @@ class FaceStylizerFake extends FaceStylizer implements MediapipeTasksFake {
|
||||||
expect(stream).toEqual('stylized_image');
|
expect(stream).toEqual('stylized_image');
|
||||||
this.imageListener = listener;
|
this.imageListener = listener;
|
||||||
});
|
});
|
||||||
|
this.attachListenerSpies[1] =
|
||||||
|
spyOn(this.graphRunner, 'attachEmptyPacketListener')
|
||||||
|
.and.callFake((stream, listener) => {
|
||||||
|
expect(stream).toEqual('stylized_image');
|
||||||
|
this.emptyPacketListener = listener;
|
||||||
|
});
|
||||||
spyOn(this.graphRunner, 'setGraph').and.callFake(binaryGraph => {
|
spyOn(this.graphRunner, 'setGraph').and.callFake(binaryGraph => {
|
||||||
this.graph = CalculatorGraphConfig.deserializeBinary(binaryGraph);
|
this.graph = CalculatorGraphConfig.deserializeBinary(binaryGraph);
|
||||||
});
|
});
|
||||||
|
@ -111,4 +118,21 @@ describe('FaceStylizer', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('invokes callback even when no faes are detected', (done) => {
|
||||||
|
// Pass the test data to our listener
|
||||||
|
faceStylizer.fakeWasmModule._waitUntilIdle.and.callFake(() => {
|
||||||
|
verifyListenersRegistered(faceStylizer);
|
||||||
|
faceStylizer.emptyPacketListener!(/* timestamp= */ 1337);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Invoke the face stylizeer
|
||||||
|
faceStylizer.stylize({} as HTMLImageElement, (image, width, height) => {
|
||||||
|
expect(faceStylizer.fakeWasmModule._waitUntilIdle).toHaveBeenCalled();
|
||||||
|
expect(image).toBeNull();
|
||||||
|
expect(width).toEqual(0);
|
||||||
|
expect(height).toEqual(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user