Offer three denoise networks and a method to choose between them
AI Denoise's Apply switch becomes Method: Bilinear, Fast, Medium, Best, default Best, so an untouched raw writes nothing and develops through the mixture. `apply` is still read and never written: 0 is Bilinear, 1 keeps a network already chosen. - Best is the mixture of a flat and an edge expert with a learned gate; Medium and Fast are students distilled from it. 2.48 s, 0.79 s and 0.57 s for a 20 MP frame on TensorRT fp16. - Each network carries its own tile border (256 for the mixture, 192 for the students) through `dr_denoise::Shipped` and `TileNet::halo`. - The file is hashed once at open and each network keys its own cached result; Bilinear keeps the result in memory for the way back. - Each has an .a16w16 sibling for the Hexagon: 0.00 dB on the 6D gate, at most 0.11 dB with the noise scaled x0.5 to x4. - APK BUNDLED 19 -> 23; the PKGBUILD installs all three.
This commit is contained in:
@@ -47,17 +47,29 @@ pub fn dir() -> PathBuf {
|
||||
.unwrap_or_else(|| PathBuf::from("denoise-cache"))
|
||||
}
|
||||
|
||||
/// The key for a file's bytes under a model.
|
||||
pub fn key(bytes: &[u8], model: &Path) -> String {
|
||||
let mut h = Sha256::new();
|
||||
h.update(bytes);
|
||||
if let Some(name) = model.file_name() {
|
||||
h.update(name.to_string_lossy().as_bytes());
|
||||
/// A file's bytes, hashed once at open: each method's network keys its
|
||||
/// result from this, so changing the method does not read the file again.
|
||||
#[derive(Clone)]
|
||||
pub struct FileHash(Sha256);
|
||||
|
||||
impl FileHash {
|
||||
pub fn of(bytes: &[u8]) -> Self {
|
||||
let mut h = Sha256::new();
|
||||
h.update(bytes);
|
||||
FileHash(h)
|
||||
}
|
||||
|
||||
/// The key for these bytes under a model.
|
||||
pub fn key(&self, model: &Path) -> String {
|
||||
let mut h = self.0.clone();
|
||||
if let Some(name) = model.file_name() {
|
||||
h.update(name.to_string_lossy().as_bytes());
|
||||
}
|
||||
let size = std::fs::metadata(model).map(|m| m.len()).unwrap_or(0);
|
||||
h.update(size.to_le_bytes());
|
||||
let digest = h.finalize();
|
||||
digest.iter().map(|b| format!("{b:02x}")).collect()
|
||||
}
|
||||
let size = std::fs::metadata(model).map(|m| m.len()).unwrap_or(0);
|
||||
h.update(size.to_le_bytes());
|
||||
let digest = h.finalize();
|
||||
digest.iter().map(|b| format!("{b:02x}")).collect()
|
||||
}
|
||||
|
||||
fn path_in(dir: &Path, key: &str) -> PathBuf {
|
||||
@@ -204,11 +216,11 @@ mod tests {
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let model = dir.join("m.onnx");
|
||||
std::fs::write(&model, b"weights").unwrap();
|
||||
let a = key(b"photo", &model);
|
||||
assert_eq!(a, key(b"photo", &model));
|
||||
assert_ne!(a, key(b"photo2", &model));
|
||||
let a = FileHash::of(b"photo").key(&model);
|
||||
assert_eq!(a, FileHash::of(b"photo").key(&model));
|
||||
assert_ne!(a, FileHash::of(b"photo2").key(&model));
|
||||
std::fs::write(&model, b"other weights").unwrap();
|
||||
assert_ne!(a, key(b"photo", &model));
|
||||
assert_ne!(a, FileHash::of(b"photo").key(&model));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user