1
+ import { InferenceSession , Tensor } from "onnxruntime-web" ;
2
+ import ndarray from "ndarray" ;
3
+ import ops from "ndarray-ops" ;
4
+
5
+ async function loadAgeModel ( ) {
6
+ var feature_session = null ;
7
+ await InferenceSession . create ( "../model/fr_age.onnx" , { executionProviders : [ 'wasm' ] } )
8
+ . then ( ( session ) => {
9
+ feature_session = session
10
+ const input_tensor = new Tensor ( "float32" , new Float32Array ( 64 * 64 * 3 ) , [ 1 , 3 , 64 , 64 ] ) ;
11
+ for ( let i = 0 ; i < 64 * 64 * 3 ; i ++ ) {
12
+ input_tensor . data [ i ] = Math . random ( ) * 2.0 - 1.0 ;
13
+ }
14
+ const feeds = { "input" : input_tensor } ;
15
+ const output_tensor = feature_session . run ( feeds )
16
+ console . log ( "initialize the age session." )
17
+ } )
18
+ return feature_session ;
19
+ }
20
+
21
+ function alignAgeImage ( image , bbox , scale_value ) {
22
+ var src_h = image . rows ,
23
+ src_w = image . cols ;
24
+
25
+ var x = bbox [ 0 ]
26
+ var y = bbox [ 1 ]
27
+ var box_w = bbox [ 2 ]
28
+ var box_h = bbox [ 3 ]
29
+
30
+ var scale = Math . min ( ( src_h - 1 ) / box_h , Math . min ( ( src_w - 1 ) / box_w , scale_value ) )
31
+
32
+ var new_width = box_w * scale
33
+ var new_height = box_h * scale
34
+ var center_x = box_w / 2 + x ,
35
+ center_y = box_h / 2 + y
36
+
37
+ var left_top_x = center_x - new_width / 2
38
+ var left_top_y = center_y - new_height / 2
39
+ var right_bottom_x = center_x + new_width / 2
40
+ var right_bottom_y = center_y + new_height / 2
41
+
42
+ if ( left_top_x < 0 ) {
43
+ right_bottom_x -= left_top_x
44
+ left_top_x = 0
45
+ }
46
+
47
+ if ( left_top_y < 0 ) {
48
+ right_bottom_y -= left_top_y
49
+ left_top_y = 0
50
+ }
51
+
52
+ if ( right_bottom_x > src_w - 1 ) {
53
+ left_top_x -= right_bottom_x - src_w + 1
54
+ right_bottom_x = src_w - 1
55
+ }
56
+
57
+ if ( right_bottom_y > src_h - 1 ) {
58
+ left_top_y -= right_bottom_y - src_h + 1
59
+ right_bottom_y = src_h - 1
60
+ }
61
+ var rect = new cv . Rect ( Math . max ( parseInt ( left_top_x ) , 0 ) , Math . max ( parseInt ( left_top_y ) , 0 ) ,
62
+ Math . min ( parseInt ( right_bottom_x - left_top_x ) , src_w - 1 ) , Math . min ( parseInt ( right_bottom_y - left_top_y ) , src_h - 1 ) )
63
+
64
+ var face_image = new cv . Mat ( )
65
+ face_image = image . roi ( rect )
66
+
67
+ var dsize = new cv . Size ( 64 , 64 ) ;
68
+ var resize_image = new cv . Mat ( ) ;
69
+ cv . resize ( face_image , resize_image , dsize ) ;
70
+
71
+ face_image . delete ( )
72
+ return resize_image
73
+ }
74
+
75
+ function mergeAge ( x , s1 , s2 , s3 , lambda_local , lambda_d ) {
76
+ let a = 0 ;
77
+ let b = 0 ;
78
+ let c = 0 ;
79
+
80
+ const V = 101 ;
81
+
82
+ for ( let i = 0 ; i < s1 ; i ++ )
83
+ a = a + ( i + lambda_local * x [ 12 + i ] ) * x [ i ] ;
84
+ // console.log("a = ", a)
85
+
86
+ a = a / ( s1 * ( 1 + lambda_d * x [ 9 ] ) ) ;
87
+
88
+ for ( let i = 0 ; i < s2 ; i ++ )
89
+ b = b + ( i + lambda_local * x [ 15 + i ] ) * x [ 3 + i ] ;
90
+ //console.log("b = ", b)
91
+
92
+ b = b / ( s1 * ( 1 + lambda_d * x [ 9 ] ) ) / ( s2 * ( 1 + lambda_d * x [ 10 ] ) ) ;
93
+
94
+ for ( let i = 0 ; i < s3 ; i ++ )
95
+ c = c + ( i + lambda_local * x [ 18 + i ] ) * x [ 6 + i ] ;
96
+ //console.log("c = ", c)
97
+
98
+ c = c / ( s1 * ( 1 + lambda_d * x [ 9 ] ) ) / ( s2 * ( 1 + lambda_d * x [ 10 ] ) ) / ( s3 * ( 1 + lambda_d * x [ 11 ] ) ) ;
99
+ return ( a + b + c ) * V ;
100
+ }
101
+
102
+ function preprocessAge ( img ) {
103
+ var cols = img . cols ;
104
+ var rows = img . rows ;
105
+ var channels = 3 ;
106
+
107
+ var img_data = ndarray ( new Float32Array ( rows * cols * channels ) , [ rows , cols , channels ] ) ;
108
+
109
+ for ( var y = 0 ; y < rows ; y ++ )
110
+ for ( var x = 0 ; x < cols ; x ++ ) {
111
+ let pixel = img . ucharPtr ( y , x ) ;
112
+ // if(x == 0 && y == 0)
113
+ // console.log(pixel);
114
+ for ( var c = 0 ; c < channels ; c ++ ) {
115
+ var pixel_value = 0
116
+ if ( c === 0 ) // R
117
+ pixel_value = ( pixel [ c ] / 255.0 - 0.485 ) / 0.229
118
+ if ( c === 1 ) // G
119
+ pixel_value = ( pixel [ c ] / 255.0 - 0.456 ) / 0.224
120
+ if ( c === 2 ) // B
121
+ pixel_value = ( pixel [ c ] / 255.0 - 0.406 ) / 0.225
122
+
123
+ img_data . set ( y , x , c , pixel_value )
124
+ }
125
+ }
126
+
127
+ var preprocesed = ndarray ( new Float32Array ( 3 * 64 * 64 ) , [ 1 , 3 , 64 , 64 ] )
128
+ ops . assign ( preprocesed . pick ( 0 , 0 , null , null ) , img_data . pick ( null , null , 0 ) ) ;
129
+ ops . assign ( preprocesed . pick ( 0 , 1 , null , null ) , img_data . pick ( null , null , 1 ) ) ;
130
+ ops . assign ( preprocesed . pick ( 0 , 2 , null , null ) , img_data . pick ( null , null , 2 ) ) ;
131
+
132
+ return preprocesed
133
+ }
134
+
135
+ async function predictAge ( session , canvas_id , bbox ) {
136
+ var img = cv . imread ( canvas_id ) ;
137
+
138
+ var face_size = bbox . shape [ 0 ] ;
139
+ var bbox_size = bbox . shape [ 1 ] ;
140
+
141
+ const result = [ ] ;
142
+ for ( let i = 0 ; i < face_size ; i ++ ) {
143
+ var x1 = parseInt ( bbox . data [ i * bbox_size ] ) ,
144
+ y1 = parseInt ( bbox . data [ i * bbox_size + 1 ] ) ,
145
+ x2 = parseInt ( bbox . data [ i * bbox_size + 2 ] ) ,
146
+ y2 = parseInt ( bbox . data [ i * bbox_size + 3 ] ) ,
147
+ width = Math . abs ( x2 - x1 ) ,
148
+ height = Math . abs ( y2 - y1 ) ;
149
+
150
+ var face_img = alignAgeImage ( img , [ x1 , y1 , width , height ] , 1.4 ) ;
151
+ //cv.imshow("live-temp", face_img);
152
+ var input_image = preprocessAge ( face_img ) ;
153
+ face_img . delete ( ) ;
154
+
155
+ const input_tensor = new Tensor ( "float32" , new Float32Array ( 64 * 64 * 3 ) , [ 1 , 3 , 64 , 64 ] ) ;
156
+ input_tensor . data . set ( input_image . data ) ;
157
+ const feeds = { "input" : input_tensor } ;
158
+
159
+ const output_tensor = await session . run ( feeds ) ;
160
+ const outputLayers = [ "prob_stage_1" , "prob_stage_2" , "prob_stage_3" , "stage1_delta_k" , "stage2_delta_k" , "stage3_delta_k" ,
161
+ "index_offset_stage1" , "index_offset_stage2" , "index_offset_stage3" ] ;
162
+
163
+ const outputFeat = [ ] ;
164
+ for ( let i = 0 ; i < outputLayers . length ; i ++ ) {
165
+ const result = output_tensor [ outputLayers [ i ] ] ;
166
+ // console.log(outputLayers[i], ": ", result.size);
167
+ for ( let j = 0 ; j < result . size ; j ++ )
168
+ outputFeat . push ( result . data [ j ] ) ;
169
+ }
170
+
171
+ let age = mergeAge ( outputFeat , 3 , 3 , 3 , 1 , 1 ) ;
172
+ console . log ( "output age: " , age ) ;
173
+ result . push ( [ x1 , y1 , x2 , y2 , age ] ) ;
174
+ }
175
+
176
+ img . delete ( ) ;
177
+ return result ;
178
+ }
179
+
180
+ export { loadAgeModel , predictAge }
0 commit comments