improving performance
This commit is contained in:
parent
9f1490bc6d
commit
0500ad0e68
@ -85,7 +85,6 @@ export class ThumbnailGeneratorMWs {
|
|||||||
|
|
||||||
const persons: PersonWithPhoto[] = req.resultPipe;
|
const persons: PersonWithPhoto[] = req.resultPipe;
|
||||||
for (let i = 0; i < persons.length; i++) {
|
for (let i = 0; i < persons.length; i++) {
|
||||||
|
|
||||||
// load parameters
|
// load parameters
|
||||||
const mediaPath = path.join(ProjectPath.ImageFolder,
|
const mediaPath = path.join(ProjectPath.ImageFolder,
|
||||||
persons[i].samplePhoto.directory.path,
|
persons[i].samplePhoto.directory.path,
|
||||||
@ -151,8 +150,8 @@ export class ThumbnailGeneratorMWs {
|
|||||||
thPath: thPath,
|
thPath: thPath,
|
||||||
makeSquare: false,
|
makeSquare: false,
|
||||||
cut: {
|
cut: {
|
||||||
left: Math.round(Math.max(0, photo.metadata.faces[0].box.x - margin.x / 2)),
|
left: Math.round(Math.max(0, photo.metadata.faces[0].box.left - margin.x / 2)),
|
||||||
top: Math.round(Math.max(0, photo.metadata.faces[0].box.y - margin.y / 2)),
|
top: Math.round(Math.max(0, photo.metadata.faces[0].box.top - margin.y / 2)),
|
||||||
width: photo.metadata.faces[0].box.width + margin.x,
|
width: photo.metadata.faces[0].box.width + margin.x,
|
||||||
height: photo.metadata.faces[0].box.height + margin.y
|
height: photo.metadata.faces[0].box.height + margin.y
|
||||||
},
|
},
|
||||||
@ -208,7 +207,7 @@ export class ThumbnailGeneratorMWs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static generatePersonThumbnailName(mediaPath: string, faceRegion: FaceRegion, size: number): string {
|
public static generatePersonThumbnailName(mediaPath: string, faceRegion: FaceRegion, size: number): string {
|
||||||
return crypto.createHash('md5').update(mediaPath + '_' + faceRegion.name + '_' + faceRegion.box.x + '_' + faceRegion.box.y)
|
return crypto.createHash('md5').update(mediaPath + '_' + faceRegion.name + '_' + faceRegion.box.left + '_' + faceRegion.box.top)
|
||||||
.digest('hex') + '_' + size + '.jpg';
|
.digest('hex') + '_' + size + '.jpg';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export interface IPersonManager {
|
|||||||
|
|
||||||
keywordsToPerson(media: MediaDTO[]): Promise<void>;
|
keywordsToPerson(media: MediaDTO[]): Promise<void>;
|
||||||
|
|
||||||
updateCounts(): Promise<void>;
|
onGalleryIndexUpdate(): Promise<void>;
|
||||||
|
|
||||||
updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry>;
|
updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export class PersonManager implements IPersonManager {
|
|||||||
throw new Error('not supported by memory DB');
|
throw new Error('not supported by memory DB');
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCounts(): Promise<void> {
|
onGalleryIndexUpdate(): Promise<void> {
|
||||||
throw new Error('not supported by memory DB');
|
throw new Error('not supported by memory DB');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -274,8 +274,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
|
|||||||
directory: dir.id
|
directory: dir.id
|
||||||
})
|
})
|
||||||
.leftJoinAndSelect('face.person', 'person')
|
.leftJoinAndSelect('face.person', 'person')
|
||||||
.select(['face.id', 'face.box.x',
|
.select(['face.id', 'face.box.left',
|
||||||
'face.box.y', 'face.box.width', 'face.box.height',
|
'face.box.top', 'face.box.width', 'face.box.height',
|
||||||
'media.id', 'person.name', 'person.id'])
|
'media.id', 'person.name', 'person.id'])
|
||||||
.getMany();
|
.getMany();
|
||||||
for (let i = 0; i < dir.media.length; i++) {
|
for (let i = 0; i < dir.media.length; i++) {
|
||||||
|
|||||||
@ -260,8 +260,8 @@ export class IndexingManager implements IIndexingManager {
|
|||||||
for (let j = 0; j < indexedFaces.length; j++) {
|
for (let j = 0; j < indexedFaces.length; j++) {
|
||||||
if (indexedFaces[j].box.height === scannedFaces[i].box.height &&
|
if (indexedFaces[j].box.height === scannedFaces[i].box.height &&
|
||||||
indexedFaces[j].box.width === scannedFaces[i].box.width &&
|
indexedFaces[j].box.width === scannedFaces[i].box.width &&
|
||||||
indexedFaces[j].box.x === scannedFaces[i].box.x &&
|
indexedFaces[j].box.left === scannedFaces[i].box.left &&
|
||||||
indexedFaces[j].box.y === scannedFaces[i].box.y &&
|
indexedFaces[j].box.top === scannedFaces[i].box.top &&
|
||||||
indexedFaces[j].person.name === scannedFaces[i].name) {
|
indexedFaces[j].person.name === scannedFaces[i].name) {
|
||||||
face = indexedFaces[j];
|
face = indexedFaces[j];
|
||||||
indexedFaces.splice(j, 1);
|
indexedFaces.splice(j, 1);
|
||||||
@ -289,7 +289,7 @@ export class IndexingManager implements IIndexingManager {
|
|||||||
await this.saveChildDirs(connection, currentDirId, scannedDirectory);
|
await this.saveChildDirs(connection, currentDirId, scannedDirectory);
|
||||||
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
|
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
|
||||||
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
|
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
|
||||||
await ObjectManagers.getInstance().PersonManager.updateCounts();
|
await ObjectManagers.getInstance().PersonManager.onGalleryIndexUpdate();
|
||||||
await ObjectManagers.getInstance().VersionManager.updateDataVersion();
|
await ObjectManagers.getInstance().VersionManager.updateDataVersion();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@ -6,10 +6,12 @@ import {PhotoDTO} from '../../../common/entities/PhotoDTO';
|
|||||||
import {MediaEntity} from './enitites/MediaEntity';
|
import {MediaEntity} from './enitites/MediaEntity';
|
||||||
import {FaceRegionEntry} from './enitites/FaceRegionEntry';
|
import {FaceRegionEntry} from './enitites/FaceRegionEntry';
|
||||||
import {PersonDTO} from '../../../common/entities/PersonDTO';
|
import {PersonDTO} from '../../../common/entities/PersonDTO';
|
||||||
|
import {Utils} from '../../../common/Utils';
|
||||||
|
|
||||||
const LOG_TAG = '[PersonManager]';
|
const LOG_TAG = '[PersonManager]';
|
||||||
|
|
||||||
export class PersonManager implements IPersonManager {
|
export class PersonManager implements IPersonManager {
|
||||||
|
samplePhotos: { [key: string]: PhotoDTO } = {};
|
||||||
persons: PersonEntry[] = [];
|
persons: PersonEntry[] = [];
|
||||||
|
|
||||||
async updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry> {
|
async updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry> {
|
||||||
@ -34,22 +36,25 @@ export class PersonManager implements IPersonManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getSamplePhoto(name: string): Promise<PhotoDTO> {
|
async getSamplePhoto(name: string): Promise<PhotoDTO> {
|
||||||
const connection = await SQLConnection.getConnection();
|
if (!this.samplePhotos[name]) {
|
||||||
const rawAndEntities = await connection.getRepository(MediaEntity).createQueryBuilder('media')
|
const connection = await SQLConnection.getConnection();
|
||||||
.limit(1)
|
const rawAndEntities = await connection.getRepository(MediaEntity).createQueryBuilder('media')
|
||||||
.leftJoinAndSelect('media.directory', 'directory')
|
.limit(1)
|
||||||
.leftJoinAndSelect('media.metadata.faces', 'faces')
|
.leftJoinAndSelect('media.directory', 'directory')
|
||||||
.leftJoinAndSelect('faces.person', 'person')
|
.leftJoinAndSelect('media.metadata.faces', 'faces')
|
||||||
.where('person.name LIKE :name COLLATE utf8_general_ci', {name: name}).getRawAndEntities();
|
.leftJoin('faces.person', 'person')
|
||||||
|
.where('person.name LIKE :name COLLATE utf8_general_ci', {name: name}).getRawAndEntities();
|
||||||
|
|
||||||
if (rawAndEntities.entities.length === 0) {
|
if (rawAndEntities.entities.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
const media: PhotoDTO = Utils.clone(rawAndEntities.entities[0]);
|
||||||
|
|
||||||
|
media.metadata.faces = [FaceRegionEntry.fromRawToDTO(rawAndEntities.raw[0])];
|
||||||
|
|
||||||
|
this.samplePhotos[name] = media;
|
||||||
}
|
}
|
||||||
const media: PhotoDTO = rawAndEntities.entities[0];
|
return this.samplePhotos[name];
|
||||||
|
|
||||||
media.metadata.faces = [FaceRegionEntry.fromRawToDTO(rawAndEntities.raw[0])];
|
|
||||||
|
|
||||||
return media;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +134,12 @@ export class PersonManager implements IPersonManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async onGalleryIndexUpdate() {
|
||||||
|
await this.updateCounts();
|
||||||
|
this.samplePhotos = {};
|
||||||
|
}
|
||||||
|
|
||||||
public async updateCounts() {
|
public async updateCounts() {
|
||||||
const connection = await SQLConnection.getConnection();
|
const connection = await SQLConnection.getConnection();
|
||||||
await connection.query('update person_entry set count = ' +
|
await connection.query('update person_entry set count = ' +
|
||||||
|
|||||||
@ -9,9 +9,9 @@ export class FaceRegionBoxEntry implements FaceRegionBox {
|
|||||||
@Column('int')
|
@Column('int')
|
||||||
width: number;
|
width: number;
|
||||||
@Column('int')
|
@Column('int')
|
||||||
x: number;
|
left: number;
|
||||||
@Column('int')
|
@Column('int')
|
||||||
y: number;
|
top: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,13 +42,13 @@ export class FaceRegionEntry {
|
|||||||
faces_personId: number,
|
faces_personId: number,
|
||||||
faces_boxHeight: number,
|
faces_boxHeight: number,
|
||||||
faces_boxWidth: number,
|
faces_boxWidth: number,
|
||||||
faces_boxX: number,
|
faces_boxLeft: number,
|
||||||
faces_boxY: number,
|
faces_boxTop: number,
|
||||||
person_id: number,
|
person_id: number,
|
||||||
person_name: string
|
person_name: string
|
||||||
}): FaceRegion {
|
}): FaceRegion {
|
||||||
return {
|
return {
|
||||||
box: {width: raw.faces_boxWidth, height: raw.faces_boxHeight, x: raw.faces_boxX, y: raw.faces_boxY},
|
box: {width: raw.faces_boxWidth, height: raw.faces_boxHeight, left: raw.faces_boxLeft, top: raw.faces_boxTop},
|
||||||
name: raw.person_name
|
name: raw.person_name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -211,12 +211,12 @@ export class MetadataLoader {
|
|||||||
const box = {
|
const box = {
|
||||||
width: Math.round(regionBox['stArea:w'] * metadata.size.width),
|
width: Math.round(regionBox['stArea:w'] * metadata.size.width),
|
||||||
height: Math.round(regionBox['stArea:h'] * metadata.size.height),
|
height: Math.round(regionBox['stArea:h'] * metadata.size.height),
|
||||||
x: Math.round(regionBox['stArea:x'] * metadata.size.width),
|
left: Math.round(regionBox['stArea:x'] * metadata.size.width),
|
||||||
y: Math.round(regionBox['stArea:y'] * metadata.size.height)
|
top: Math.round(regionBox['stArea:y'] * metadata.size.height)
|
||||||
};
|
};
|
||||||
// convert center base box to corner based box
|
// convert center base box to corner based box
|
||||||
box.x = Math.max(0, box.x - box.width / 2);
|
box.left = Math.max(0, box.left - box.width / 2);
|
||||||
box.y = Math.max(0, box.y - box.height / 2);
|
box.top = Math.max(0, box.top - box.height / 2);
|
||||||
faces.push({name: name, box: box});
|
faces.push({name: name, box: box});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export class PersonRouter {
|
|||||||
public static route(app: Express) {
|
public static route(app: Express) {
|
||||||
|
|
||||||
this.updatePerson(app);
|
this.updatePerson(app);
|
||||||
this.addPersons(app);
|
this.addGetPersons(app);
|
||||||
this.getPersonThumbnail(app);
|
this.getPersonThumbnail(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ export class PersonRouter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static addPersons(app: Express) {
|
private static addGetPersons(app: Express) {
|
||||||
app.get(['/api/person'],
|
app.get(['/api/person'],
|
||||||
// common part
|
// common part
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
|
|||||||
@ -14,8 +14,8 @@ export interface PhotoDTO extends MediaDTO {
|
|||||||
export interface FaceRegionBox {
|
export interface FaceRegionBox {
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
x: number;
|
left: number;
|
||||||
y: number;
|
top: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FaceRegion {
|
export interface FaceRegion {
|
||||||
|
|||||||
@ -55,7 +55,6 @@ export class FaceComponent implements OnInit, OnDestroy {
|
|||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
await this.faceService.setFavourite(this.person, !this.person.isFavourite).catch(console.error);
|
await this.faceService.setFavourite(this.person, !this.person.isFavourite).catch(console.error);
|
||||||
this.faceService.getPersons();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,9 @@ export class GridMedia extends Media {
|
|||||||
get Video(): VideoDTO {
|
get Video(): VideoDTO {
|
||||||
return <VideoDTO>this.media;
|
return <VideoDTO>this.media;
|
||||||
}
|
}
|
||||||
|
get Photo(): PhotoDTO {
|
||||||
|
return <PhotoDTO>this.media;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -194,8 +194,8 @@ export class TestHelper {
|
|||||||
const f: FaceRegion = {
|
const f: FaceRegion = {
|
||||||
name: rndStr() + '.jpg',
|
name: rndStr() + '.jpg',
|
||||||
box: {
|
box: {
|
||||||
x: rndInt(),
|
left: rndInt(),
|
||||||
y: rndInt(),
|
top: rndInt(),
|
||||||
width: rndInt(),
|
width: rndInt(),
|
||||||
height: rndInt()
|
height: rndInt()
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user