feat(noise-removal): SOTA noise removal with 4 quality tiers (#57)

* feat(noise-removal): register tool in shared constants and i18n

* feat(noise-removal): add SCUNet and NAFNet model architectures

* feat(noise-removal): add Python denoising engine with 4 quality tiers

* feat(noise-removal): add TypeScript bridge for Python sidecar

* feat(noise-removal): add frontend settings with 4-tier selector

* feat(noise-removal): register in tool registry and pipeline

* feat(noise-removal): add Fastify API route with Zod validation

* feat(noise-removal): add SCUNet and NAFNet model downloads to Docker build

* test(noise-removal): add to e2e tool page rendering tests

* test(noise-removal): add integration tests for API endpoint

* style: fix biome formatting and import ordering

* fix(noise-removal): use correct model download URLs

NAFNet model is hosted on HuggingFace, not GitHub releases.
Also align SCUNet URL to use the KAIR releases (same as Docker build).

* fix(noise-removal): remove emojis from tier selector, simplify labels

Drop emoji icons from Quick/Balanced/Quality/Maximum buttons. Replace
technical algorithm names with plain descriptions users can understand.

---------

Co-authored-by: stirling-image <stirling-image@users.noreply.github.com>
This commit is contained in:
stirling-image
2026-04-13 19:50:23 +08:00
committed by GitHub
co-authored by stirling-image
parent 61794dca2d
commit dfffc0a8cc
16 changed files with 1804 additions and 0 deletions
@@ -5,6 +5,7 @@ import { CompressControls } from "./compress-settings";
import { ConvertControls } from "./convert-settings";
import { CropControls } from "./crop-settings";
import { GifToolsControls } from "./gif-tools-settings";
import { NoiseRemovalControls } from "./noise-removal-settings";
import { RemoveBgControls } from "./remove-bg-settings";
import { ReplaceColorControls } from "./replace-color-settings";
import { ResizeControls } from "./resize-settings";
@@ -44,6 +45,8 @@ export function PipelineStepSettings({ toolId, settings, onChange }: PipelineSte
if (toolId === "blur-faces") return <BlurFacesControls settings={settings} onChange={onChange} />;
if (toolId === "remove-background")
return <RemoveBgControls settings={settings} onChange={onChange} />;
if (toolId === "noise-removal")
return <NoiseRemovalControls settings={settings} onChange={onChange} />;
if (COLOR_TOOL_IDS.has(toolId))
return <ColorControls toolId={toolId} settings={settings} onChange={onChange} />;