Face exploration working even better
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
99d8c927ee
commit
17fbb4e21c
@ -21,6 +21,7 @@ div {
|
|||||||
|
|
||||||
.Resizer {
|
.Resizer {
|
||||||
width: 0.5rem;
|
width: 0.5rem;
|
||||||
|
background-color: #ccc;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +37,8 @@ div {
|
|||||||
|
|
||||||
.Identities {
|
.Identities {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
padding: 0.25rem;
|
||||||
|
gap: 0.25rem;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 1px solid green;
|
border: 1px solid green;
|
||||||
@ -46,16 +49,13 @@ div {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
border: 2px solid #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Face:hover {
|
.Face:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Face .Image {
|
|
||||||
border: 0.25rem solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClusterEditor {
|
.ClusterEditor {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -82,12 +82,17 @@ div {
|
|||||||
background-position: 50% 50% !important;
|
background-position: 50% 50% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Face:hover .Image {
|
.Active {
|
||||||
border: 0.25rem solid yellow;
|
filter: brightness(1.25);
|
||||||
|
border-color: orange !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Face.Selected .Image {
|
.Face:hover {
|
||||||
border: 0.25rem solid blue;
|
border-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Face.Selected {
|
||||||
|
border-color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Face .Title {
|
.Face .Title {
|
||||||
@ -129,5 +134,6 @@ div {
|
|||||||
|
|
||||||
.Cluster .Faces {
|
.Cluster .Faces {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
gap: 0.25rem;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ import './App.css';
|
|||||||
|
|
||||||
const base = process.env.PUBLIC_URL; /* /identities -- set in .env */
|
const base = process.env.PUBLIC_URL; /* /identities -- set in .env */
|
||||||
|
|
||||||
const makeFaceBoxes = (photo: any, dimensions: any): any => {
|
const makeFaceBoxes = (photo: any, dimensions: any, onFaceClick: any): any => {
|
||||||
const faces: FaceData[] = photo.faces;
|
const faces: FaceData[] = photo.faces;
|
||||||
|
|
||||||
let width: number, height: number, offsetLeft = 0, offsetTop = 0;
|
let width: number, height: number, offsetLeft = 0, offsetTop = 0;
|
||||||
@ -32,20 +32,29 @@ const makeFaceBoxes = (photo: any, dimensions: any): any => {
|
|||||||
offsetTop = 0;
|
offsetTop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return faces.map((face: FaceData) => (
|
return faces.map((face: FaceData) => {
|
||||||
|
const faceId = face.faceId;
|
||||||
|
const identityId = face.identityId;
|
||||||
|
return (
|
||||||
<div className="FaceBox"
|
<div className="FaceBox"
|
||||||
key={face.faceId}
|
key={faceId}
|
||||||
|
data-identity-id={identityId}
|
||||||
|
data-face-id={faceId}
|
||||||
style={{
|
style={{
|
||||||
left: offsetLeft + Math.floor(face.left * width) + "px",
|
left: offsetLeft + Math.floor(face.left * width) + "px",
|
||||||
top: offsetTop + Math.floor(face.top * height) + "px",
|
top: offsetTop + Math.floor(face.top * height) + "px",
|
||||||
width: Math.floor((face.right - face.left) * width) + "px",
|
width: Math.floor((face.right - face.left) * width) + "px",
|
||||||
height: Math.floor((face.bottom - face.top) * height) + "px"
|
height: Math.floor((face.bottom - face.top) * height) + "px"
|
||||||
}}
|
}}
|
||||||
|
onClick={(e) => { onFaceClick(e, face) }}
|
||||||
|
onMouseEnter={(e) => { onFaceMouseEnter(e, face) }}
|
||||||
|
onMouseLeave={(e) => { onFaceMouseLeave(e, face) }}
|
||||||
/>
|
/>
|
||||||
));
|
)
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const Photo = ({ photoId }: any) => {
|
const Photo = ({ photoId, onFaceClick }: any) => {
|
||||||
const [image, setImage] = useState<any>(undefined);
|
const [image, setImage] = useState<any>(undefined);
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
const [dimensions, setDimensions] = React.useState({width: 0, height: 0});
|
const [dimensions, setDimensions] = React.useState({width: 0, height: 0});
|
||||||
@ -54,8 +63,8 @@ const Photo = ({ photoId }: any) => {
|
|||||||
if (image === undefined || dimensions.height === 0) {
|
if (image === undefined || dimensions.height === 0) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
return makeFaceBoxes(image, dimensions);
|
return makeFaceBoxes(image, dimensions, onFaceClick);
|
||||||
}, [image, dimensions]);
|
}, [image, dimensions, onFaceClick]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current) {
|
if (!ref.current) {
|
||||||
@ -92,19 +101,56 @@ const Photo = ({ photoId }: any) => {
|
|||||||
return (<div className="Image"
|
return (<div className="Image"
|
||||||
ref={ref}
|
ref={ref}
|
||||||
style={{
|
style={{
|
||||||
background: `url(../${image.path}thumbs/scaled/${image.filename})`.replace(/ /g, '%20')
|
background: `url("${base}/../${image.path}thumbs/scaled/${image.filename}")`.replace(/ /g, '%20')
|
||||||
}}>{ faces }</div>
|
}}>{ faces }</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Face = ({ faceId, onClick, title, ...rest }: any) => {
|
const onFaceMouseEnter = (e: any, face: FaceData) => {
|
||||||
|
const faceId = face.faceId;
|
||||||
|
const els = [...document.querySelectorAll(`[data-face-id="${faceId}"]`)];
|
||||||
|
|
||||||
|
if (face.identity) {
|
||||||
|
const identityId = face.identity.identityId;
|
||||||
|
els.splice(0, 0,
|
||||||
|
...document.querySelectorAll(`[data-identity-id="${identityId}"]`));
|
||||||
|
}
|
||||||
|
|
||||||
|
els.forEach(el => {
|
||||||
|
el.classList.add('Active');
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFaceMouseLeave = (e: any, face: FaceData) => {
|
||||||
|
const faceId = face.faceId;
|
||||||
|
const els = [...document.querySelectorAll(`[data-face-id="${faceId}"]`)];
|
||||||
|
|
||||||
|
if (face.identity) {
|
||||||
|
const identityId = face.identity.identityId;
|
||||||
|
els.splice(0, 0,
|
||||||
|
...document.querySelectorAll(`[data-identity-id="${identityId}"]`));
|
||||||
|
}
|
||||||
|
|
||||||
|
els.forEach(el => {
|
||||||
|
el.classList.remove('Active');
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const Face = ({ face, onFaceClick, title, ...rest }: any) => {
|
||||||
|
const faceId = face.faceId;
|
||||||
const idPath = String(faceId % 100).padStart(2, '0');
|
const idPath = String(faceId % 100).padStart(2, '0');
|
||||||
return (
|
return (
|
||||||
<div {...rest} onClick={(e) => { onClick(e, faceId) }}
|
<div
|
||||||
|
data-face-id={face.faceId}
|
||||||
|
data-identity-id={face.identityId}
|
||||||
|
{...rest}
|
||||||
|
onClick={(e) => { onFaceClick(e, face) }}
|
||||||
|
onMouseEnter={(e) => { onFaceMouseEnter(e, face) }}
|
||||||
|
onMouseLeave={(e) => { onFaceMouseLeave(e, face) }}
|
||||||
className='Face'>
|
className='Face'>
|
||||||
<div className='Image'
|
<div className='Image'
|
||||||
style={{
|
style={{
|
||||||
background: `url("/faces/${idPath}/${faceId}.jpg")`,
|
background: `url("${base}/../faces/${idPath}/${faceId}.jpg")`,
|
||||||
}}>
|
}}>
|
||||||
<div className='Title'>{title}</div>
|
<div className='Title'>{title}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -113,47 +159,54 @@ const Face = ({ faceId, onClick, title, ...rest }: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type ClusterProps = {
|
type ClusterProps = {
|
||||||
identity: Identity,
|
identity: IdentityData,
|
||||||
setImage(image: number): void,
|
setImage(image: number): void,
|
||||||
setSelected(selected: number[]): void,
|
setSelected(selected: number[]): void,
|
||||||
setIdentity(identity: Identity): void
|
setIdentity(identity: IdentityData): void
|
||||||
};
|
};
|
||||||
|
|
||||||
const Cluster = ({ identity, setIdentity, setImage, setSelected }: ClusterProps) => {
|
const Cluster = ({ identity, setIdentity, setImage, setSelected }: ClusterProps) => {
|
||||||
const relatedFacesJSX = useMemo(() => {
|
const relatedFacesJSX = useMemo(() => {
|
||||||
const faceClicked = async (e: any, id: any) => {
|
const faceClicked = async (e: any, face: FaceData) => {
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const el = e.currentTarget;
|
const el = e.currentTarget;
|
||||||
const face = identity.relatedFaces.find(item => item.faceId === id);
|
|
||||||
if (!face) {
|
/* Control -- select / deselect single item */
|
||||||
return;
|
if (e.ctrlKey) {
|
||||||
}
|
|
||||||
if (e.shiftKey) {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
setImage(face.photoId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.classList.toggle('Selected');
|
el.classList.toggle('Selected');
|
||||||
const selected = [...el.parentElement
|
const selected = [...el.parentElement
|
||||||
.querySelectorAll('.Selected')]
|
.querySelectorAll('.Selected')]
|
||||||
.map((face: any) => face.getAttribute('data-face-id'));
|
.map((face: any) => face.getAttribute('data-face-id'));
|
||||||
setSelected(selected);
|
setSelected(selected);
|
||||||
console.log(face);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift -- select groups */
|
||||||
|
if (e.shiftKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default to load image */
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
setImage(face.photoId);
|
||||||
}
|
}
|
||||||
if (identity === undefined) {
|
if (identity === undefined) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return identity.relatedFaces.map(face =>
|
return identity.relatedFaces.map(face =>
|
||||||
<Face
|
<div
|
||||||
data-face-id={face.faceId}
|
|
||||||
key={face.faceId}
|
key={face.faceId}
|
||||||
faceId={face.faceId}
|
style={{
|
||||||
onClick={faceClicked}
|
display: "flex",
|
||||||
|
alignItems: "center"}}>
|
||||||
|
<Face
|
||||||
|
face={face}
|
||||||
|
onFaceClick={faceClicked}
|
||||||
title={face.distance}/>
|
title={face.distance}/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}, [identity, setImage, setSelected]);
|
}, [identity, setImage, setSelected]);
|
||||||
|
|
||||||
@ -233,6 +286,7 @@ type FaceData = {
|
|||||||
firstName: string,
|
firstName: string,
|
||||||
middleName: string,
|
middleName: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
|
identity: IdentityData,
|
||||||
identityId: number,
|
identityId: number,
|
||||||
distance: number,
|
distance: number,
|
||||||
descriptors: any[],
|
descriptors: any[],
|
||||||
@ -242,40 +296,33 @@ type FaceData = {
|
|||||||
left: number,
|
left: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Identity = {
|
type IdentityData = {
|
||||||
lastName: string,
|
lastName: string,
|
||||||
middleName: string,
|
middleName: string,
|
||||||
firstName: string,
|
firstName: string,
|
||||||
descriptors: number[],
|
descriptors: number[],
|
||||||
id: number
|
identityId: number
|
||||||
displayName: string,
|
displayName: string,
|
||||||
relatedFaces: FaceData[]
|
relatedFaces: FaceData[]
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IdentitiesProps {
|
interface IdentitiesProps {
|
||||||
setIdentity(identity: Identity): void,
|
identities: IdentityData[],
|
||||||
identities: Identity[]
|
onFaceClick(e: any, face: FaceData): void
|
||||||
};
|
};
|
||||||
|
|
||||||
const Identities = ({ identities, setIdentity } : IdentitiesProps) => {
|
const Identities = ({ identities, onFaceClick } : IdentitiesProps) => {
|
||||||
const identitiesJSX = useMemo(() => {
|
const identitiesJSX = useMemo(() => {
|
||||||
const loadIdentity = async (id: number) => {
|
|
||||||
const res = await window.fetch(`${base}/api/v1/identities/${id}`);
|
|
||||||
const data = await res.json();
|
|
||||||
setIdentity(data[0]);
|
|
||||||
};
|
|
||||||
|
|
||||||
return identities.map((identity) => {
|
return identities.map((identity) => {
|
||||||
const face = identity.relatedFaces[0];
|
const face = identity.relatedFaces[0];
|
||||||
return (
|
return (
|
||||||
<Face key={face.faceId}
|
<Face key={face.faceId}
|
||||||
data-face-id={face.faceId}
|
face={face}
|
||||||
faceId={face.faceId}
|
onFaceClick={onFaceClick}
|
||||||
onClick={() => loadIdentity(identity.id)}
|
|
||||||
title={identity.displayName}/>
|
title={identity.displayName}/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, [ setIdentity, identities ]);
|
}, [ identities, onFaceClick ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='Identities'>
|
<div className='Identities'>
|
||||||
@ -293,27 +340,50 @@ const Button = ({ onClick, children }: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [identities, setIdentities] = useState<Identity[]>([]);
|
const [identities, setIdentities] = useState<IdentityData[]>([]);
|
||||||
|
const { identityId, faceId } = useParams();
|
||||||
const [identity, setIdentity] = useState<any>(undefined);
|
const [identity, setIdentity] = useState<any>(undefined);
|
||||||
const [image, setImage] = useState<number>(0);
|
const [image, setImage] = useState<number>(0);
|
||||||
const { loading, data } = useApi(
|
const { loading, data } = useApi(
|
||||||
`${base}/api/v1/identities`
|
`${base}/api/v1/identities`
|
||||||
);
|
);
|
||||||
const [selected, setSelected] = useState<number[]>([]);
|
const [selected, setSelected] = useState<number[]>([]);
|
||||||
const { identityId, faceId } = useParams();
|
|
||||||
|
|
||||||
console.log({ identityId, faceId});
|
const loadIdentity = async (identityId: number) => {
|
||||||
|
try {
|
||||||
|
const res = await window.fetch(`${base}/api/v1/identities/${identityId}`);
|
||||||
|
const data = await res.json();
|
||||||
|
setIdentity(data[0]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (identityId !== undefined && !isNaN(+identityId)) {
|
||||||
|
loadIdentity(+identityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (faceId !== undefined && !isNaN(+faceId)) {
|
||||||
|
setImage(+faceId);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data && data.length) {
|
if (data && data.length) {
|
||||||
setIdentities(data as Identity[]);
|
data.forEach((identity: IdentityData) => {
|
||||||
|
identity.relatedFaces.forEach(face => {
|
||||||
|
face.identity = identity;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setIdentities(data as IdentityData[]);
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const removeSelected = async () => {
|
const removeSelected = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await window.fetch(
|
const res = await window.fetch(
|
||||||
`${base}/api/v1/identities/faces/remove/${identity.id}`, {
|
`${base}/api/v1/identities/faces/remove/${identity.identityId}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ faces: selected })
|
body: JSON.stringify({ faces: selected })
|
||||||
@ -333,6 +403,30 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onFaceClick = (e: any, face: FaceData) => {
|
||||||
|
if (!face.identity) {
|
||||||
|
console.log(`Face ${face.faceId} does not have an Identity`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const identityId = face.identity.identityId;
|
||||||
|
console.log(face.identity);
|
||||||
|
const identitiesEl = document.querySelector('.Identities');
|
||||||
|
if (!identitiesEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const faceIdentity = identitiesEl.querySelector(
|
||||||
|
`[data-identity-id="${identityId}"]`);
|
||||||
|
if (!faceIdentity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
faceIdentity.scrollIntoView()
|
||||||
|
};
|
||||||
|
|
||||||
|
const identitiesOnFaceClick = (e: any, face: FaceData) => {
|
||||||
|
const identityId = face.identity.identityId;
|
||||||
|
loadIdentity(identityId);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<div className="Worksheet">
|
<div className="Worksheet">
|
||||||
@ -357,10 +451,11 @@ const App = () => {
|
|||||||
<PanelResizeHandle className="Resizer"/>
|
<PanelResizeHandle className="Resizer"/>
|
||||||
<Panel>
|
<Panel>
|
||||||
{image === 0 && <div style={{ margin: '1rem' }}>Select image to view</div>}
|
{image === 0 && <div style={{ margin: '1rem' }}>Select image to view</div>}
|
||||||
{image !== 0 && <Photo photoId={image}/> }
|
{image !== 0 && <Photo onFaceClick={onFaceClick} photoId={image}/> }
|
||||||
</Panel>
|
</Panel>
|
||||||
</PanelGroup>
|
</PanelGroup>
|
||||||
{ !loading && <Identities {... {identities, setIdentity }}/> }
|
{ !loading && <Identities
|
||||||
|
{... { onFaceClick: identitiesOnFaceClick, identities }}/> }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -16,6 +16,7 @@ const useApi = (_url: string, _options?: {}) : UseApi => {
|
|||||||
if (_url === '') {
|
if (_url === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchApi = async () => {
|
const fetchApi = async () => {
|
||||||
console.log(`Fetching ${_url}...`);
|
console.log(`Fetching ${_url}...`);
|
||||||
try {
|
try {
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
# DEVELOPMENT -- use npm development server on port 3000 (entrypoint.sh)
|
# DEVELOPMENT -- use npm development server on port 3000 (entrypoint.sh)
|
||||||
|
location /identities/api/v1/ {
|
||||||
|
rewrite ^/identities/api/v1/(.*)$ https://${host}/api/v1/$1 permanent;
|
||||||
|
}
|
||||||
|
|
||||||
location /identities {
|
location /identities {
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
@ -12,11 +16,3 @@ location /identities {
|
|||||||
proxy_set_header Connection "Upgrade";
|
proxy_set_header Connection "Upgrade";
|
||||||
proxy_pass https://localhost:3000;
|
proxy_pass https://localhost:3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /wsapp/ {
|
|
||||||
proxy_pass http://wsbackend;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
}
|
|
@ -1,4 +1,8 @@
|
|||||||
# PRODUCTION -- pre-built source
|
# PRODUCTION -- pre-built source
|
||||||
|
location /identities/api/v1/ {
|
||||||
|
rewrite ^/identities/api/v1/(.*)$ https://${host}/api/v1/$1 permanent;
|
||||||
|
}
|
||||||
|
|
||||||
location /identities {
|
location /identities {
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
alias /website/client/build;
|
alias /website/client/build;
|
||||||
|
@ -174,6 +174,7 @@ router.get("/:id?", async (req, res) => {
|
|||||||
identity[key] = '';
|
identity[key] = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
identity.identityId = identity.id;
|
||||||
|
|
||||||
const relatedFaces = identity.relatedFaceIds.split(","),
|
const relatedFaces = identity.relatedFaceIds.split(","),
|
||||||
relatedFacePhotos = identity.relatedFacePhotoIds.split(",");
|
relatedFacePhotos = identity.relatedFacePhotoIds.split(",");
|
||||||
@ -197,6 +198,7 @@ router.get("/:id?", async (req, res) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
identityId: identity.id,
|
||||||
faceId,
|
faceId,
|
||||||
photoId: relatedFacePhotos[index],
|
photoId: relatedFacePhotos[index],
|
||||||
distance
|
distance
|
||||||
@ -215,6 +217,7 @@ router.get("/:id?", async (req, res) => {
|
|||||||
identity.relatedFaces = [ identity.relatedFaces[0] ];
|
identity.relatedFaces = [ identity.relatedFaces[0] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete identity.id;
|
||||||
delete identity.descriptors;
|
delete identity.descriptors;
|
||||||
delete identity.relatedFaceIds;
|
delete identity.relatedFaceIds;
|
||||||
delete identity.relatedFacePhotoIds;
|
delete identity.relatedFacePhotoIds;
|
||||||
|
@ -1127,8 +1127,8 @@ router.get("/:id", async (req, res) => {
|
|||||||
if (face.identityId) {
|
if (face.identityId) {
|
||||||
const results = await photoDB.sequelize.query(
|
const results = await photoDB.sequelize.query(
|
||||||
`
|
`
|
||||||
SELECT displayName,firstName,lastName,middleName FROM identities
|
SELECT id AS identityId,displayName,firstName,lastName,middleName FROM identities
|
||||||
WHERE id=:id
|
WHERE identityId=:id
|
||||||
`, {
|
`, {
|
||||||
replacements: { id: face.identityId },
|
replacements: { id: face.identityId },
|
||||||
type: photoDB.Sequelize.QueryTypes.SELECT
|
type: photoDB.Sequelize.QueryTypes.SELECT
|
||||||
@ -1136,7 +1136,6 @@ router.get("/:id", async (req, res) => {
|
|||||||
);
|
);
|
||||||
face.identity = results[0];
|
face.identity = results[0];
|
||||||
}
|
}
|
||||||
delete face.identityId;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).json(photo);
|
return res.status(200).json(photo);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user