use original image for ml

This commit is contained in:
mertalev 2025-05-13 23:41:57 -04:00
parent c15507baad
commit 016a760dda
No known key found for this signature in database
GPG Key ID: DF6ABC77AAD98C95
5 changed files with 10 additions and 77 deletions

View File

@ -20,7 +20,7 @@ class FaceDetector(InferenceModel):
def _load(self) -> ModelSession: def _load(self) -> ModelSession:
session = self._make_session(self.model_path) session = self._make_session(self.model_path)
self.model = RetinaFace(session=session) self.model = RetinaFace(session=session)
self.model.prepare(ctx_id=0, det_thresh=self.min_score, input_size=(640, 640)) self.model.prepare(ctx_id=0, det_thresh=self.min_score, input_size=(256, 256))
return session return session

View File

@ -169,8 +169,7 @@ export class AssetJobRepository {
getForClipEncoding(id: string) { getForClipEncoding(id: string) {
return this.db return this.db
.selectFrom('assets') .selectFrom('assets')
.select(['assets.id', 'assets.visibility']) .select(['assets.id', 'assets.visibility', 'assets.originalPath'])
.select((eb) => withFiles(eb, AssetFileType.PREVIEW))
.where('assets.id', '=', id) .where('assets.id', '=', id)
.executeTakeFirst(); .executeTakeFirst();
} }
@ -179,10 +178,9 @@ export class AssetJobRepository {
getForDetectFacesJob(id: string) { getForDetectFacesJob(id: string) {
return this.db return this.db
.selectFrom('assets') .selectFrom('assets')
.select(['assets.id', 'assets.visibility']) .select(['assets.id', 'assets.visibility', 'assets.originalPath'])
.$call(withExifInner) .$call(withExifInner)
.select((eb) => withFaces(eb, true)) .select((eb) => withFaces(eb, true))
.select((eb) => withFiles(eb, AssetFileType.PREVIEW))
.where('assets.id', '=', id) .where('assets.id', '=', id)
.executeTakeFirst(); .executeTakeFirst();
} }

View File

@ -5,9 +5,7 @@ import { Exif } from 'src/database';
import { OnEvent, OnJob } from 'src/decorators'; import { OnEvent, OnJob } from 'src/decorators';
import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto'; import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto';
import { import {
AssetFileType,
AssetPathType, AssetPathType,
AssetType,
AssetVisibility, AssetVisibility,
AudioCodec, AudioCodec,
Colorspace, Colorspace,
@ -24,7 +22,6 @@ import {
VideoCodec, VideoCodec,
VideoContainer, VideoContainer,
} from 'src/enum'; } from 'src/enum';
import { UpsertFileOptions } from 'src/repositories/asset.repository';
import { BoundingBox } from 'src/repositories/machine-learning.repository'; import { BoundingBox } from 'src/repositories/machine-learning.repository';
import { BaseService } from 'src/services/base.service'; import { BaseService } from 'src/services/base.service';
import { import {
@ -163,69 +160,6 @@ export class MediaService extends BaseService {
return JobStatus.SKIPPED; return JobStatus.SKIPPED;
} }
let generated: {
previewPath: string;
thumbnailPath: string;
fullsizePath?: string;
thumbhash: Buffer;
};
if (asset.type === AssetType.VIDEO || asset.originalFileName.toLowerCase().endsWith('.gif')) {
generated = await this.generateVideoThumbnails(asset);
} else if (asset.type === AssetType.IMAGE) {
generated = await this.generateImageThumbnails(asset);
} else {
this.logger.warn(`Skipping thumbnail generation for asset ${id}: ${asset.type} is not an image or video`);
return JobStatus.SKIPPED;
}
const { previewFile, thumbnailFile, fullsizeFile } = getAssetFiles(asset.files);
const toUpsert: UpsertFileOptions[] = [];
if (previewFile?.path !== generated.previewPath) {
toUpsert.push({ assetId: asset.id, path: generated.previewPath, type: AssetFileType.PREVIEW });
}
if (thumbnailFile?.path !== generated.thumbnailPath) {
toUpsert.push({ assetId: asset.id, path: generated.thumbnailPath, type: AssetFileType.THUMBNAIL });
}
if (generated.fullsizePath && fullsizeFile?.path !== generated.fullsizePath) {
toUpsert.push({ assetId: asset.id, path: generated.fullsizePath, type: AssetFileType.FULLSIZE });
}
if (toUpsert.length > 0) {
await this.assetRepository.upsertFiles(toUpsert);
}
const pathsToDelete: string[] = [];
if (previewFile && previewFile.path !== generated.previewPath) {
this.logger.debug(`Deleting old preview for asset ${asset.id}`);
pathsToDelete.push(previewFile.path);
}
if (thumbnailFile && thumbnailFile.path !== generated.thumbnailPath) {
this.logger.debug(`Deleting old thumbnail for asset ${asset.id}`);
pathsToDelete.push(thumbnailFile.path);
}
if (fullsizeFile && fullsizeFile.path !== generated.fullsizePath) {
this.logger.debug(`Deleting old fullsize preview image for asset ${asset.id}`);
pathsToDelete.push(fullsizeFile.path);
if (!generated.fullsizePath) {
// did not generate a new fullsize image, delete the existing record
await this.assetRepository.deleteFiles([fullsizeFile]);
}
}
if (pathsToDelete.length > 0) {
await Promise.all(pathsToDelete.map((path) => this.storageRepository.unlink(path)));
}
if (!asset.thumbhash || Buffer.compare(asset.thumbhash, generated.thumbhash) !== 0) {
await this.assetRepository.update({ id: asset.id, thumbhash: generated.thumbhash });
}
await this.assetRepository.upsertJobStatus({ assetId: asset.id, previewAt: new Date(), thumbnailAt: new Date() });
return JobStatus.SUCCESS; return JobStatus.SUCCESS;
} }

View File

@ -290,8 +290,7 @@ export class PersonService extends BaseService {
} }
const asset = await this.assetJobRepository.getForDetectFacesJob(id); const asset = await this.assetJobRepository.getForDetectFacesJob(id);
const previewFile = asset?.files[0]; if (!asset) {
if (!asset || asset.files.length !== 1 || !previewFile) {
return JobStatus.FAILED; return JobStatus.FAILED;
} }
@ -301,10 +300,12 @@ export class PersonService extends BaseService {
const { imageHeight, imageWidth, faces } = await this.machineLearningRepository.detectFaces( const { imageHeight, imageWidth, faces } = await this.machineLearningRepository.detectFaces(
machineLearning.urls, machineLearning.urls,
previewFile.path, asset.originalPath,
machineLearning.facialRecognition, machineLearning.facialRecognition,
); );
this.logger.debug(`${faces.length} faces detected in ${previewFile.path}`); this.logger.debug(
`${faces.length} faces detected in ${asset.originalPath} with scores ${faces.map((f) => f.score)}`,
);
const facesToAdd: (Insertable<AssetFaces> & { id: string })[] = []; const facesToAdd: (Insertable<AssetFaces> & { id: string })[] = [];
const embeddings: FaceSearch[] = []; const embeddings: FaceSearch[] = [];

View File

@ -100,7 +100,7 @@ export class SmartInfoService extends BaseService {
} }
const asset = await this.assetJobRepository.getForClipEncoding(id); const asset = await this.assetJobRepository.getForClipEncoding(id);
if (!asset || asset.files.length !== 1) { if (!asset) {
return JobStatus.FAILED; return JobStatus.FAILED;
} }
@ -110,7 +110,7 @@ export class SmartInfoService extends BaseService {
const embedding = await this.machineLearningRepository.encodeImage( const embedding = await this.machineLearningRepository.encodeImage(
machineLearning.urls, machineLearning.urls,
asset.files[0].path, asset.originalPath,
machineLearning.clip, machineLearning.clip,
); );