1
1
import * as ffi from 'ffi' ;
2
2
import * as ref from 'ref' ;
3
3
import * as Struct from 'ref-struct' ;
4
- import { readFileSync } from 'fs' ;
4
+ import { readFileSync } from 'fs' ;
5
5
6
6
7
7
const char_pointer = ref . refType ( 'char' ) ;
@@ -68,15 +68,15 @@ export class DarknetBase {
68
68
this . meta . names = this . names . join ( '\n' ) ;
69
69
70
70
this . darknet = ffi . Library ( library , {
71
- 'float_to_image' : [ IMAGE , [ 'int' , 'int' , 'int' , float_pointer ] ] ,
72
- 'load_image_color' : [ IMAGE , [ 'string' , 'int' , 'int' ] ] ,
73
- 'network_predict_image' : [ float_pointer , [ 'pointer' , IMAGE ] ] ,
74
- 'get_network_boxes' : [ detection_pointer , [ 'pointer' , 'int' , 'int' , 'float' , 'float' , int_pointer , 'int' , int_pointer ] ] ,
75
- 'do_nms_obj' : [ 'void' , [ detection_pointer , 'int' , 'int' , 'float' ] ] ,
76
- 'free_image' : [ 'void' , [ IMAGE ] ] ,
77
- 'free_detections' : [ 'void' , [ detection_pointer , 'int' ] ] ,
78
- 'load_network' : [ 'pointer' , [ 'string' , 'string' , 'int' ] ] ,
79
- 'get_metadata' : [ METADATA , [ 'string' ] ] ,
71
+ 'float_to_image' : [ IMAGE , [ 'int' , 'int' , 'int' , float_pointer ] ] ,
72
+ 'load_image_color' : [ IMAGE , [ 'string' , 'int' , 'int' ] ] ,
73
+ 'network_predict_image' : [ float_pointer , [ 'pointer' , IMAGE ] ] ,
74
+ 'get_network_boxes' : [ detection_pointer , [ 'pointer' , 'int' , 'int' , 'float' , 'float' , int_pointer , 'int' , int_pointer ] ] ,
75
+ 'do_nms_obj' : [ 'void' , [ detection_pointer , 'int' , 'int' , 'float' ] ] ,
76
+ 'free_image' : [ 'void' , [ IMAGE ] ] ,
77
+ 'free_detections' : [ 'void' , [ detection_pointer , 'int' ] ] ,
78
+ 'load_network' : [ 'pointer' , [ 'string' , 'string' , 'int' ] ] ,
79
+ 'get_metadata' : [ METADATA , [ 'string' ] ] ,
80
80
} ) ;
81
81
82
82
this . net = this . darknet . load_network ( config . config , config . weights , 0 ) ;
@@ -361,6 +361,7 @@ export interface IDarknetConfig {
361
361
config : string ;
362
362
names ?: string [ ] ;
363
363
namefile ?: string ;
364
+ processes ?: number ;
364
365
}
365
366
366
367
export interface Detection {
@@ -374,5 +375,92 @@ export interface Detection {
374
375
} ;
375
376
}
376
377
377
- export { Darknet } from './detector' ;
378
- export { Darknet as DarknetExperimental } from './detector' ;
378
+ import { zip , Subject } from 'rxjs' ;
379
+ import { filter , take } from 'rxjs/operators' ;
380
+ import { generate } from 'shortid' ;
381
+
382
+ interface IDetectMe {
383
+ id : string ;
384
+ image : string | IBufferImage
385
+ options ?: IConfig
386
+ }
387
+
388
+ interface IDetection {
389
+ id : string ;
390
+ detections : Detection [ ]
391
+ }
392
+
393
+ export class Darknet {
394
+
395
+ private images$ = new Subject < IDetectMe > ( ) ;
396
+ private completion$ = new Subject ( ) ;
397
+ private detection$ = new Subject < IDetection > ( ) ;
398
+
399
+ private processes : DarknetBase [ ] ;
400
+
401
+ constructor ( config : IDarknetConfig ) {
402
+ const count = Math . min ( config . processes || 1 , 1 ) ;
403
+
404
+ this . processes = new Array ( count ) . fill ( ( ) => (
405
+ new Darknet ( config )
406
+ ) ) . map ( a => a ( ) ) ;
407
+
408
+
409
+ this . subscribeToDetections ( ) ;
410
+ this . completion$ . next ( ) ;
411
+ }
412
+
413
+ private async doAsyncDetection ( darknet : DarknetBase , image : string | IBufferImage , config ?: IConfig ) : Promise < Detection [ ] > {
414
+ if ( ! config ) config = { } ;
415
+ let thresh = ( config . thresh ) ? config . thresh : 0.5 ;
416
+ let hier_thresh = ( config . hier_thresh ) ? config . hier_thresh : 0.5 ;
417
+ let nms = ( config . nms ) ? config . nms : 0.5 ;
418
+
419
+ const darkNetLoadedImage = typeof image === 'string' ;
420
+
421
+ const imageData = typeof image === 'string' ?
422
+ await darknet . getImageFromPathAsync ( image ) :
423
+ await darknet . RGBBufferToImageAsync ( image . b , image . w , image . h , image . c ) ;
424
+
425
+ const detection = await darknet [ '_detectAsync' ] ( darknet . net , darknet . meta , imageData , thresh , hier_thresh , nms ) ;
426
+
427
+ if ( darkNetLoadedImage ) {
428
+ // memory is owned by the darknet lib
429
+ await new Promise ( ( res , rej ) =>
430
+ darknet . darknet . free_image . async ( imageData , ( e : any ) => e ? rej ( e ) : res ( ) )
431
+ ) ;
432
+ } else {
433
+ // memory is owned by JS and will GC eventually
434
+ }
435
+ return detection ;
436
+ }
437
+
438
+ private subscribeToDetections ( ) {
439
+ zip ( this . images$ , this . completion$ )
440
+ . subscribe ( x => {
441
+ this . doAsyncDetection ( x [ 0 ] . image )
442
+ . then ( dets => {
443
+ this . completion$ . next ( ) ;
444
+ this . detection$ . next ( {
445
+ id : x [ 0 ] . id ,
446
+ detections : dets
447
+ } ) ;
448
+ } ) . catch ( er => console . log ( er ) ) ;
449
+ } )
450
+ }
451
+
452
+ detectAsync ( image : string | IBufferImage , options ?: IConfig ) : Promise < Detection [ ] > {
453
+ const id = generate ( ) ;
454
+ this . images$ . next ( { id, image, options} ) ;
455
+ return new Promise ( resolve => {
456
+ this . detection$
457
+ . pipe (
458
+ filter ( det => det . id === id ) ,
459
+ take ( 1 ) ,
460
+ ) . subscribe ( det => resolve ( det . detections ) ) ;
461
+ } ) ;
462
+ }
463
+
464
+ }
465
+
466
+ export const DarknetExperiment = Darknet ;
0 commit comments