98 lines
2.6 KiB
JavaScript
98 lines
2.6 KiB
JavaScript
"use strict";
|
|
|
|
const Promise = require("bluebird");
|
|
|
|
let photoDB;
|
|
|
|
function bufferToFloat32Array(buffer) {
|
|
return new Float64Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Float64Array.BYTES_PER_ELEMENT);
|
|
}
|
|
|
|
function euclideanDistance(a, b) {
|
|
let A = bufferToFloat32Array(a);
|
|
let B = bufferToFloat32Array(b);
|
|
console.log(A.length, B.length);
|
|
let sum = 0;
|
|
for (let i = 0; i < A.length; i++) {
|
|
let delta = A[i] - B[i];
|
|
sum += delta * delta;
|
|
}
|
|
return Math.sqrt(sum);
|
|
}
|
|
|
|
require("./db/photos").then(function(db) {
|
|
photoDB = db;
|
|
})
|
|
.then(async () => {
|
|
const id = 7;
|
|
const filter = ` WHERE identities.id=:id `;
|
|
const identities = await photoDB.sequelize.query("SELECT " +
|
|
"identities.*," +
|
|
"GROUP_CONCAT(faces.id) AS relatedFaceIds," +
|
|
"GROUP_CONCAT(faces.descriptorId) AS relatedFaceDescriptorIds," +
|
|
"GROUP_CONCAT(faces.photoId) AS relatedFacePhotoIds " +
|
|
"FROM identities " +
|
|
"INNER JOIN faces ON identities.id=faces.identityId " +
|
|
filter +
|
|
"GROUP BY identities.id", {
|
|
replacements: { id },
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
});
|
|
|
|
await Promise.map(identities, async (identity) => {
|
|
[ 'firstName', 'middleName', 'lastName' ].forEach(key => {
|
|
if (!identity[key]) {
|
|
identity[key] = '';
|
|
}
|
|
});
|
|
|
|
const relatedFaces = identity.relatedFaceIds.split(","),
|
|
relatedFacePhotos = identity.relatedFacePhotoIds.split(",");
|
|
|
|
let descriptors = await photoDB.sequelize.query(
|
|
`SELECT descriptors FROM facedescriptors WHERE id in (:ids)`, {
|
|
replacements: {
|
|
ids: identity.relatedFaceDescriptorIds.split(',')
|
|
},
|
|
type: photoDB.Sequelize.QueryTypes.SELECT,
|
|
raw: true
|
|
}
|
|
);
|
|
|
|
descriptors = descriptors.map(entry => entry.descriptors);
|
|
|
|
identity.relatedFaces = relatedFaces.map((faceId, index) => {
|
|
const distance = euclideanDistance(
|
|
descriptors[index],
|
|
identity.descriptors
|
|
);
|
|
|
|
console.log(index, distance);
|
|
return {
|
|
faceId,
|
|
photoId: relatedFacePhotos[index],
|
|
distance
|
|
};
|
|
});
|
|
|
|
identity
|
|
.relatedFaces
|
|
.sort((A, B) => {
|
|
return A.distance - B.distance;
|
|
});
|
|
|
|
/* If no filter was specified, only return the best face for
|
|
* the identity */
|
|
if (!filter) {
|
|
identity.relatedFaces = [ identity.relatedFaces[0] ];
|
|
}
|
|
|
|
delete identity.descriptors;
|
|
delete identity.relatedFaceIds;
|
|
delete identity.relatedFacePhotoIds;
|
|
delete identity.relatedIdentityDescriptors;
|
|
}, {
|
|
concurrency: 10
|
|
});
|
|
}); |