radames commited on
Commit
a74fca5
1 Parent(s): 174a3d9

Upload 6 files

Browse files
Files changed (6) hide show
  1. build/m.d.ts +5 -5
  2. build/m.js +227 -11
  3. build/m_bg.wasm +2 -2
  4. build/m_bg.wasm.d.ts +3 -2
  5. lib-example.html +473 -0
  6. samWorker.js +1 -1
build/m.d.ts CHANGED
@@ -14,11 +14,10 @@ export class Model {
14
  */
15
  set_image_embeddings(image_data: Uint8Array): void;
16
  /**
17
- * @param {number} x
18
- * @param {number} y
19
  * @returns {any}
20
  */
21
- mask_for_point(x: number, y: number): any;
22
  }
23
 
24
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
@@ -28,12 +27,13 @@ export interface InitOutput {
28
  readonly __wbg_model_free: (a: number) => void;
29
  readonly model_new: (a: number, b: number, c: number, d: number) => void;
30
  readonly model_set_image_embeddings: (a: number, b: number, c: number, d: number) => void;
31
- readonly model_mask_for_point: (a: number, b: number, c: number, d: number) => void;
32
  readonly main: (a: number, b: number) => number;
33
- readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
34
  readonly __wbindgen_malloc: (a: number, b: number) => number;
35
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
 
36
  readonly __wbindgen_free: (a: number, b: number, c: number) => void;
 
37
  readonly __wbindgen_start: () => void;
38
  }
39
 
 
14
  */
15
  set_image_embeddings(image_data: Uint8Array): void;
16
  /**
17
+ * @param {any} input
 
18
  * @returns {any}
19
  */
20
+ mask_for_point(input: any): any;
21
  }
22
 
23
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
 
27
  readonly __wbg_model_free: (a: number) => void;
28
  readonly model_new: (a: number, b: number, c: number, d: number) => void;
29
  readonly model_set_image_embeddings: (a: number, b: number, c: number, d: number) => void;
30
+ readonly model_mask_for_point: (a: number, b: number, c: number) => void;
31
  readonly main: (a: number, b: number) => number;
 
32
  readonly __wbindgen_malloc: (a: number, b: number) => number;
33
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
34
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
35
  readonly __wbindgen_free: (a: number, b: number, c: number) => void;
36
+ readonly __wbindgen_exn_store: (a: number) => void;
37
  readonly __wbindgen_start: () => void;
38
  }
39
 
build/m.js CHANGED
@@ -47,13 +47,17 @@ function takeObject(idx) {
47
  return ret;
48
  }
49
 
50
- let WASM_VECTOR_LEN = 0;
 
 
51
 
52
- function passArray8ToWasm0(arg, malloc) {
53
- const ptr = malloc(arg.length * 1, 1) >>> 0;
54
- getUint8Memory0().set(arg, ptr / 1);
55
- WASM_VECTOR_LEN = arg.length;
56
- return ptr;
 
 
57
  }
58
 
59
  let cachedInt32Memory0 = null;
@@ -65,6 +69,8 @@ function getInt32Memory0() {
65
  return cachedInt32Memory0;
66
  }
67
 
 
 
68
  const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
69
 
70
  const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
@@ -117,6 +123,86 @@ function passStringToWasm0(arg, malloc, realloc) {
117
  WASM_VECTOR_LEN = offset;
118
  return ptr;
119
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  /**
121
  */
122
  export class Model {
@@ -180,14 +266,13 @@ export class Model {
180
  }
181
  }
182
  /**
183
- * @param {number} x
184
- * @param {number} y
185
  * @returns {any}
186
  */
187
- mask_for_point(x, y) {
188
  try {
189
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
190
- wasm.model_mask_for_point(retptr, this.__wbg_ptr, x, y);
191
  var r0 = getInt32Memory0()[retptr / 4 + 0];
192
  var r1 = getInt32Memory0()[retptr / 4 + 1];
193
  var r2 = getInt32Memory0()[retptr / 4 + 2];
@@ -242,10 +327,46 @@ function __wbg_get_imports() {
242
  imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
243
  takeObject(arg0);
244
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
246
  const ret = getObject(arg0);
247
  return addHeapObject(ret);
248
  };
 
 
 
 
 
 
 
 
 
 
 
 
249
  imports.wbg.__wbg_String_4370c5505c674d30 = function(arg0, arg1) {
250
  const ret = String(getObject(arg1));
251
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -265,6 +386,10 @@ function __wbg_get_imports() {
265
  const ret = getStringFromWasm0(arg0, arg1);
266
  return addHeapObject(ret);
267
  };
 
 
 
 
268
  imports.wbg.__wbg_set_bd72c078edfa51ad = function(arg0, arg1, arg2) {
269
  getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
270
  };
@@ -290,13 +415,53 @@ function __wbg_get_imports() {
290
  wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
291
  }
292
  };
293
- imports.wbg.__wbg_log_fa2e12d24033131f = function(arg0, arg1) {
294
  console.log(getStringFromWasm0(arg0, arg1));
295
  };
 
 
 
 
 
 
 
 
 
 
 
 
296
  imports.wbg.__wbg_new_898a68150f225f2e = function() {
297
  const ret = new Array();
298
  return addHeapObject(ret);
299
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  imports.wbg.__wbg_new_b51585de1b234aff = function() {
301
  const ret = new Object();
302
  return addHeapObject(ret);
@@ -304,9 +469,59 @@ function __wbg_get_imports() {
304
  imports.wbg.__wbg_set_502d29070ea18557 = function(arg0, arg1, arg2) {
305
  getObject(arg0)[arg1 >>> 0] = takeObject(arg2);
306
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  imports.wbg.__wbindgen_throw = function(arg0, arg1) {
308
  throw new Error(getStringFromWasm0(arg0, arg1));
309
  };
 
 
 
 
310
 
311
  return imports;
312
  }
@@ -318,6 +533,7 @@ function __wbg_init_memory(imports, maybe_memory) {
318
  function __wbg_finalize_init(instance, module) {
319
  wasm = instance.exports;
320
  __wbg_init.__wbindgen_wasm_module = module;
 
321
  cachedInt32Memory0 = null;
322
  cachedUint8Memory0 = null;
323
 
 
47
  return ret;
48
  }
49
 
50
+ function isLikeNone(x) {
51
+ return x === undefined || x === null;
52
+ }
53
 
54
+ let cachedFloat64Memory0 = null;
55
+
56
+ function getFloat64Memory0() {
57
+ if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {
58
+ cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer);
59
+ }
60
+ return cachedFloat64Memory0;
61
  }
62
 
63
  let cachedInt32Memory0 = null;
 
69
  return cachedInt32Memory0;
70
  }
71
 
72
+ let WASM_VECTOR_LEN = 0;
73
+
74
  const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
75
 
76
  const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
 
123
  WASM_VECTOR_LEN = offset;
124
  return ptr;
125
  }
126
+
127
+ function debugString(val) {
128
+ // primitive types
129
+ const type = typeof val;
130
+ if (type == 'number' || type == 'boolean' || val == null) {
131
+ return `${val}`;
132
+ }
133
+ if (type == 'string') {
134
+ return `"${val}"`;
135
+ }
136
+ if (type == 'symbol') {
137
+ const description = val.description;
138
+ if (description == null) {
139
+ return 'Symbol';
140
+ } else {
141
+ return `Symbol(${description})`;
142
+ }
143
+ }
144
+ if (type == 'function') {
145
+ const name = val.name;
146
+ if (typeof name == 'string' && name.length > 0) {
147
+ return `Function(${name})`;
148
+ } else {
149
+ return 'Function';
150
+ }
151
+ }
152
+ // objects
153
+ if (Array.isArray(val)) {
154
+ const length = val.length;
155
+ let debug = '[';
156
+ if (length > 0) {
157
+ debug += debugString(val[0]);
158
+ }
159
+ for(let i = 1; i < length; i++) {
160
+ debug += ', ' + debugString(val[i]);
161
+ }
162
+ debug += ']';
163
+ return debug;
164
+ }
165
+ // Test for built-in
166
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
167
+ let className;
168
+ if (builtInMatches.length > 1) {
169
+ className = builtInMatches[1];
170
+ } else {
171
+ // Failed to match the standard '[object ClassName]'
172
+ return toString.call(val);
173
+ }
174
+ if (className == 'Object') {
175
+ // we're a user defined class or Object
176
+ // JSON.stringify avoids problems with cycles, and is generally much
177
+ // easier than looping through ownProperties of `val`.
178
+ try {
179
+ return 'Object(' + JSON.stringify(val) + ')';
180
+ } catch (_) {
181
+ return 'Object';
182
+ }
183
+ }
184
+ // errors
185
+ if (val instanceof Error) {
186
+ return `${val.name}: ${val.message}\n${val.stack}`;
187
+ }
188
+ // TODO we could test for more things here, like `Set`s and `Map`s.
189
+ return className;
190
+ }
191
+
192
+ function passArray8ToWasm0(arg, malloc) {
193
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
194
+ getUint8Memory0().set(arg, ptr / 1);
195
+ WASM_VECTOR_LEN = arg.length;
196
+ return ptr;
197
+ }
198
+
199
+ function handleError(f, args) {
200
+ try {
201
+ return f.apply(this, args);
202
+ } catch (e) {
203
+ wasm.__wbindgen_exn_store(addHeapObject(e));
204
+ }
205
+ }
206
  /**
207
  */
208
  export class Model {
 
266
  }
267
  }
268
  /**
269
+ * @param {any} input
 
270
  * @returns {any}
271
  */
272
+ mask_for_point(input) {
273
  try {
274
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
275
+ wasm.model_mask_for_point(retptr, this.__wbg_ptr, addHeapObject(input));
276
  var r0 = getInt32Memory0()[retptr / 4 + 0];
277
  var r1 = getInt32Memory0()[retptr / 4 + 1];
278
  var r2 = getInt32Memory0()[retptr / 4 + 2];
 
327
  imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
328
  takeObject(arg0);
329
  };
330
+ imports.wbg.__wbindgen_boolean_get = function(arg0) {
331
+ const v = getObject(arg0);
332
+ const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
333
+ return ret;
334
+ };
335
+ imports.wbg.__wbindgen_number_get = function(arg0, arg1) {
336
+ const obj = getObject(arg1);
337
+ const ret = typeof(obj) === 'number' ? obj : undefined;
338
+ getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret;
339
+ getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret);
340
+ };
341
+ imports.wbg.__wbindgen_is_object = function(arg0) {
342
+ const val = getObject(arg0);
343
+ const ret = typeof(val) === 'object' && val !== null;
344
+ return ret;
345
+ };
346
+ imports.wbg.__wbindgen_is_undefined = function(arg0) {
347
+ const ret = getObject(arg0) === undefined;
348
+ return ret;
349
+ };
350
+ imports.wbg.__wbindgen_in = function(arg0, arg1) {
351
+ const ret = getObject(arg0) in getObject(arg1);
352
+ return ret;
353
+ };
354
  imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
355
  const ret = getObject(arg0);
356
  return addHeapObject(ret);
357
  };
358
+ imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
359
+ const ret = getObject(arg0) == getObject(arg1);
360
+ return ret;
361
+ };
362
+ imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
363
+ const obj = getObject(arg1);
364
+ const ret = typeof(obj) === 'string' ? obj : undefined;
365
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
366
+ var len1 = WASM_VECTOR_LEN;
367
+ getInt32Memory0()[arg0 / 4 + 1] = len1;
368
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1;
369
+ };
370
  imports.wbg.__wbg_String_4370c5505c674d30 = function(arg0, arg1) {
371
  const ret = String(getObject(arg1));
372
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
 
386
  const ret = getStringFromWasm0(arg0, arg1);
387
  return addHeapObject(ret);
388
  };
389
+ imports.wbg.__wbg_getwithrefkey_d1f0d12f1f1b63ea = function(arg0, arg1) {
390
+ const ret = getObject(arg0)[getObject(arg1)];
391
+ return addHeapObject(ret);
392
+ };
393
  imports.wbg.__wbg_set_bd72c078edfa51ad = function(arg0, arg1, arg2) {
394
  getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
395
  };
 
415
  wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
416
  }
417
  };
418
+ imports.wbg.__wbg_log_cfcb93115564df45 = function(arg0, arg1) {
419
  console.log(getStringFromWasm0(arg0, arg1));
420
  };
421
+ imports.wbg.__wbindgen_is_function = function(arg0) {
422
+ const ret = typeof(getObject(arg0)) === 'function';
423
+ return ret;
424
+ };
425
+ imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) {
426
+ const ret = getObject(arg0)[arg1 >>> 0];
427
+ return addHeapObject(ret);
428
+ };
429
+ imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) {
430
+ const ret = getObject(arg0).length;
431
+ return ret;
432
+ };
433
  imports.wbg.__wbg_new_898a68150f225f2e = function() {
434
  const ret = new Array();
435
  return addHeapObject(ret);
436
  };
437
+ imports.wbg.__wbg_next_526fc47e980da008 = function(arg0) {
438
+ const ret = getObject(arg0).next;
439
+ return addHeapObject(ret);
440
+ };
441
+ imports.wbg.__wbg_next_ddb3312ca1c4e32a = function() { return handleError(function (arg0) {
442
+ const ret = getObject(arg0).next();
443
+ return addHeapObject(ret);
444
+ }, arguments) };
445
+ imports.wbg.__wbg_done_5c1f01fb660d73b5 = function(arg0) {
446
+ const ret = getObject(arg0).done;
447
+ return ret;
448
+ };
449
+ imports.wbg.__wbg_value_1695675138684bd5 = function(arg0) {
450
+ const ret = getObject(arg0).value;
451
+ return addHeapObject(ret);
452
+ };
453
+ imports.wbg.__wbg_iterator_97f0c81209c6c35a = function() {
454
+ const ret = Symbol.iterator;
455
+ return addHeapObject(ret);
456
+ };
457
+ imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) {
458
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
459
+ return addHeapObject(ret);
460
+ }, arguments) };
461
+ imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) {
462
+ const ret = getObject(arg0).call(getObject(arg1));
463
+ return addHeapObject(ret);
464
+ }, arguments) };
465
  imports.wbg.__wbg_new_b51585de1b234aff = function() {
466
  const ret = new Object();
467
  return addHeapObject(ret);
 
469
  imports.wbg.__wbg_set_502d29070ea18557 = function(arg0, arg1, arg2) {
470
  getObject(arg0)[arg1 >>> 0] = takeObject(arg2);
471
  };
472
+ imports.wbg.__wbg_isArray_4c24b343cb13cfb1 = function(arg0) {
473
+ const ret = Array.isArray(getObject(arg0));
474
+ return ret;
475
+ };
476
+ imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) {
477
+ let result;
478
+ try {
479
+ result = getObject(arg0) instanceof ArrayBuffer;
480
+ } catch {
481
+ result = false;
482
+ }
483
+ const ret = result;
484
+ return ret;
485
+ };
486
+ imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) {
487
+ const ret = getObject(arg0).buffer;
488
+ return addHeapObject(ret);
489
+ };
490
+ imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) {
491
+ const ret = new Uint8Array(getObject(arg0));
492
+ return addHeapObject(ret);
493
+ };
494
+ imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) {
495
+ getObject(arg0).set(getObject(arg1), arg2 >>> 0);
496
+ };
497
+ imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) {
498
+ const ret = getObject(arg0).length;
499
+ return ret;
500
+ };
501
+ imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function(arg0) {
502
+ let result;
503
+ try {
504
+ result = getObject(arg0) instanceof Uint8Array;
505
+ } catch {
506
+ result = false;
507
+ }
508
+ const ret = result;
509
+ return ret;
510
+ };
511
+ imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
512
+ const ret = debugString(getObject(arg1));
513
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
514
+ const len1 = WASM_VECTOR_LEN;
515
+ getInt32Memory0()[arg0 / 4 + 1] = len1;
516
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1;
517
+ };
518
  imports.wbg.__wbindgen_throw = function(arg0, arg1) {
519
  throw new Error(getStringFromWasm0(arg0, arg1));
520
  };
521
+ imports.wbg.__wbindgen_memory = function() {
522
+ const ret = wasm.memory;
523
+ return addHeapObject(ret);
524
+ };
525
 
526
  return imports;
527
  }
 
533
  function __wbg_finalize_init(instance, module) {
534
  wasm = instance.exports;
535
  __wbg_init.__wbindgen_wasm_module = module;
536
+ cachedFloat64Memory0 = null;
537
  cachedInt32Memory0 = null;
538
  cachedUint8Memory0 = null;
539
 
build/m_bg.wasm CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:acfbd107ec1c84a9ed5388cd1afd0e494bb99426d5e162e1d017c28cca325553
3
- size 2579585
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3aa7201ff46d314086d7c2aa49e7a415901414fc3c5e584a9762344dc759b6d6
3
+ size 2667717
build/m_bg.wasm.d.ts CHANGED
@@ -4,10 +4,11 @@ export const memory: WebAssembly.Memory;
4
  export function __wbg_model_free(a: number): void;
5
  export function model_new(a: number, b: number, c: number, d: number): void;
6
  export function model_set_image_embeddings(a: number, b: number, c: number, d: number): void;
7
- export function model_mask_for_point(a: number, b: number, c: number, d: number): void;
8
  export function main(a: number, b: number): number;
9
- export function __wbindgen_add_to_stack_pointer(a: number): number;
10
  export function __wbindgen_malloc(a: number, b: number): number;
11
  export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
 
12
  export function __wbindgen_free(a: number, b: number, c: number): void;
 
13
  export function __wbindgen_start(): void;
 
4
  export function __wbg_model_free(a: number): void;
5
  export function model_new(a: number, b: number, c: number, d: number): void;
6
  export function model_set_image_embeddings(a: number, b: number, c: number, d: number): void;
7
+ export function model_mask_for_point(a: number, b: number, c: number): void;
8
  export function main(a: number, b: number): number;
 
9
  export function __wbindgen_malloc(a: number, b: number): number;
10
  export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
11
+ export function __wbindgen_add_to_stack_pointer(a: number): number;
12
  export function __wbindgen_free(a: number, b: number, c: number): void;
13
+ export function __wbindgen_exn_store(a: number): void;
14
  export function __wbindgen_start(): void;
lib-example.html ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
4
+ <title>Candle Segment Anything Model (SAM) Rust/WASM</title>
5
+ </head>
6
+ <body></body>
7
+ </html>
8
+
9
+ <!DOCTYPE html>
10
+ <html>
11
+ <head>
12
+ <meta charset="UTF-8" />
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14
+ <style>
15
+ @import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@200;300;400&family=Source+Sans+3:wght@100;200;300;400;500;600;700;800;900&display=swap");
16
+ html,
17
+ body {
18
+ font-family: "Source Sans 3", sans-serif;
19
+ }
20
+ </style>
21
+ <script src="https://cdn.tailwindcss.com"></script>
22
+ <script type="module">
23
+ // base url for image examples
24
+ const MODEL_BASEURL =
25
+ "https://huggingface.co/lmz/candle-sam/resolve/main/";
26
+
27
+ // models base url
28
+ const MODELS = {
29
+ sam_mobile_tiny: {
30
+ url: "mobile_sam-tiny-vitt.safetensors",
31
+ },
32
+ sam_base: {
33
+ url: "sam_vit_b_01ec64.safetensors",
34
+ },
35
+ };
36
+ const samWorker = new Worker("./samWorker.js", { type: "module" });
37
+
38
+ async function segmentPoints(
39
+ modelURL, // URL to the weights file
40
+ modelID, // model ID
41
+ imageURL, // URL to the image file
42
+ points // {x, y} points to prompt image
43
+ ) {
44
+ return new Promise((resolve, reject) => {
45
+ function messageHandler(event) {
46
+ console.log(event.data);
47
+ if ("status" in event.data) {
48
+ updateStatus(event.data);
49
+ }
50
+ if ("error" in event.data) {
51
+ samWorker.removeEventListener("message", messageHandler);
52
+ reject(new Error(event.data.error));
53
+ }
54
+ if (event.data.status === "complete-embedding") {
55
+ samWorker.removeEventListener("message", messageHandler);
56
+ resolve();
57
+ }
58
+ if (event.data.status === "complete") {
59
+ samWorker.removeEventListener("message", messageHandler);
60
+ resolve(event.data.output);
61
+ }
62
+ }
63
+ samWorker.addEventListener("message", messageHandler);
64
+ samWorker.postMessage({
65
+ modelURL,
66
+ modelID,
67
+ imageURL,
68
+ points,
69
+ });
70
+ });
71
+ }
72
+ function updateStatus(statusMessage) {
73
+ statusOutput.innerText = event.data.message;
74
+ }
75
+
76
+ const clearBtn = document.querySelector("#clear-btn");
77
+ const maskBtn = document.querySelector("#mask-btn");
78
+ const undoBtn = document.querySelector("#undo-btn");
79
+ const canvas = document.querySelector("#canvas");
80
+ const mask = document.querySelector("#mask");
81
+ const ctxCanvas = canvas.getContext("2d");
82
+ const ctxMask = mask.getContext("2d");
83
+ const fileUpload = document.querySelector("#file-upload");
84
+ const dropArea = document.querySelector("#drop-area");
85
+ const dropButtons = document.querySelector("#drop-buttons");
86
+ const imagesExamples = document.querySelector("#image-select");
87
+ const modelSelection = document.querySelector("#model");
88
+ const statusOutput = document.querySelector("#output-status");
89
+
90
+ //add event listener to file input
91
+ fileUpload.addEventListener("change", (e) => {
92
+ const target = e.target;
93
+ if (target.files.length > 0) {
94
+ const href = URL.createObjectURL(target.files[0]);
95
+ cleanImageCanvas();
96
+ drawImageCanvas(href);
97
+ setImageEmbeddings(href);
98
+ }
99
+ });
100
+ // add event listener to drop-area
101
+ dropArea.addEventListener("dragenter", (e) => {
102
+ e.preventDefault();
103
+ dropArea.classList.add("border-blue-700");
104
+ });
105
+ dropArea.addEventListener("dragleave", (e) => {
106
+ e.preventDefault();
107
+ dropArea.classList.remove("border-blue-700");
108
+ });
109
+ dropArea.addEventListener("dragover", (e) => {
110
+ e.preventDefault();
111
+ });
112
+ dropArea.addEventListener("drop", (e) => {
113
+ e.preventDefault();
114
+ dropArea.classList.remove("border-blue-700");
115
+ const url = e.dataTransfer.getData("text/uri-list");
116
+ const files = e.dataTransfer.files;
117
+
118
+ if (files.length > 0) {
119
+ const href = URL.createObjectURL(files[0]);
120
+ cleanImageCanvas();
121
+ drawImageCanvas(href);
122
+ setImageEmbeddings(href);
123
+ } else if (url) {
124
+ cleanImageCanvas();
125
+ drawImageCanvas(url);
126
+ setImageEmbeddings(url);
127
+ }
128
+ });
129
+
130
+ let hasImage = false;
131
+ let isSegmenting = false;
132
+ let isEmbedding = false;
133
+ let currentImageURL = "";
134
+ let pointArr = [];
135
+ let bgPointMode = false;
136
+ //add event listener to image examples
137
+ imagesExamples.addEventListener("click", (e) => {
138
+ if (isEmbedding || isSegmenting) {
139
+ return;
140
+ }
141
+ const target = e.target;
142
+ if (target.nodeName === "IMG") {
143
+ const href = target.src;
144
+ cleanImageCanvas();
145
+ drawImageCanvas(href);
146
+ setImageEmbeddings(href);
147
+ }
148
+ });
149
+ //add event listener to mask button
150
+ maskBtn.addEventListener("click", () => {
151
+ togglePointMode();
152
+ });
153
+ //add event listener to clear button
154
+ clearBtn.addEventListener("click", () => {
155
+ cleanImageCanvas();
156
+ togglePointMode(false);
157
+ pointArr = [];
158
+ });
159
+ //add event listener to undo button
160
+ undoBtn.addEventListener("click", () => {
161
+ undoPoint();
162
+ });
163
+ //add click event to canvas
164
+ canvas.addEventListener("click", async (event) => {
165
+ if (!hasImage || isEmbedding || isSegmenting) {
166
+ return;
167
+ }
168
+ const targetBox = event.target.getBoundingClientRect();
169
+ const x = (event.clientX - targetBox.left) / targetBox.width;
170
+ const y = (event.clientY - targetBox.top) / targetBox.height;
171
+ isSegmenting = true;
172
+ pointArr = [...pointArr, [x, y, !bgPointMode]];
173
+ undoBtn.disabled = false;
174
+ const { maskURL } = await getSegmentationMask(pointArr);
175
+ isSegmenting = false;
176
+ drawMask(maskURL);
177
+ });
178
+ async function undoPoint() {
179
+ if (!hasImage || isEmbedding || isSegmenting) {
180
+ return;
181
+ }
182
+ if (pointArr.length === 0) {
183
+ return;
184
+ }
185
+ pointArr.pop();
186
+ if (pointArr.length === 0) {
187
+ ctxMask.clearRect(0, 0, canvas.width, canvas.height);
188
+ undoBtn.disabled = true;
189
+ return;
190
+ }
191
+ isSegmenting = true;
192
+ const { maskURL } = await getSegmentationMask(pointArr);
193
+ isSegmenting = false;
194
+ drawMask(maskURL);
195
+ }
196
+ function togglePointMode(mode) {
197
+ bgPointMode = mode ? mode : !bgPointMode;
198
+
199
+ maskBtn.querySelector("span").innerText = bgPointMode
200
+ ? "Background Point"
201
+ : "Mask Point";
202
+ if (bgPointMode) {
203
+ maskBtn.querySelector("#mask-circle").setAttribute("hidden", "");
204
+ maskBtn.querySelector("#unmask-circle").removeAttribute("hidden");
205
+ } else {
206
+ maskBtn.querySelector("#mask-circle").removeAttribute("hidden");
207
+ maskBtn.querySelector("#unmask-circle").setAttribute("hidden", "");
208
+ }
209
+ }
210
+
211
+ async function getSegmentationMask(points) {
212
+ const modelID = modelSelection.value;
213
+ const modelURL = MODEL_BASEURL + MODELS[modelID].url;
214
+ const imageURL = currentImageURL;
215
+ const { maskURL } = await segmentPoints(
216
+ modelURL,
217
+ modelID,
218
+ imageURL,
219
+ points
220
+ );
221
+ return { maskURL };
222
+ }
223
+ async function setImageEmbeddings(imageURL) {
224
+ if (isEmbedding) {
225
+ return;
226
+ }
227
+ canvas.classList.remove("cursor-pointer");
228
+ canvas.classList.add("cursor-wait");
229
+ clearBtn.disabled = true;
230
+ const modelID = modelSelection.value;
231
+ const modelURL = MODEL_BASEURL + MODELS[modelID].url;
232
+ isEmbedding = true;
233
+ await segmentPoints(modelURL, modelID, imageURL);
234
+ canvas.classList.remove("cursor-wait");
235
+ canvas.classList.add("cursor-pointer");
236
+ clearBtn.disabled = false;
237
+ isEmbedding = false;
238
+ currentImageURL = imageURL;
239
+ }
240
+
241
+ function cleanImageCanvas() {
242
+ ctxCanvas.clearRect(0, 0, canvas.width, canvas.height);
243
+ ctxMask.clearRect(0, 0, canvas.width, canvas.height);
244
+ hasImage = false;
245
+ isEmbedding = false;
246
+ isSegmenting = false;
247
+ currentImageURL = "";
248
+ clearBtn.disabled = true;
249
+ canvas.parentElement.style.height = "auto";
250
+ dropButtons.classList.remove("invisible");
251
+ }
252
+ function drawMask(maskURL) {
253
+ if (!maskURL) {
254
+ throw new Error("No mask URL provided");
255
+ }
256
+
257
+ const img = new Image();
258
+ img.crossOrigin = "anonymous";
259
+
260
+ img.onload = () => {
261
+ mask.width = canvas.width;
262
+ mask.height = canvas.height;
263
+ ctxMask.drawImage(canvas, 0, 0);
264
+ ctxMask.globalCompositeOperation = "source-atop";
265
+ ctxMask.fillStyle = "rgba(255, 0, 0, 0.6)";
266
+ ctxMask.fillRect(0, 0, canvas.width, canvas.height);
267
+ ctxMask.globalCompositeOperation = "destination-in";
268
+ ctxMask.drawImage(img, 0, 0);
269
+ };
270
+ img.src = maskURL;
271
+ }
272
+ function drawImageCanvas(imgURL) {
273
+ if (!imgURL) {
274
+ throw new Error("No image URL provided");
275
+ }
276
+
277
+ ctxCanvas.clearRect(0, 0, canvas.width, canvas.height);
278
+ ctxCanvas.clearRect(0, 0, canvas.width, canvas.height);
279
+
280
+ const img = new Image();
281
+ img.crossOrigin = "anonymous";
282
+
283
+ img.onload = () => {
284
+ canvas.width = img.width;
285
+ canvas.height = img.height;
286
+ ctxCanvas.drawImage(img, 0, 0);
287
+ canvas.parentElement.style.height = canvas.offsetHeight + "px";
288
+ hasImage = true;
289
+ clearBtn.disabled = false;
290
+ dropButtons.classList.add("invisible");
291
+ };
292
+ img.src = imgURL;
293
+ }
294
+
295
+ const observer = new ResizeObserver((entries) => {
296
+ for (let entry of entries) {
297
+ if (entry.target === canvas) {
298
+ canvas.parentElement.style.height = canvas.offsetHeight + "px";
299
+ }
300
+ }
301
+ });
302
+ observer.observe(canvas);
303
+ </script>
304
+ </head>
305
+ <body class="container max-w-4xl mx-auto p-4">
306
+ <main class="grid grid-cols-1 gap-8 relative">
307
+ <span class="absolute text-5xl -ml-[1em]">🕯️</span>
308
+ <div>
309
+ <h1 class="text-5xl font-bold">Candle Segment Anything</h1>
310
+ <h2 class="text-2xl font-bold">Rust/WASM Demo</h2>
311
+ <p class="max-w-lg">
312
+ Zero-shot image segmentation with
313
+ <a
314
+ href="https://segment-anything.com"
315
+ class="underline hover:text-blue-500 hover:no-underline"
316
+ target="_blank"
317
+ >Segment Anything Model (SAM)</a
318
+ >
319
+ and
320
+ <a
321
+ href="https://github.com/ChaoningZhang/MobileSAM"
322
+ class="underline hover:text-blue-500 hover:no-underline"
323
+ target="_blank"
324
+ >MobileSAM </a
325
+ >. It runs in the browser with a WASM runtime built with
326
+ <a
327
+ href="https://github.com/huggingface/candle/"
328
+ target="_blank"
329
+ class="underline hover:text-blue-500 hover:no-underline"
330
+ >Candle
331
+ </a>
332
+ </p>
333
+ </div>
334
+ <div>
335
+ <label for="model" class="font-medium">Models Options: </label>
336
+ <select
337
+ id="model"
338
+ class="border-2 border-gray-500 rounded-md font-light">
339
+ <option value="sam_mobile_tiny" selected>
340
+ Mobile SAM Tiny (40.6 MB)
341
+ </option>
342
+ <option value="sam_base">SAM Base (375 MB)</option>
343
+ </select>
344
+ </div>
345
+ <div>
346
+ <p class="text-xs italic max-w-lg">
347
+ <b>Note:</b>
348
+ The model's first run may take a few seconds as it loads and caches
349
+ the model in the browser, and then creates the image embeddings. Any
350
+ subsequent clicks on points will be significantly faster.
351
+ </p>
352
+ </div>
353
+ <div class="relative max-w-2xl">
354
+ <div class="flex justify-between items-center">
355
+ <div class="px-2 rounded-md inline text-xs">
356
+ <span id="output-status" class="m-auto font-light"></span>
357
+ </div>
358
+ <div class="flex gap-2">
359
+ <button
360
+ id="mask-btn"
361
+ title="Toggle Mask Point and Background Point"
362
+ class="text-xs bg-white rounded-md disabled:opacity-50 flex gap-1 items-center">
363
+ <span>Mask Point</span>
364
+ <svg
365
+ xmlns="http://www.w3.org/2000/svg"
366
+ height="1em"
367
+ viewBox="0 0 512 512">
368
+ <path
369
+ id="mask-circle"
370
+ d="M256 512a256 256 0 1 0 0-512 256 256 0 1 0 0 512z" />
371
+ <path
372
+ id="unmask-circle"
373
+ hidden
374
+ d="M464 256a208 208 0 1 0-416 0 208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0 256 256 0 1 1-512 0z" />
375
+ </svg>
376
+ </button>
377
+ <button
378
+ id="undo-btn"
379
+ disabled
380
+ title="Undo Last Point"
381
+ class="text-xs bg-white rounded-md disabled:opacity-50 flex gap-1 items-center">
382
+ <svg
383
+ xmlns="http://www.w3.org/2000/svg"
384
+ height="1em"
385
+ viewBox="0 0 512 512">
386
+ <path
387
+ d="M48.5 224H40a24 24 0 0 1-24-24V72a24 24 0 0 1 41-17l41.6 41.6a224 224 0 1 1-1 317.8 32 32 0 0 1 45.3-45.3 160 160 0 1 0 1-227.3L185 183a24 24 0 0 1-17 41H48.5z" />
388
+ </svg>
389
+ </button>
390
+
391
+ <button
392
+ id="clear-btn"
393
+ disabled
394
+ title="Clear Image"
395
+ class="text-xs bg-white rounded-md disabled:opacity-50 flex gap-1 items-center">
396
+ <svg
397
+ class=""
398
+ xmlns="http://www.w3.org/2000/svg"
399
+ viewBox="0 0 13 12"
400
+ height="1em">
401
+ <path
402
+ d="M1.6.7 12 11.1M12 .7 1.6 11.1"
403
+ stroke="#2E3036"
404
+ stroke-width="2" />
405
+ </svg>
406
+ </button>
407
+ </div>
408
+ </div>
409
+ <div
410
+ id="drop-area"
411
+ class="flex flex-col items-center justify-center border-2 border-gray-300 border-dashed rounded-xl relative p-20 w-full overflow-hidden">
412
+ <div
413
+ id="drop-buttons"
414
+ class="flex flex-col items-center justify-center space-y-1 text-center relative z-10">
415
+ <svg
416
+ width="25"
417
+ height="25"
418
+ viewBox="0 0 25 25"
419
+ fill="none"
420
+ xmlns="http://www.w3.org/2000/svg">
421
+ <path
422
+ d="M3.5 24.3a3 3 0 0 1-1.9-.8c-.5-.5-.8-1.2-.8-1.9V2.9c0-.7.3-1.3.8-1.9.6-.5 1.2-.7 2-.7h18.6c.7 0 1.3.2 1.9.7.5.6.7 1.2.7 2v18.6c0 .7-.2 1.4-.7 1.9a3 3 0 0 1-2 .8H3.6Zm0-2.7h18.7V2.9H3.5v18.7Zm2.7-2.7h13.3c.3 0 .5 0 .6-.3v-.7l-3.7-5a.6.6 0 0 0-.6-.2c-.2 0-.4 0-.5.3l-3.5 4.6-2.4-3.3a.6.6 0 0 0-.6-.3c-.2 0-.4.1-.5.3l-2.7 3.6c-.1.2-.2.4 0 .7.1.2.3.3.6.3Z"
423
+ fill="#000" />
424
+ </svg>
425
+ <div class="flex text-sm text-gray-600">
426
+ <label
427
+ for="file-upload"
428
+ class="relative cursor-pointer bg-white rounded-md font-medium text-blue-950 hover:text-blue-700">
429
+ <span>Drag and drop your image here</span>
430
+ <span class="block text-xs">or</span>
431
+ <span class="block text-xs">Click to upload</span>
432
+ </label>
433
+ </div>
434
+ <input
435
+ id="file-upload"
436
+ name="file-upload"
437
+ type="file"
438
+ class="sr-only" />
439
+ </div>
440
+ <canvas id="canvas" class="absolute w-full"></canvas>
441
+ <canvas
442
+ id="mask"
443
+ class="pointer-events-none absolute w-full"></canvas>
444
+ </div>
445
+ <div class="text-right py-2">
446
+ <button
447
+ id="share-btn"
448
+ class="bg-white rounded-md hover:outline outline-orange-200 disabled:opacity-50 invisible">
449
+ <img
450
+ src="https://huggingface.co/datasets/huggingface/badges/raw/main/share-to-community-sm.svg" />
451
+ </button>
452
+ </div>
453
+ </div>
454
+ <div>
455
+ <div
456
+ class="flex gap-3 items-center overflow-x-scroll"
457
+ id="image-select">
458
+ <h3 class="font-medium">Examples:</h3>
459
+
460
+ <img
461
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/sf.jpg"
462
+ class="cursor-pointer w-24 h-24 object-cover" />
463
+ <img
464
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/bike.jpeg"
465
+ class="cursor-pointer w-24 h-24 object-cover" />
466
+ <img
467
+ src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/candle/examples/000000000077.jpg"
468
+ class="cursor-pointer w-24 h-24 object-cover" />
469
+ </div>
470
+ </div>
471
+ </main>
472
+ </body>
473
+ </html>
samWorker.js CHANGED
@@ -141,7 +141,7 @@ self.addEventListener("message", async (event) => {
141
  }
142
 
143
  self.postMessage({ status: "segmenting", message: "Segmenting" });
144
- const { mask, image } = sam.mask_for_point(points.x, points.y);
145
  const maskDataURL = await createImageCanvas(mask, image);
146
  // Send the segment back to the main thread as JSON
147
  self.postMessage({
 
141
  }
142
 
143
  self.postMessage({ status: "segmenting", message: "Segmenting" });
144
+ const { mask, image } = sam.mask_for_point({ points });
145
  const maskDataURL = await createImageCanvas(mask, image);
146
  // Send the segment back to the main thread as JSON
147
  self.postMessage({