1
- import { WorkerResponse , WorkerCommand , BodypixFunctionType , BodyPixConfig , ModelConfigMobileNetV1_05 , BodyPixOperatipnParams } from "./const" ;
1
+ import { BodyPixConfig , BodyPixOperatipnParams , BodypixFunctionTypes , ModelConfigs } from "./const" ;
2
2
import * as bodyPix from "@tensorflow-models/body-pix" ;
3
- import { BrowserType , getBrowserType } from "./BrowserUtil" ;
4
3
import { SemanticPersonSegmentation } from "@tensorflow-models/body-pix" ;
4
+ import { WorkerManagerBase , LocalWorker , getBrowserType } from "worker-base" ;
5
5
6
- export { ModelConfigResNet , ModelConfigMobileNetV1 , ModelConfigMobileNetV1_05 , BodypixFunctionType , BodyPixConfig , BodyPixOperatipnParams } from "./const" ;
7
- export { BrowserType , getBrowserType } from "./BrowserUtil" ;
6
+ export { BodypixFunctionTypes , BodyPixConfig , BodyPixOperatipnParams } from "./const" ;
8
7
export { SemanticPersonSegmentation , SemanticPartSegmentation , PersonSegmentation , PartSegmentation } from "@tensorflow-models/body-pix" ;
9
- export { BodyPixInternalResolution } from "@tensorflow-models/body-pix/dist/types" ;
8
+ export { BodyPixInternalResolution , BodyPixArchitecture , BodyPixMultiplier , BodyPixOutputStride , BodyPixQuantBytes } from "@tensorflow-models/body-pix/dist/types" ;
10
9
11
10
import * as tf from "@tensorflow/tfjs" ;
12
11
@@ -28,7 +27,7 @@ const load_module = async (config: BodyPixConfig) => {
28
27
export const generateBodyPixDefaultConfig = ( ) : BodyPixConfig => {
29
28
const defaultConf : BodyPixConfig = {
30
29
browserType : getBrowserType ( ) ,
31
- model : ModelConfigMobileNetV1_05 ,
30
+ model : ModelConfigs . ModelConfigMobileNetV1_05 ,
32
31
processOnLocal : false ,
33
32
useTFWasmBackend : false ,
34
33
} ;
@@ -37,7 +36,7 @@ export const generateBodyPixDefaultConfig = (): BodyPixConfig => {
37
36
38
37
export const generateDefaultBodyPixParams = ( ) => {
39
38
const defaultParams : BodyPixOperatipnParams = {
40
- type : BodypixFunctionType . SegmentPerson ,
39
+ type : BodypixFunctionTypes . SegmentPerson ,
41
40
segmentPersonParams : {
42
41
flipHorizontal : false ,
43
42
internalResolution : "medium" ,
@@ -80,7 +79,7 @@ export const generateDefaultBodyPixParams = () => {
80
79
return defaultParams ;
81
80
} ;
82
81
83
- class LocalBP {
82
+ class LocalBP extends LocalWorker {
84
83
model : bodyPix . BodyPix | null = null ;
85
84
canvas : HTMLCanvasElement = ( ( ) => {
86
85
const newCanvas = document . createElement ( "canvas" ) ;
@@ -93,36 +92,29 @@ class LocalBP {
93
92
this . model = await bodyPix . load ( config . model ) ;
94
93
} ;
95
94
96
- perf = Array . from ( new Array ( 50 ) , ( ) => 0 ) ;
97
- predict = async ( targetCanvas : HTMLCanvasElement , config : BodyPixConfig , params : BodyPixOperatipnParams ) => {
98
- // ImageData作成
99
- const processWidth = params . processWidth <= 0 || params . processHeight <= 0 ? targetCanvas . width : params . processWidth ;
100
- const processHeight = params . processWidth <= 0 || params . processHeight <= 0 ? targetCanvas . height : params . processHeight ;
95
+ predict = async ( config : BodyPixConfig , params : BodyPixOperatipnParams , targetCanvas : HTMLCanvasElement ) => {
96
+ // // ImageData作成
97
+ // const processWidth = params.processWidth <= 0 || params.processHeight <= 0 ? targetCanvas.width : params.processWidth;
98
+ // const processHeight = params.processWidth <= 0 || params.processHeight <= 0 ? targetCanvas.height : params.processHeight;
101
99
102
- //console.log("process image size:", processWidth, processHeight)
103
- this . canvas . width = processWidth ;
104
- this . canvas . height = processHeight ;
105
- const ctx = this . canvas . getContext ( "2d" ) ! ;
106
- ctx . drawImage ( targetCanvas , 0 , 0 , processWidth , processHeight ) ;
107
- const newImg = ctx . getImageData ( 0 , 0 , processWidth , processHeight ) ;
100
+ // //console.log("process image size:", processWidth, processHeight)
101
+ // this.canvas.width = processWidth;
102
+ // this.canvas.height = processHeight;
103
+ // const ctx = this.canvas.getContext("2d")!;
104
+ // ctx.drawImage(targetCanvas, 0, 0, processWidth, processHeight);
105
+ // const newImg = ctx.getImageData(0, 0, processWidth, processHeight);
106
+
107
+ const ctx = targetCanvas . getContext ( "2d" ) ! ;
108
+ const newImg = ctx . getImageData ( 0 , 0 , targetCanvas . width , targetCanvas . height ) ;
108
109
109
110
let prediction ;
110
- if ( params . type === BodypixFunctionType . SegmentPerson ) {
111
- const start = performance . now ( ) ;
111
+ if ( params . type === BodypixFunctionTypes . SegmentPerson ) {
112
112
prediction = await this . model ! . segmentPerson ( newImg , params . segmentPersonParams ) ;
113
- const end = performance . now ( ) ;
114
- this . perf . shift ( ) ;
115
- this . perf . push ( end - start ) ;
116
- const average =
117
- this . perf . reduce ( ( p , c ) => {
118
- return p + c ;
119
- } ) / this . perf . length ;
120
- // console.log("inference average:", average, this.perf.length)
121
- } else if ( params . type === BodypixFunctionType . SegmentPersonParts ) {
113
+ } else if ( params . type === BodypixFunctionTypes . SegmentPersonParts ) {
122
114
prediction = await this . model ! . segmentPersonParts ( newImg , params . segmentPersonPartsParams ) ;
123
- } else if ( params . type === BodypixFunctionType . SegmentMultiPerson ) {
115
+ } else if ( params . type === BodypixFunctionTypes . SegmentMultiPerson ) {
124
116
prediction = await this . model ! . segmentMultiPerson ( newImg , params . segmentMultiPersonParams ) ;
125
- } else if ( params . type === BodypixFunctionType . SegmentMultiPersonParts ) {
117
+ } else if ( params . type === BodypixFunctionTypes . SegmentMultiPersonParts ) {
126
118
prediction = await this . model ! . segmentMultiPersonParts ( newImg , params . segmentMultiPersonPartsParams ) ;
127
119
} else {
128
120
// segmentPersonに倒す
@@ -132,92 +124,42 @@ class LocalBP {
132
124
} ;
133
125
}
134
126
135
- export class BodypixWorkerManager {
136
- private workerBP : Worker | null = null ;
137
-
127
+ export class BodypixWorkerManager extends WorkerManagerBase {
138
128
config : BodyPixConfig = generateBodyPixDefaultConfig ( ) ;
139
- private localBP = new LocalBP ( ) ;
140
-
129
+ localWorker = new LocalBP ( ) ;
141
130
init = async ( config : BodyPixConfig | null = null ) => {
142
- if ( config != null ) {
143
- this . config = config ;
144
- }
145
- if ( this . workerBP ) {
146
- this . workerBP . terminate ( ) ;
147
- }
148
- this . workerBP = null ;
149
-
150
- if ( this . config . browserType === BrowserType . SAFARI || this . config . processOnLocal == true ) {
151
- // safariはwebworkerでWebGLが使えないのでworkerは使わない。
152
- return new Promise < void > ( ( onResolve , onFail ) => {
153
- this . localBP . init ( this . config ! ) . then ( ( ) => {
154
- onResolve ( ) ;
155
- } ) ;
156
- } ) ;
157
- }
158
-
159
- const workerBP : Worker = new workerJs ( ) ;
160
-
161
- workerBP ! . postMessage ( {
162
- message : WorkerCommand . INITIALIZE ,
163
- config : this . config ,
164
- } ) ;
165
- const p = new Promise < void > ( ( onResolve , onFail ) => {
166
- workerBP ! . onmessage = ( event ) => {
167
- if ( event . data . message === WorkerResponse . INITIALIZED ) {
168
- console . log ( "WORKERSS INITIALIZED" ) ;
169
- this . workerBP = workerBP ;
170
- onResolve ( ) ;
171
- } else {
172
- console . log ( "Bodypix Initialization something wrong.." ) ;
173
- onFail ( event ) ;
174
- }
175
- } ;
176
- } ) ;
177
- await p ;
131
+ this . config = config || generateBodyPixDefaultConfig ( ) ;
132
+ await this . initCommon (
133
+ {
134
+ useWorkerForSafari : false ,
135
+ processOnLocal : this . config . processOnLocal ,
136
+ localWorker : ( ) => {
137
+ return new workerJs ! ( ) ;
138
+ } ,
139
+ workerJs : ( ) => {
140
+ return new workerJs ( ) ;
141
+ } ,
142
+ } ,
143
+ config
144
+ ) ;
178
145
return ;
179
146
} ;
180
147
181
- predict = async ( targetCanvas : HTMLCanvasElement , params : BodyPixOperatipnParams ) => {
182
- if ( this . config . browserType === BrowserType . SAFARI || this . config . processOnLocal == true ) {
183
- const prediction = await this . localBP . predict ( targetCanvas , this . config , params ) ;
148
+ predict = async ( params : BodyPixOperatipnParams , targetCanvas : HTMLCanvasElement ) => {
149
+ if ( ! this . worker ) {
150
+ const resizedCanvas = this . generateTargetCanvas ( targetCanvas , params . processWidth , params . processHeight ) ;
151
+ const prediction = await this . localWorker . predict ( this . config , params , resizedCanvas ) ;
184
152
return prediction ;
185
- } else {
186
- if ( ! this . workerBP ) {
187
- return Array . from ( new Array ( params . processWidth ) , ( ) => new Array ( params . processHeight ) . fill ( 1 ) ) ;
188
- }
189
- const offscreen = new OffscreenCanvas ( targetCanvas . width , targetCanvas . height ) ;
190
- const offctx = offscreen . getContext ( "2d" ) ! ;
191
- offctx . drawImage ( targetCanvas , 0 , 0 , targetCanvas . width , targetCanvas . height ) ;
192
- const imageBitmap = offscreen . transferToImageBitmap ( ) ;
193
- const uid = performance . now ( ) ;
194
- const p = new Promise ( ( onResolve , onFail ) => {
195
- this . workerBP ! . postMessage (
196
- {
197
- message : WorkerCommand . PREDICT ,
198
- uid : uid ,
199
- params : params ,
200
- image : imageBitmap ,
201
- config : this . config ,
202
- } ,
203
- [ imageBitmap ]
204
- ) ;
205
-
206
- this . workerBP ! . onmessage = ( event ) => {
207
- if ( event . data . message === WorkerResponse . PREDICTED && event . data . uid === uid ) {
208
- onResolve ( event . data . prediction ) ;
209
- } else {
210
- console . log ( "Bodypix Prediction something wrong.." , event . data . message , WorkerResponse . PREDICTED , event . data . uid , uid ) ;
211
- // onFail(event)
212
- }
213
- } ;
214
- } ) ;
215
- return p ;
216
153
}
154
+ const imageBitmap = this . generateImageBitmap ( targetCanvas , params . processWidth , params . processHeight ) ;
155
+ const prediction = ( await this . sendToWorker ( this . config , params , imageBitmap ) ) as bodyPix . SemanticPersonSegmentation | bodyPix . SemanticPartSegmentation | bodyPix . PersonSegmentation [ ] | bodyPix . PartSegmentation [ ] ;
156
+ return prediction ;
217
157
} ;
218
158
}
219
159
220
- //// Utility for Demo
160
+ /////////////////////////
161
+ //// Utility for Demo ///
162
+ /////////////////////////
221
163
export const createForegroundImage = ( srcCanvas : HTMLCanvasElement , prediction : SemanticPersonSegmentation ) => {
222
164
const tmpCanvas = document . createElement ( "canvas" ) ;
223
165
tmpCanvas . width = prediction . width ;
0 commit comments