fix: improve AI tool reliability for face detection and background removal (#25)

- Replace OpenCV Haar Cascades with MediaPipe for face detection, using
  short-range model first with full-range fallback for better accuracy
- Add auto-orient to remove-background route for EXIF-rotated photos
- Change default background removal model from u2net to birefnet-general-lite
- Fix flaky test by setting SQLite busy_timeout before journal_mode pragma

Co-authored-by: Siddharth Kumar Sah <siddharth123sk@gmail.com>
This commit is contained in:
stirling-image
2026-04-06 22:00:48 +08:00
committed by GitHub
co-authored by Siddharth Kumar Sah
parent 3c4562c9ce
commit 2eb77fe0f2
6 changed files with 45 additions and 30 deletions
+4 -2
View File
@@ -10,9 +10,11 @@ mkdirSync(dirname(env.DB_PATH), { recursive: true });
const sqlite: DatabaseType = new Database(env.DB_PATH);
// Critical SQLite pragmas for reliability
sqlite.pragma("journal_mode = WAL");
// Critical SQLite pragmas for reliability.
// busy_timeout must be set first so journal_mode = WAL can retry
// if another connection holds the lock (e.g. parallel test files).
sqlite.pragma("busy_timeout = 5000");
sqlite.pragma("journal_mode = WAL");
sqlite.pragma("synchronous = NORMAL");
sqlite.pragma("foreign_keys = ON");
+1 -4
View File
@@ -10,10 +10,7 @@ import { createWorkspace } from "../../lib/workspace.js";
import { updateSingleFileProgress } from "../progress.js";
import { registerToolProcessFn } from "../tool-factory.js";
/**
* Face detection and blurring route.
* Uses MediaPipe for detection, PIL for blurring.
*/
/** Face detection and blurring route. */
export function registerBlurFaces(app: FastifyInstance) {
app.post("/api/v1/tools/blur-faces", async (request: FastifyRequest, reply: FastifyReply) => {
let fileBuffer: Buffer | null = null;
@@ -4,6 +4,7 @@ import { basename, join } from "node:path";
import { removeBackground } from "@stirling-image/ai";
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import { z } from "zod";
import { autoOrient } from "../../lib/auto-orient.js";
import { validateImageBuffer } from "../../lib/file-validation.js";
import { createWorkspace } from "../../lib/workspace.js";
import { updateSingleFileProgress } from "../progress.js";
@@ -56,6 +57,10 @@ export function registerRemoveBackground(app: FastifyInstance) {
try {
const settings = settingsRaw ? JSON.parse(settingsRaw) : {};
// Auto-orient to fix EXIF rotation before processing
fileBuffer = await autoOrient(fileBuffer);
request.log.info(
{ toolId: "remove-background", imageSize: fileBuffer.length, model: settings.model },
"Starting background removal",
@@ -126,9 +131,10 @@ export function registerRemoveBackground(app: FastifyInstance) {
}),
process: async (inputBuffer, settings, filename) => {
const s = settings as { model?: string; backgroundColor?: string };
const orientedBuffer = await autoOrient(inputBuffer);
const jobId = randomUUID();
const workspacePath = await createWorkspace(jobId);
const resultBuffer = await removeBackground(inputBuffer, join(workspacePath, "output"), {
const resultBuffer = await removeBackground(orientedBuffer, join(workspacePath, "output"), {
model: s.model,
backgroundColor: s.backgroundColor,
});