2020-08-20 02:10:42 +02:00
import { FaceMatch } from '../classes/FaceMatch' ;
import { LabeledFaceDescriptors } from '../classes/LabeledFaceDescriptors' ;
import { euclideanDistance } from '../euclideanDistance' ;
export class FaceMatcher {
2020-08-18 14:04:33 +02:00
constructor ( inputs , distanceThreshold = 0.6 ) {
this . _distanceThreshold = distanceThreshold ;
const inputArray = Array . isArray ( inputs ) ? inputs : [ inputs ] ;
if ( ! inputArray . length ) {
throw new Error ( ` FaceRecognizer.constructor - expected atleast one input ` ) ;
}
let count = 1 ;
const createUniqueLabel = ( ) => ` person ${ count ++ } ` ;
this . _labeledDescriptors = inputArray . map ( ( desc ) => {
2020-08-20 02:10:42 +02:00
if ( desc instanceof LabeledFaceDescriptors ) {
2020-08-18 14:04:33 +02:00
return desc ;
}
if ( desc instanceof Float32Array ) {
2020-08-20 02:10:42 +02:00
return new LabeledFaceDescriptors ( createUniqueLabel ( ) , [ desc ] ) ;
2020-08-18 14:04:33 +02:00
}
if ( desc . descriptor && desc . descriptor instanceof Float32Array ) {
2020-08-20 02:10:42 +02:00
return new LabeledFaceDescriptors ( createUniqueLabel ( ) , [ desc . descriptor ] ) ;
2020-08-18 14:04:33 +02:00
}
throw new Error ( ` FaceRecognizer.constructor - expected inputs to be of type LabeledFaceDescriptors | WithFaceDescriptor<any> | Float32Array | Array<LabeledFaceDescriptors | WithFaceDescriptor<any> | Float32Array> ` ) ;
} ) ;
}
get labeledDescriptors ( ) { return this . _labeledDescriptors ; }
get distanceThreshold ( ) { return this . _distanceThreshold ; }
computeMeanDistance ( queryDescriptor , descriptors ) {
return descriptors
2020-08-20 02:10:42 +02:00
. map ( d => euclideanDistance ( d , queryDescriptor ) )
2020-08-18 14:04:33 +02:00
. reduce ( ( d1 , d2 ) => d1 + d2 , 0 )
/ ( d e s c r i p t o r s . l e n g t h | | 1 ) ;
}
matchDescriptor ( queryDescriptor ) {
return this . labeledDescriptors
2020-08-20 02:10:42 +02:00
. map ( ( { descriptors , label } ) => new FaceMatch ( label , this . computeMeanDistance ( queryDescriptor , descriptors ) ) )
2020-08-18 14:04:33 +02:00
. reduce ( ( best , curr ) => best . distance < curr . distance ? best : curr ) ;
}
findBestMatch ( queryDescriptor ) {
const bestMatch = this . matchDescriptor ( queryDescriptor ) ;
return bestMatch . distance < this . distanceThreshold
? bestMatch
2020-08-20 02:10:42 +02:00
: new FaceMatch ( 'unknown' , bestMatch . distance ) ;
2020-08-18 14:04:33 +02:00
}
toJSON ( ) {
return {
distanceThreshold : this . distanceThreshold ,
labeledDescriptors : this . labeledDescriptors . map ( ( ld ) => ld . toJSON ( ) )
} ;
}
static fromJSON ( json ) {
const labeledDescriptors = json . labeledDescriptors
2020-08-20 02:10:42 +02:00
. map ( ( ld ) => LabeledFaceDescriptors . fromJSON ( ld ) ) ;
2020-08-18 14:04:33 +02:00
return new FaceMatcher ( labeledDescriptors , json . distanceThreshold ) ;
}
}
//# sourceMappingURL=FaceMatcher.js.map