1
+ <!DOCTYPE html>
2
+ < html >
3
+ < head >
4
+ < script src ="face-api.js "> </ script >
5
+ < script src ="commons.js "> </ script >
6
+ < link rel ="stylesheet " href ="styles.css ">
7
+ < link rel ="stylesheet " href ="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css ">
8
+ < script type ="text/javascript " src ="https://code.jquery.com/jquery-2.1.1.min.js "> </ script >
9
+ < script src ="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js "> </ script >
10
+ </ head >
11
+ < body >
12
+ < div id ="navbar "> </ div >
13
+ < div class ="center-content page-container ">
14
+ < div class ="progress " id ="loader ">
15
+ < div class ="indeterminate "> </ div >
16
+ </ div >
17
+ < div style ="position: relative " class ="margin ">
18
+ < img id ="inputImg " src ="" style ="max-width: 800px; " />
19
+ < canvas id ="overlay " />
20
+ </ div >
21
+ < div class ="row side-by-side ">
22
+ < div id ="selectList "> </ div >
23
+ < div class ="row ">
24
+ < label for ="imgUrlInput "> Get image from URL:</ label >
25
+ < input id ="imgUrlInput " type ="text " class ="bold ">
26
+ </ div >
27
+ < button
28
+ class ="waves-effect waves-light btn "
29
+ onclick ="loadImageFromUrl() "
30
+ >
31
+ Ok
32
+ </ button >
33
+ </ div >
34
+ < div class ="row side-by-side ">
35
+ < div class ="row side-by-side ">
36
+ < div class ="row ">
37
+ < label for ="minFaceSize "> Minimum Face Size:</ label >
38
+ < input disabled value ="40 " id ="minFaceSize " type ="text " class ="bold ">
39
+ </ div >
40
+ < button
41
+ class ="waves-effect waves-light btn "
42
+ onclick ="onDecreaseMinFaceSize() "
43
+ >
44
+ < i class ="material-icons left "> -</ i >
45
+ </ button >
46
+ < button
47
+ class ="waves-effect waves-light btn "
48
+ onclick ="onIncreaseMinFaceSize() "
49
+ >
50
+ < i class ="material-icons left "> +</ i >
51
+ </ button >
52
+ </ div >
53
+ < div class ="row ">
54
+ < label for ="minConfidence "> Min Confidence:</ label >
55
+ < input disabled value ="0.7 " id ="minConfidence " type ="text " class ="bold ">
56
+ </ div >
57
+ < button
58
+ class ="waves-effect waves-light btn button-sm "
59
+ onclick ="onDecreaseMinConfidence() "
60
+ >
61
+ < i class ="material-icons left "> -</ i >
62
+ </ button >
63
+ < button
64
+ class ="waves-effect waves-light btn button-sm "
65
+ onclick ="onIncreaseMinConfidence() "
66
+ >
67
+ < i class ="material-icons left "> +</ i >
68
+ </ button >
69
+ < div class ="row ">
70
+ < label for ="maxDistance "> Max Descriptor Distance:</ label >
71
+ < input disabled value ="0.6 " id ="maxDistance " type ="text " class ="bold ">
72
+ </ div >
73
+ < button
74
+ class ="waves-effect waves-light btn button-sm "
75
+ onclick ="onDecreaseMaxDistance() "
76
+ >
77
+ < i class ="material-icons left "> -</ i >
78
+ </ button >
79
+ < button
80
+ class ="waves-effect waves-light btn button-sm "
81
+ onclick ="onIncreaseMaxDistance() "
82
+ >
83
+ < i class ="material-icons left "> +</ i >
84
+ </ button >
85
+ </ div >
86
+ </ div >
87
+
88
+ < script >
89
+ let maxDistance = 0.6
90
+ let minConfidence = 0.7
91
+ let minFaceSize = 40
92
+ let trainDescriptorsByClass = [ ]
93
+
94
+ function onIncreaseMinFaceSize ( ) {
95
+ minFaceSize = Math . min ( faceapi . round ( minFaceSize + 20 ) , 200 )
96
+ $ ( '#minFaceSize' ) . val ( minFaceSize )
97
+ }
98
+
99
+ function onDecreaseMinFaceSize ( ) {
100
+ minFaceSize = Math . max ( faceapi . round ( minFaceSize - 20 ) , 20 )
101
+ $ ( '#minFaceSize' ) . val ( minFaceSize )
102
+ }
103
+
104
+ function onIncreaseMinConfidence ( ) {
105
+ minConfidence = Math . min ( faceapi . round ( minConfidence + 0.1 ) , 1.0 )
106
+ $ ( '#minConfidence' ) . val ( minConfidence )
107
+ updateResults ( )
108
+ }
109
+
110
+ function onDecreaseMinConfidence ( ) {
111
+ minConfidence = Math . max ( faceapi . round ( minConfidence - 0.1 ) , 0.1 )
112
+ $ ( '#minConfidence' ) . val ( minConfidence )
113
+ updateResults ( )
114
+ }
115
+
116
+ function onIncreaseMaxDistance ( ) {
117
+ maxDistance = Math . min ( faceapi . round ( maxDistance + 0.1 ) , 1.0 )
118
+ $ ( '#maxDistance' ) . val ( maxDistance )
119
+ updateResults ( )
120
+ }
121
+
122
+ function onDecreaseMaxDistance ( ) {
123
+ maxDistance = Math . max ( faceapi . round ( maxDistance - 0.1 ) , 0.1 )
124
+ $ ( '#maxDistance' ) . val ( maxDistance )
125
+ updateResults ( )
126
+ }
127
+
128
+ async function loadImageFromUrl ( url ) {
129
+ const img = await requestExternalImage ( $ ( '#imgUrlInput' ) . val ( ) )
130
+ $ ( '#inputImg' ) . get ( 0 ) . src = img . src
131
+ updateResults ( )
132
+ }
133
+
134
+ async function updateResults ( ) {
135
+ const inputImgEl = $ ( '#inputImg' ) . get ( 0 )
136
+ const { width, height } = inputImgEl
137
+ const canvas = $ ( '#overlay' ) . get ( 0 )
138
+ canvas . width = width
139
+ canvas . height = height
140
+
141
+ const mtcnnParams = {
142
+ minFaceSize
143
+ }
144
+
145
+ const fullFaceDescriptions = ( await faceapi . allFacesMtcnn ( inputImgEl , mtcnnParams ) )
146
+ . map ( fd => fd . forSize ( width , height ) )
147
+
148
+ fullFaceDescriptions . forEach ( ( { detection, landmarks, descriptor } ) => {
149
+ faceapi . drawDetection ( 'overlay' , [ detection ] , { withScore : false } )
150
+ faceapi . drawLandmarks ( 'overlay' , landmarks , { lineWidth : 4 , color : 'red' } )
151
+ const bestMatch = getBestMatch ( trainDescriptorsByClass , descriptor )
152
+ const text = `${ bestMatch . distance < maxDistance ? bestMatch . className : 'unkown' } (${ bestMatch . distance } )`
153
+ const { x, y, height : boxHeight } = detection . getBox ( )
154
+ faceapi . drawText (
155
+ canvas . getContext ( '2d' ) ,
156
+ x ,
157
+ y + boxHeight ,
158
+ text ,
159
+ Object . assign ( faceapi . getDefaultDrawOptions ( ) , { color : 'red' , fontSize : 16 } )
160
+ )
161
+ } )
162
+ }
163
+
164
+ async function onSelectionChanged ( uri ) {
165
+ const imgBuf = await fetchImage ( uri )
166
+ $ ( `#inputImg` ) . get ( 0 ) . src = ( await faceapi . bufferToImage ( imgBuf ) ) . src
167
+ updateResults ( )
168
+ }
169
+
170
+ async function run ( ) {
171
+ await faceapi . loadMtcnnModel ( '/' )
172
+ await faceapi . loadFaceRecognitionModel ( '/' )
173
+
174
+ trainDescriptorsByClass = await initTrainDescriptorsByClass ( faceapi . recognitionNet , 1 )
175
+
176
+ $ ( '#loader' ) . hide ( )
177
+ onSelectionChanged ( $ ( '#selectList select' ) . val ( ) )
178
+ }
179
+
180
+ $ ( document ) . ready ( function ( ) {
181
+ renderNavBar ( '#navbar' , 'mtcnn_face_recognition' )
182
+ renderImageSelectList (
183
+ '#selectList' ,
184
+ async ( uri ) => {
185
+ await onSelectionChanged ( uri )
186
+ } ,
187
+ 'bbt1.jpg'
188
+ )
189
+ run ( )
190
+ } )
191
+ </ script >
192
+ </ body >
193
+ </ html >
0 commit comments