Para «Rellenar con IA» de Eliminar en Labstream OS: la página manda el trozo de la foto
alrededor de lo pintado, en 8 bits con el hueco en el alfa, y la app lo devuelve con el
hueco relleno por LaMa y lo demás byte a byte como estaba (src-tauri/src/ia/relleno.rs).
- Comando nuevo ia_rellenar (permitido solo para el origen de la app). ia_estado e
ia_preparar llevan { que: "relleno" }; sin él siguen hablando del sujeto, como la 1.22,
y el estado dice ahora de qué IA habla (así la página sabe que esta app rellena).
- LaMa (Apache-2.0) en la exportación ONNX de tamaño libre de g-ronimo, desde el servidor
de la app con la sesión de la pestaña y fijada por huella (≈210 MB). Se rellena al
tamaño del trozo en múltiplos de 32, con 1024 px de lado como mucho.
- En la CPU: las dos exportaciones de LaMa probadas fallan con DirectML en una RTX 5080
(su FFT, sea el operador DFT o productos de matrices: 80070057, también con las formas
fijadas y sin optimizar); en la CPU, ~3 s a 512 px y ~10 s a 1024, y no le quita
memoria a la tarjeta.
- Las piezas por IA: el motor (ONNX Runtime + DirectML) es de las dos; cada modelo se baja
cuando se usa la suya. Cada modelo abierto se suelta a los 2 min sin uso.
Pruebas nuevas: el tamaño al que se rellena y que fuera del hueco no cambia nada; y una de
punta a punta en este equipo (ignorada en CI).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102 líneas
4.4 KiB
Rust
102 líneas
4.4 KiB
Rust
// ── Lo que la IA baja la primera vez, de dónde, y con qué huella ──
|
||
// El motor (≈215 MB) es de las dos IA; cada modelo se baja solo cuando se usa la suya: el del sujeto
|
||
// (≈490 MB) o el de rellenar (≈210 MB).
|
||
//
|
||
// Fijado por versión y huella SHA-256 (comprobadas al bajarlo el 14-oct-2026): si algún día cambia
|
||
// lo que hay en esa dirección, no se usa.
|
||
//
|
||
// - El modelo: BiRefNet general (MIT, ZhengPeng7; el mismo del navegador) en media precisión, del
|
||
// servidor de la app (api/modelos/sujeto-equipo, con la sesión de la pestaña). Sale de la
|
||
// exportación ONNX oficial del autor (release v1 de su GitHub, float32) pasada a float16 con la
|
||
// entrada y la salida en float32 (scripts/modelo-sujeto-equipo.py de labstream-os). Entrada
|
||
// `input_image` [1, 3, 1024, 1024], salida `output_image` [1, 1, 1024, 1024] (logits). En una RTX
|
||
// 5080: 0,3 s por foto y el mismo borde que el original en la CPU.
|
||
// El HR (2048 px, matting) se probó y NO va: su convolución deformable, deshecha en GatherND en la
|
||
// exportación oficial, ocupa 14–15 GB con DirectML y tarda de 6 a 45 s (14-oct-2026).
|
||
// - Rellenar (1.23): LaMa (Apache-2.0, advimman/big-lama), la exportación ONNX de tamaño libre de
|
||
// g-ronimo (Hugging Face g-ronimo/lama, `lama.onnx`, la que usa wipe.photos), copiada al servidor de
|
||
// la app (api/modelos/relleno-equipo). Entrada `input` [1, 4, alto, ancho] (múltiplos de 32),
|
||
// salida `output` [1, 3, alto, ancho], 0..1. Corre en la CPU (ver motor.rs: abrir_en_cpu).
|
||
// - ONNX Runtime 1.24.4 con DirectML (NuGet de Microsoft): onnxruntime.dll para x64.
|
||
// - DirectML 1.15.4 (NuGet de Microsoft): DirectML.dll para Windows x64 (el paquete trae también
|
||
// las de Xbox y las de depurar: se saca por su ruta exacta).
|
||
|
||
use super::bajar::{Forma, Pieza};
|
||
|
||
pub const NOMBRE_MODELO: &str = "BiRefNet";
|
||
pub const NOMBRE_RELLENO: &str = "LaMa";
|
||
pub const ARCHIVO_RELLENO: &str = "lama-g-ronimo-44bb92b2.onnx";
|
||
/// El lado de la entrada y de la salida del modelo.
|
||
pub const LADO: usize = 1024;
|
||
|
||
pub const ARCHIVO_MODELO: &str = "birefnet-general-epoch_244-fp16.onnx";
|
||
pub const DLL_ORT: &str = "onnxruntime.dll";
|
||
pub const DLL_DIRECTML: &str = "DirectML.dll";
|
||
|
||
/// De qué IA se habla: la máscara de sujeto o rellenar.
|
||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||
pub enum Que {
|
||
Sujeto,
|
||
Relleno,
|
||
}
|
||
|
||
impl Que {
|
||
pub fn de(v: Option<&str>) -> Que {
|
||
if v == Some("relleno") {
|
||
Que::Relleno
|
||
} else {
|
||
Que::Sujeto
|
||
}
|
||
}
|
||
pub fn nombre(self) -> &'static str {
|
||
match self {
|
||
Que::Sujeto => "sujeto",
|
||
Que::Relleno => "relleno",
|
||
}
|
||
}
|
||
}
|
||
|
||
static RELLENO: Pieza = Pieza {
|
||
nombre: "lama-g-ronimo-44bb92b2",
|
||
url: "https://os.labstreamsas.com/api/modelos/relleno-equipo",
|
||
sha256: "44bb92b2693db40bb088dda226365a3aa8080a561584b8b0287ab11a97f9e9e7",
|
||
bytes: 209_181_361,
|
||
forma: Forma::Archivo(ARCHIVO_RELLENO),
|
||
con_sesion: true,
|
||
};
|
||
|
||
static PIEZAS: [Pieza; 3] = [
|
||
Pieza {
|
||
nombre: "onnxruntime-directml-1.24.4",
|
||
url: "https://api.nuget.org/v3-flatcontainer/microsoft.ml.onnxruntime.directml/1.24.4/microsoft.ml.onnxruntime.directml.1.24.4.nupkg",
|
||
sha256: "57e9f11b73437bef7a309496135d4c1f96b1a8e9ddba60013fa27bfc1d788681",
|
||
bytes: 12_458_649,
|
||
forma: Forma::Zip(&["runtimes/win-x64/native/onnxruntime.dll", "runtimes/win-x64/native/onnxruntime_providers_shared.dll"]),
|
||
con_sesion: false,
|
||
},
|
||
Pieza {
|
||
nombre: "directml-1.15.4",
|
||
url: "https://api.nuget.org/v3-flatcontainer/microsoft.ai.directml/1.15.4/microsoft.ai.directml.1.15.4.nupkg",
|
||
sha256: "4e7cb7ddce8cf837a7a75dc029209b520ca0101470fcdf275c1f49736a3615b9",
|
||
bytes: 202_292_617,
|
||
forma: Forma::Zip(&["bin/x64-win/DirectML.dll"]),
|
||
con_sesion: false,
|
||
},
|
||
Pieza {
|
||
nombre: "birefnet-general-epoch_244-fp16",
|
||
url: "https://os.labstreamsas.com/api/modelos/sujeto-equipo",
|
||
sha256: "323232ec73a04ac4d0ef8c325a75aa8d69ed7062235a7cf9941769fae4c9709f",
|
||
bytes: 489_666_838,
|
||
forma: Forma::Archivo(ARCHIVO_MODELO),
|
||
con_sesion: true,
|
||
},
|
||
];
|
||
|
||
/// Lo que necesita cada IA: el motor (los dos primeros) y su modelo.
|
||
pub fn de(que: Que) -> Vec<&'static Pieza> {
|
||
match que {
|
||
Que::Sujeto => PIEZAS.iter().collect(),
|
||
Que::Relleno => vec![&PIEZAS[0], &PIEZAS[1], &RELLENO],
|
||
}
|
||
}
|