ID can now be set per face
Signed-off-by: James P. Ketrenos <james.p.ketrenos@intel.com>
This commit is contained in:
parent
40b3a0d819
commit
83e006b43c
@ -403,6 +403,7 @@ const Button = ({ onClick, children }: any) => {
|
||||
const App = () => {
|
||||
const [identities, setIdentities] = useState<IdentityData[]>([]);
|
||||
const { identityId, faceId } = useParams();
|
||||
const [selectedIdentities, setSelectedIdentities] = useState<number[]>([]);
|
||||
const [identity, setIdentity] = useState<IdentityData | undefined>(undefined);
|
||||
const [image, setImage] = useState<number>(0);
|
||||
const { loading, data } = useApi(
|
||||
@ -503,6 +504,27 @@ const App = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const changeSelectedIdentity = async () => {
|
||||
|
||||
if (selectedIdentities.length === 0) {
|
||||
window.alert('You need to select an identity first (CTRL+CLICK)');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await window.fetch(
|
||||
`${base}/api/v1/identities/faces/add/${selectedIdentities[0]}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ faces: selected })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
removeFacesFromIdentities(data.faces);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const markSelectedNotFace = async () => {
|
||||
try {
|
||||
const res = await window.fetch(
|
||||
@ -534,7 +556,36 @@ const App = () => {
|
||||
};
|
||||
|
||||
const identitiesOnFaceClick = (e: any, face: FaceData) => {
|
||||
const identitiesEl = document.querySelector('.Identities');
|
||||
if (!identitiesEl) {
|
||||
return;
|
||||
}
|
||||
const identityId = face.identityId;
|
||||
|
||||
const el = e.currentTarget;
|
||||
|
||||
/* Control -- select / deselect single item */
|
||||
if (e.ctrlKey) {
|
||||
[...identitiesEl.querySelectorAll('.Selected')].forEach(item => {
|
||||
item.classList.remove('Selected')
|
||||
});
|
||||
el.classList.toggle('Selected');
|
||||
|
||||
const selected = [...identitiesEl.querySelectorAll('.Selected')]
|
||||
.map((face: any) => face.getAttribute('data-identity-id'));
|
||||
setSelectedIdentities(selected);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Shift -- select groups */
|
||||
if (e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Default to load image */
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
loadIdentity(identityId);
|
||||
}
|
||||
|
||||
@ -559,6 +610,7 @@ const App = () => {
|
||||
{ selected.length !== 0 && <>
|
||||
<Button onClick={markSelectedIncorrectIdentity}>Remove</Button>
|
||||
<Button onClick={markSelectedNotFace}>Not a face</Button>
|
||||
<Button onClick={changeSelectedIdentity}>Change Identity</Button>
|
||||
</>}
|
||||
</div>
|
||||
</Panel>
|
||||
|
@ -99,7 +99,8 @@ def load_faces(db_path ):
|
||||
FROM faces
|
||||
INNER JOIN photos ON (photos.duplicate == 0 OR photos.duplicate IS NULL)
|
||||
JOIN facedescriptors ON (faces.descriptorId=facedescriptors.id)
|
||||
WHERE faces.identityId IS null
|
||||
WHERE faces.identityId IS null
|
||||
AND faces.classifiedBy != 'not-a-face'
|
||||
AND faces.photoId=photos.id
|
||||
''')
|
||||
for row in res.fetchall():
|
||||
|
@ -134,7 +134,24 @@ router.put('/:id', async (req, res) => {
|
||||
return res.status(200).send(identity);
|
||||
});
|
||||
|
||||
router.put("/faces/remove/:id", (req, res) => {
|
||||
|
||||
const addFaceToIdentityDescriptors = (identity, face) => {
|
||||
};
|
||||
|
||||
const removeFaceToIdentityDescriptors = (identity, face) => {
|
||||
};
|
||||
|
||||
const writeIdentityDescriptors = async (identity) => {
|
||||
await photoDB.sequelize.query(
|
||||
'UPDATE identities ' +
|
||||
'SET descriptors=:descriptors' +
|
||||
'WHERE id=:identityId', {
|
||||
replacements: identity
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
router.put("/faces/remove/:id", async (req, res) => {
|
||||
console.log(`PUT ${req.url}`)
|
||||
if (!req.user.maintainer) {
|
||||
console.warn(`${req.user.name} attempted to modify photos.`);
|
||||
@ -150,23 +167,28 @@ router.put("/faces/remove/:id", (req, res) => {
|
||||
return res.status(400).send({ message: "No faces supplied." });
|
||||
}
|
||||
|
||||
return photoDB.sequelize.query(
|
||||
"UPDATE faces SET identityId=null " +
|
||||
"WHERE id IN (:faceIds)", {
|
||||
replacements: {
|
||||
identityId: id,
|
||||
faceIds: req.body.faces
|
||||
}
|
||||
}).then(() => {
|
||||
try {
|
||||
await photoDB.sequelize.query(
|
||||
"UPDATE faces SET identityId=null " +
|
||||
"WHERE id IN (:faceIds)", {
|
||||
replacements: {
|
||||
identityId: id,
|
||||
faceIds: req.body.faces
|
||||
}
|
||||
});
|
||||
const identity = {
|
||||
id: id,
|
||||
faces: req.body.faces
|
||||
};
|
||||
identity.faces = identity.faces.map(id => +id);
|
||||
|
||||
updateIdentityDescriptors(identity);
|
||||
|
||||
return res.status(200).json(identity);
|
||||
}).catch((error) => {
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(500).send({message: "Error processing request." });
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
router.put("/faces/add/:id", async (req, res) => {
|
||||
@ -197,7 +219,11 @@ router.put("/faces/add/:id", async (req, res) => {
|
||||
id: id,
|
||||
faces: req.body.faces
|
||||
};
|
||||
return res.status(200).json([identity]);
|
||||
identity.faces = identity.faces.map(id => +id);
|
||||
|
||||
updateIdentityDescriptors(identity);
|
||||
|
||||
return res.status(200).json(identity);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(500).send("Error processing request.");
|
||||
@ -249,10 +275,16 @@ router.post("/", (req, res) => {
|
||||
});
|
||||
|
||||
function bufferToFloat32Array(buffer) {
|
||||
return new Float64Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Float64Array.BYTES_PER_ELEMENT);
|
||||
return new Float64Array(buffer.buffer,
|
||||
buffer.byteOffset,
|
||||
buffer.byteLength / Float64Array.BYTES_PER_ELEMENT);
|
||||
}
|
||||
|
||||
function euclideanDistance(a, b) {
|
||||
if (!a.buffer || !b.buffer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let A = bufferToFloat32Array(a);
|
||||
let B = bufferToFloat32Array(b);
|
||||
let sum = 0;
|
||||
@ -270,7 +302,7 @@ const getUnknownIdentity = async (faceCount) => {
|
||||
firstName: '',
|
||||
middleName: '',
|
||||
displayName: 'Unknown',
|
||||
descriptors: [],
|
||||
descriptors: new Float32Array(0),
|
||||
relatedFaces: []
|
||||
};
|
||||
const limit = faceCount
|
||||
@ -293,7 +325,7 @@ const getUnknownIdentity = async (faceCount) => {
|
||||
unknownIdentity.relatedFaces.forEach(face => {
|
||||
face.identityId = -1;
|
||||
face.distance = face.faceConfidence;
|
||||
face.descriptors = [];
|
||||
face.descriptors = new Float32Array(0);
|
||||
delete face.faceConfidence;
|
||||
});
|
||||
return unknownIdentity;
|
||||
@ -361,10 +393,15 @@ router.get("/:id?", async (req, res) => {
|
||||
descriptors = descriptors.map(entry => entry.descriptors);
|
||||
|
||||
identity.relatedFaces = relatedFaces.map((faceId, index) => {
|
||||
const distance = euclideanDistance(
|
||||
descriptors[index],
|
||||
identity.descriptors
|
||||
);
|
||||
let distance = 0;
|
||||
if (descriptors[index] && identity.descriptors) {
|
||||
distance = euclideanDistance(
|
||||
descriptors[index],
|
||||
identity.descriptors
|
||||
);
|
||||
} else {
|
||||
distance = -1;
|
||||
}
|
||||
|
||||
return {
|
||||
identityId: identity.id,
|
||||
|
Loading…
x
Reference in New Issue
Block a user