@capturebridge/sdk 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/IFace.js CHANGED
@@ -1,274 +1,278 @@
1
- import ICAO from './ICAO.js'
2
- import { BASE_URL, blobToBase64 } from './Common.js'
3
-
4
- // This is not exported as we may eventually detect this from the plugin
5
- // See: Iface.matchModes()
6
- const VALID_MODES = ['accurate', 'balanced', 'fast', 'accurate_server']
7
-
8
- /**
9
- * Probe
10
- * @classdesc Probe Class for Innovatrics IFace SDK
11
- *
12
- * @see {@link IFace}
13
- */
14
- export class Probe {
15
- source
16
- url
17
- imageData
18
- /**
19
- * Instantiate an IFace Probe
20
- * @constructor
21
- * @param {string} source - The image source for the probe.
22
- * @param {string} [type] - The type of data in the image source, valid values
23
- * are 'url', 'base64', and 'dataurl'. If not provided 'base64' is the default.
24
- *
25
- * @example
26
- * const candidate = new Candidate('/person/123.jpg', '123', 'url')
27
- */
28
- constructor (source, type = 'base64') {
29
- // TODO:
30
- // If the source is typeof object and/or type=object we should do some duck
31
- // typing and accept any of...
32
- // - The result of an ICAO check that contains a cropped image
33
- // - An Image tag (fetch the source)
34
- // - A Blob
35
- // - An Array Buffer
36
- // - An object that has a fullCapture method (call function in .data())
37
- switch (type) {
38
- case 'url':
39
- this.url = source
40
- break
41
- case 'base64':
42
- this.imageData = source
43
- break
44
- case 'dataurl':
45
- this.imageData = source.split(',')[1]
46
- break
47
- case undefined:
48
- case null:
49
- default:
50
- throw new Error('Invalid image source type provided')
51
- }
52
- }
53
-
54
- /**
55
- * Fetch the image data and base64 encode it
56
- * @async
57
- * @example
58
- * const probe = new Probe("/img/photo.jpg")
59
- * await probe.data()
60
- * console.log(probe.imageData)
61
- */
62
- async data () {
63
- if (!this.imageData) {
64
- const response = await fetch(this.url)
65
- const blob = await response.blob()
66
- this.imageData = await blobToBase64(blob)
67
- }
68
- }
69
-
70
- toJSON () {
71
- return this.imageData
72
- }
73
- }
74
-
75
- /**
76
- * Candidate
77
- * @classdesc Candidate Class for Innovatrics IFace SDK
78
- *
79
- * @see {@link IFace}
80
- */
81
- export class Candidate extends Probe {
82
- id
83
-
84
- // TODO: Support setting different modes on individual candidates
85
- // an example usecase for this is to set 'accurate_server' the most recent
86
- // photo, and 'fast' for the remaining set (since they likely have already
87
- // been verified at some point) In the plugin we would have to re-template the
88
- // probe for each additional mode and it doesn't make sense to do so until
89
- // the plugin is checking each photo against the probe in a separate thread.
90
- mode
91
-
92
- /**
93
- * Instantiate an IFace Candidate
94
- * @constructor
95
- * @param {string} source - The image source for the candidate.
96
- * @param {string} id - The ID for the candidate when the match results are
97
- * returned this Id will be returned with it's respective results.
98
- * @param {string} [type] - The type of data in the image source, valid values
99
- * are 'url', 'base64', and 'dataurl'. If not provided 'base64' is the default.
100
- *
101
- * @example
102
- * const candidate = new Candidate('/person/123.jpg', '123', 'url')
103
- */
104
- constructor (source, id, type = 'base64') {
105
- super(source, type)
106
- if (id) {
107
- this.id = id
108
- } else {
109
- throw new Error('Candidate ID not provided')
110
- }
111
- }
112
-
113
- toJSON () {
114
- return {
115
- id: this.id,
116
- base64: this.imageData
117
- }
118
- }
119
- }
120
-
121
- /**
122
- * IFace
123
- * @classdesc Class for Innovatrics IFace SDK
124
- *
125
- */
126
- export class IFace extends ICAO {
127
- /**
128
- * Instantiate an IFace plugin
129
- * @constructor
130
- * @param {string} [baseURL] - Protocol, domain, and port for the service.
131
- *
132
- * @example
133
- * const iface = new IFace()
134
- */
135
- constructor (baseUrl = BASE_URL) {
136
- super('capture_verify_iface', baseUrl)
137
- }
138
-
139
- /**
140
- * Return list of available face matching modes
141
- *
142
- * @returns {string[]} List of available face matching modes
143
- *
144
- * @async
145
- * @example
146
- * const iface = new IFace()
147
- * const modes = await iface.matchModes()
148
- * // do something with modes, such as build a <select> element
149
- * const select = document.createElement('select')
150
- * modes.forEach(mode => {
151
- * const option = document.createElement('option')
152
- * option.value = mode
153
- * select.appendChild(mode)
154
- * })
155
- * document.body.appendChild(select)
156
- */
157
- async matchModes () {
158
- // This is async as we may later get this from the plugin at runtime
159
- return VALID_MODES
160
- }
161
-
162
- matchModesHandler (callback) {
163
- callback(null, VALID_MODES)
164
- }
165
-
166
- /**
167
- * Check the ICAO compliance of an image
168
- * @param {string} image - A base64 encoded image.
169
- *
170
- * @param {string|bool} [crop] - If falsy image will not be cropped, otherwise
171
- * the value will be interpreted as the preferred crop method which will vary
172
- * by plugin implementation.
173
- *
174
- * @returns {object} Results of the ICAO check, this may vary by plugin
175
- * implementation.
176
- *
177
- * @async
178
- * @example
179
- * // Take a photo with a Canon Camera and perform ICAO checks on the
180
- * // returned image
181
- * const camera = new CanonCamera()
182
- * const photo = await camera.takePhoto('base64')
183
- * const iface = new IFace()
184
- * const results = await iface.icao(photo)
185
- * const img = document.createElement('img')
186
- * img.src = 'data:image/jpeg;base64,' + results.cropped
187
- * console.log(`found ${result.faces_found} faces in the image`)
188
- * document.body.appendChild(img)
189
- */
190
- async icao (image, cropMethod = false) {
191
- return await this.check(image, cropMethod)
192
- }
193
-
194
- /**
195
- * Perform a facial match against one or more photos.
196
- *
197
- * @param {object|string} probe - Either a Probe object or a base64 encoded
198
- * image that is being compared or searched against one or more candidates
199
- *
200
- * @param {object[]} candidates - An array of candidate objects against which
201
- * the probe photo is compared.
202
- * @param {string} candidates[].id - Id of the photo, when the results of the
203
- * matched are returned, this id will be returned so results can be matched
204
- * back to their original image. Must be less than 16 characters.
205
- * @param {string} candidates[].base64 - Base64 encoded string containing the
206
- * photo.
207
- * @param {string} [candidates[].mode] - Matching mode to use for this photo.
208
- * If left unspecified will use the mode provided in the mode parameter.
209
- *
210
- * @param {string} [mode=fast] - Matching mode to use for all images, can be
211
- * overriden on each candidate if desired. Valid values are: 'accurate',
212
- * 'balanced', 'fast', and 'accurate_server'.
213
- *
214
- * @async
215
- * @example
216
- * // Create an iface object
217
- * const iface = new IFace()
218
- *
219
- * // Obtain a photo for the probe photo
220
- * const probe = await camera.takePhoto('base64')
221
- *
222
- * // Create a candidate set from the person's previous photos
223
- * const candidates = [
224
- * new Candidate('/person/1/photo/2.jpg', '3', 'url'),
225
- * new Candidate('/person/1/photo/1.jpg', '2', 'url')
226
- * ]
227
- *
228
- * // Match the probe to all the candidates using the 'balanced' mode
229
- * const results = await iface.match(probe, candidates, 'balanced')
230
- *
231
- * // use the results
232
- * console.log(results)
233
- */
234
- async match (probe, candidates, mode = 'fast') {
235
- if (VALID_MODES.indexOf(mode) === -1) {
236
- throw new Error('Invalid mode provided')
237
- }
238
-
239
- // If this is a Probe object fetch it's image data
240
- if (typeof probe === 'object' && probe.constructor.name === 'Probe') {
241
- await probe.data()
242
- }
243
-
244
- // And fetch data for candidates
245
- const asyncOperations = candidates.map(async candidate => {
246
- if (typeof candidate === 'object' &&
247
- candidate.constructor.name === 'Candidate') {
248
- await candidate.data()
249
- }
250
- })
251
-
252
- // Wait for all async operations to complete
253
- await Promise.all(asyncOperations)
254
-
255
- const body = {
256
- probe,
257
- mode,
258
- candidates
259
- }
260
- const options = {
261
- method: 'POST',
262
- mode: 'cors',
263
- headers: {
264
- 'Content-Type': 'application/json'
265
- },
266
- body: JSON.stringify(body)
267
- }
268
- const url = `${this.baseUrl}/plugin/${this.id}/face/match`
269
- const response = await fetch(url, options)
270
- return await response.json()
271
- }
272
- }
273
-
274
- export default IFace
1
+ /**
2
+ * @module IFace
3
+ */
4
+
5
+ import ICAO from './ICAO.js'
6
+ import { BASE_URL, blobToBase64 } from './Common.js'
7
+
8
+ // This is not exported as we may eventually detect this from the plugin
9
+ // See: Iface.matchModes()
10
+ const VALID_MODES = ['accurate', 'balanced', 'fast', 'accurate_server']
11
+
12
+ /**
13
+ * Probe
14
+ * @classdesc Probe Class for Innovatrics IFace SDK
15
+ *
16
+ * @see {@link IFace}
17
+ */
18
+ export class Probe {
19
+ source
20
+ url
21
+ imageData
22
+ /**
23
+ * Instantiate an IFace Probe
24
+ * @constructor
25
+ * @param {string} source - The image source for the probe.
26
+ * @param {string} [type] - The type of data in the image source, valid values
27
+ * are 'url', 'base64', and 'dataurl'. If not provided 'base64' is the default.
28
+ *
29
+ * @example
30
+ * const candidate = new Candidate('/person/123.jpg', '123', 'url')
31
+ */
32
+ constructor (source, type = 'base64') {
33
+ // TODO:
34
+ // If the source is typeof object and/or type=object we should do some duck
35
+ // typing and accept any of...
36
+ // - The result of an ICAO check that contains a cropped image
37
+ // - An Image tag (fetch the source)
38
+ // - A Blob
39
+ // - An Array Buffer
40
+ // - An object that has a fullCapture method (call function in .data())
41
+ switch (type) {
42
+ case 'url':
43
+ this.url = source
44
+ break
45
+ case 'base64':
46
+ this.imageData = source
47
+ break
48
+ case 'dataurl':
49
+ this.imageData = source.split(',')[1]
50
+ break
51
+ case undefined:
52
+ case null:
53
+ default:
54
+ throw new Error('Invalid image source type provided')
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Fetch the image data and base64 encode it
60
+ * @async
61
+ * @example
62
+ * const probe = new Probe("/img/photo.jpg")
63
+ * await probe.data()
64
+ * console.log(probe.imageData)
65
+ */
66
+ async data () {
67
+ if (!this.imageData) {
68
+ const response = await fetch(this.url)
69
+ const blob = await response.blob()
70
+ this.imageData = await blobToBase64(blob)
71
+ }
72
+ }
73
+
74
+ toJSON () {
75
+ return this.imageData
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Candidate
81
+ * @classdesc Candidate Class for Innovatrics IFace SDK
82
+ * @extends Probe
83
+ * @see {@link IFace}
84
+ */
85
+ export class Candidate extends Probe {
86
+ id
87
+
88
+ // TODO: Support setting different modes on individual candidates
89
+ // an example usecase for this is to set 'accurate_server' the most recent
90
+ // photo, and 'fast' for the remaining set (since they likely have already
91
+ // been verified at some point) In the plugin we would have to re-template the
92
+ // probe for each additional mode and it doesn't make sense to do so until
93
+ // the plugin is checking each photo against the probe in a separate thread.
94
+ mode
95
+
96
+ /**
97
+ * Instantiate an IFace Candidate
98
+ * @constructor
99
+ * @param {string} source - The image source for the candidate.
100
+ * @param {string} id - The ID for the candidate when the match results are
101
+ * returned this Id will be returned with it's respective results.
102
+ * @param {string} [type] - The type of data in the image source, valid values
103
+ * are 'url', 'base64', and 'dataurl'. If not provided 'base64' is the default.
104
+ *
105
+ * @example
106
+ * const candidate = new Candidate('/person/123.jpg', '123', 'url')
107
+ */
108
+ constructor (source, id, type = 'base64') {
109
+ super(source, type)
110
+ if (id) {
111
+ this.id = id
112
+ } else {
113
+ throw new Error('Candidate ID not provided')
114
+ }
115
+ }
116
+
117
+ toJSON () {
118
+ return {
119
+ id: this.id,
120
+ base64: this.imageData
121
+ }
122
+ }
123
+ }
124
+
125
+ /**
126
+ * IFace
127
+ * @classdesc Class for Innovatrics IFace SDK
128
+ *
129
+ */
130
+ export class IFace extends ICAO {
131
+ /**
132
+ * Instantiate an IFace plugin
133
+ * @constructor
134
+ * @param {string} [baseURL] - Protocol, domain, and port for the service.
135
+ *
136
+ * @example
137
+ * const iface = new IFace()
138
+ */
139
+ constructor (baseUrl = BASE_URL) {
140
+ super('capture_verify_iface', baseUrl)
141
+ }
142
+
143
+ /**
144
+ * Return list of available face matching modes
145
+ *
146
+ * @returns {string[]} List of available face matching modes
147
+ *
148
+ * @async
149
+ * @example
150
+ * const iface = new IFace()
151
+ * const modes = await iface.matchModes()
152
+ * // do something with modes, such as build a <select> element
153
+ * const select = document.createElement('select')
154
+ * modes.forEach(mode => {
155
+ * const option = document.createElement('option')
156
+ * option.value = mode
157
+ * select.appendChild(mode)
158
+ * })
159
+ * document.body.appendChild(select)
160
+ */
161
+ async matchModes () {
162
+ // This is async as we may later get this from the plugin at runtime
163
+ return VALID_MODES
164
+ }
165
+
166
+ matchModesHandler (callback) {
167
+ callback(null, VALID_MODES)
168
+ }
169
+
170
+ /**
171
+ * Check the ICAO compliance of an image
172
+ * @param {string} image - A base64 encoded image.
173
+ *
174
+ * @param {string|bool} [crop] - If falsy image will not be cropped, otherwise
175
+ * the value will be interpreted as the preferred crop method which will vary
176
+ * by plugin implementation.
177
+ *
178
+ * @returns {object} Results of the ICAO check, this may vary by plugin
179
+ * implementation.
180
+ *
181
+ * @async
182
+ * @example
183
+ * // Take a photo with a Canon Camera and perform ICAO checks on the
184
+ * // returned image
185
+ * const camera = new CanonCamera()
186
+ * const photo = await camera.takePhoto('base64')
187
+ * const iface = new IFace()
188
+ * const results = await iface.icao(photo)
189
+ * const img = document.createElement('img')
190
+ * img.src = 'data:image/jpeg;base64,' + results.cropped
191
+ * console.log(`found ${result.faces_found} faces in the image`)
192
+ * document.body.appendChild(img)
193
+ */
194
+ async icao (image, cropMethod = false) {
195
+ return await this.check(image, cropMethod)
196
+ }
197
+
198
+ /**
199
+ * Perform a facial match against one or more photos.
200
+ *
201
+ * @param {object|string} probe - Either a Probe object or a base64 encoded
202
+ * image that is being compared or searched against one or more candidates
203
+ *
204
+ * @param {object[]} candidates - An array of candidate objects against which
205
+ * the probe photo is compared.
206
+ * @param {string} candidates[].id - Id of the photo, when the results of the
207
+ * matched are returned, this id will be returned so results can be matched
208
+ * back to their original image. Must be less than 16 characters.
209
+ * @param {string} candidates[].base64 - Base64 encoded string containing the
210
+ * photo.
211
+ * @param {string} [candidates[].mode] - Matching mode to use for this photo.
212
+ * If left unspecified will use the mode provided in the mode parameter.
213
+ *
214
+ * @param {string} [mode=fast] - Matching mode to use for all images, can be
215
+ * overriden on each candidate if desired. Valid values are: 'accurate',
216
+ * 'balanced', 'fast', and 'accurate_server'.
217
+ *
218
+ * @async
219
+ * @example
220
+ * // Create an iface object
221
+ * const iface = new IFace()
222
+ *
223
+ * // Obtain a photo for the probe photo
224
+ * const probe = await camera.takePhoto('base64')
225
+ *
226
+ * // Create a candidate set from the person's previous photos
227
+ * const candidates = [
228
+ * new Candidate('/person/1/photo/2.jpg', '3', 'url'),
229
+ * new Candidate('/person/1/photo/1.jpg', '2', 'url')
230
+ * ]
231
+ *
232
+ * // Match the probe to all the candidates using the 'balanced' mode
233
+ * const results = await iface.match(probe, candidates, 'balanced')
234
+ *
235
+ * // use the results
236
+ * console.log(results)
237
+ */
238
+ async match (probe, candidates, mode = 'fast') {
239
+ if (VALID_MODES.indexOf(mode) === -1) {
240
+ throw new Error('Invalid mode provided')
241
+ }
242
+
243
+ // If this is a Probe object fetch it's image data
244
+ if (typeof probe === 'object' && probe.constructor.name === 'Probe') {
245
+ await probe.data()
246
+ }
247
+
248
+ // And fetch data for candidates
249
+ const asyncOperations = candidates.map(async candidate => {
250
+ if (typeof candidate === 'object' &&
251
+ candidate.constructor.name === 'Candidate') {
252
+ await candidate.data()
253
+ }
254
+ })
255
+
256
+ // Wait for all async operations to complete
257
+ await Promise.all(asyncOperations)
258
+
259
+ const body = {
260
+ probe,
261
+ mode,
262
+ candidates
263
+ }
264
+ const options = {
265
+ method: 'POST',
266
+ mode: 'cors',
267
+ headers: {
268
+ 'Content-Type': 'application/json'
269
+ },
270
+ body: JSON.stringify(body)
271
+ }
272
+ const url = `${this.baseUrl}/plugin/${this.id}/face/match`
273
+ const response = await fetch(url, options)
274
+ return await response.json()
275
+ }
276
+ }
277
+
278
+ export default IFace