From b6ca7be1853b332333672f66a023fae7f903c9d6 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sun, 4 Oct 2026 08:11:24 -0400 Subject: [PATCH] Show each denoise method in the manual as a close-up The manual's AI denoise section names the four methods and their measured times, and shows the lamp and railing of the ISO 8000 frame at 1:1 by each in place of the film and the before/after pair. The scene clicks each method and waits for that network's result: the repair now logs its own "learned denoise:" line first, so the wait matches the result's. --- docs/manual/README.md | 36 ++++++++--- docs/manual/index.html | 36 ++++++++--- docs/manual/media/develop-denoise-after.png | 3 - docs/manual/media/develop-denoise-before.png | 3 - docs/manual/media/develop-denoise-best.png | 3 + .../manual/media/develop-denoise-bilinear.png | 3 + docs/manual/media/develop-denoise-fast.png | 3 + docs/manual/media/develop-denoise-medium.png | 3 + docs/manual/media/develop-denoise.gif | 3 - tools/manual/scenes.py | 61 +++++++++++-------- 10 files changed, 99 insertions(+), 55 deletions(-) delete mode 100644 docs/manual/media/develop-denoise-after.png delete mode 100644 docs/manual/media/develop-denoise-before.png create mode 100644 docs/manual/media/develop-denoise-best.png create mode 100644 docs/manual/media/develop-denoise-bilinear.png create mode 100644 docs/manual/media/develop-denoise-fast.png create mode 100644 docs/manual/media/develop-denoise-medium.png delete mode 100644 docs/manual/media/develop-denoise.gif diff --git a/docs/manual/README.md b/docs/manual/README.md index 3c12da2..f406b87 100644 --- a/docs/manual/README.md +++ b/docs/manual/README.md @@ -210,23 +210,39 @@ the sensor recorded. How every raw is developed. `AI Denoise`, at the top of the Adjust panel, replaces how the camera's raw data is turned into colour: a network trained on this library's own photographs removes the noise and the blotches of -colour that come with it, while keeping the fine detail. It is on for every -raw unless you switch it off with `Apply`. Look at it at 1:1, where noise -lives. +colour that come with it, while keeping the fine detail. Look at it at +1:1, where noise lives. + +`Method` chooses how: + +- `Best`, the default: two networks, one for smooth areas and one for + edges, blended where each is better. The cleanest skies and the sharpest + lettering, and the slowest. +- `Medium`: one network taught by `Best`. Nearly as clean in smooth areas, + a little softer on hard edges, in about a third of the time. +- `Fast`: a smaller one, taught the same way. Visibly noisier at very high + ISO than the other two, but still far cleaner than none, and quick. +- `Bilinear`: the camera's ordinary conversion, noise and all. The photograph shows the camera's ordinary conversion while the network works, with its progress in the bar at the top, and changes when it is -done — a few seconds on a computer with a graphics card, about -fifteen on its processor alone, longer on the tablet. The result is kept, -so a photograph opened again, or exported, does not wait a second time. +done — on a laptop's graphics card, about two and a half seconds for a +20-megapixel photograph with `Best` and under one with the other two; +longer on a processor alone or on the tablet. The first photograph after +installing waits a few minutes more while the graphics card prepares each +network, once. The result is kept, so a photograph opened again, +or exported, does not wait a second time, and switching back to a method +already used is quick. `Strength` eases it off: below 100 % it puts back some of what was removed, as grain without colour, for a picture that does not look too smooth. -![An ISO 8000 night frame at 1:1, AI Denoise switched on, then some grain kept](media/develop-denoise.gif) +The lamp and railing of a night frame at ISO 8000, at 1:1, by each method: -| Before | After | +| Bilinear | Fast | |---|---| -| ![The railing and the lamp at ISO 8000, as the camera recorded them](media/develop-denoise-before.png) | ![The same, with AI Denoise](media/develop-denoise-after.png) | +| ![The railing and the lamp at ISO 8000, as the camera recorded them](media/develop-denoise-bilinear.png) | ![The same, with the Fast network](media/develop-denoise-fast.png) | +| **Medium** | **Best** | +| ![The same, with the Medium network](media/develop-denoise-medium.png) | ![The same, with the Best network](media/develop-denoise-best.png) | It works on raw files from any camera with the usual colour pattern of red, green and blue squares — not on JPEGs, and not yet on Fujifilm's @@ -234,7 +250,7 @@ X-Trans. How noisy the camera is at each ISO was measured for the Canon EOS 6D; for other cameras it is read from a DNG's own figures or estimated from the photograph, and the finished job in the activity list says which. An export uses -it whenever the photograph has it switched on. +the method the photograph has. ### Moving between photographs diff --git a/docs/manual/index.html b/docs/manual/index.html index 4b7d5f1..2aeec12 100644 --- a/docs/manual/index.html +++ b/docs/manual/index.html @@ -292,19 +292,35 @@ the sensor recorded.

How every raw is developed. AI Denoise, at the top of the Adjust panel, replaces how the camera's raw data is turned into colour: a network trained on this library's own photographs removes the noise and the blotches of -colour that come with it, while keeping the fine detail. It is on for every -raw unless you switch it off with Apply. Look at it at 1:1, where noise -lives.

+colour that come with it, while keeping the fine detail. Look at it at +1:1, where noise lives.

+

Method chooses how:

+

The photograph shows the camera's ordinary conversion while the network works, with its progress in the bar at the top, and changes when it is -done — a few seconds on a computer with a graphics card, about -fifteen on its processor alone, longer on the tablet. The result is kept, -so a photograph opened again, or exported, does not wait a second time. +done — on a laptop's graphics card, about two and a half seconds for a +20-megapixel photograph with Best and under one with the other two; +longer on a processor alone or on the tablet. The first photograph after +installing waits a few minutes more while the graphics card prepares each +network, once. The result is kept, so a photograph opened again, +or exported, does not wait a second time, and switching back to a method +already used is quick. Strength eases it off: below 100 % it puts back some of what was removed, as grain without colour, for a picture that does not look too smooth.

-
An ISO 8000 night frame at 1:1, AI Denoise switched on, then some grain kept
An ISO 8000 night frame at 1:1, AI Denoise switched on, then some grain kept
- - +

The lamp and railing of a night frame at ISO 8000, at 1:1, by each method:

+
BeforeAfter
The railing and the lamp at ISO 8000, as the camera recorded themThe same, with AI Denoise
+ + +
BilinearFast
The railing and the lamp at ISO 8000, as the camera recorded themThe same, with the Fast network
MediumBest
The same, with the Medium networkThe same, with the Best network

It works on raw files from any camera with the usual colour pattern of red, green and blue squares — not on JPEGs, and not yet on Fujifilm's @@ -312,7 +328,7 @@ X-Trans. How noisy the camera is at each ISO was measured for the Canon EOS 6D; for other cameras it is read from a DNG's own figures or estimated from the photograph, and the finished job in the activity list says which. An export uses -it whenever the photograph has it switched on.

+the method the photograph has.

Moving between photographs

The roll along the foot of the canvas holds the photographs the grid was showing; click one to open it. The right arrow, D or space opens the next, diff --git a/docs/manual/media/develop-denoise-after.png b/docs/manual/media/develop-denoise-after.png deleted file mode 100644 index 68f5751..0000000 --- a/docs/manual/media/develop-denoise-after.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d68ed4c943ff7848f4010f1ac64d5ff25e0dbdc6afd7de0780e4d44c31a3217a -size 1018071 diff --git a/docs/manual/media/develop-denoise-before.png b/docs/manual/media/develop-denoise-before.png deleted file mode 100644 index 44f0784..0000000 --- a/docs/manual/media/develop-denoise-before.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30be3acd23e36208bd536096b964560f822fae39f80ce5125fd179000e8d1da4 -size 2394740 diff --git a/docs/manual/media/develop-denoise-best.png b/docs/manual/media/develop-denoise-best.png new file mode 100644 index 0000000..f014d50 --- /dev/null +++ b/docs/manual/media/develop-denoise-best.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7b833d2b3ae0d1cdea29cb8a1a9286e365ff892809db25d34543fce40ce1d37 +size 245983 diff --git a/docs/manual/media/develop-denoise-bilinear.png b/docs/manual/media/develop-denoise-bilinear.png new file mode 100644 index 0000000..22cd96f --- /dev/null +++ b/docs/manual/media/develop-denoise-bilinear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3eb87a8ed459a5fc26935a3db6966f31788412b59df8820c4e589ca5745aba6d +size 616810 diff --git a/docs/manual/media/develop-denoise-fast.png b/docs/manual/media/develop-denoise-fast.png new file mode 100644 index 0000000..74f7476 --- /dev/null +++ b/docs/manual/media/develop-denoise-fast.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65bb6527341429289f984bed5013e0140024eab71458931c11e278611c79c6f5 +size 282951 diff --git a/docs/manual/media/develop-denoise-medium.png b/docs/manual/media/develop-denoise-medium.png new file mode 100644 index 0000000..bae7a69 --- /dev/null +++ b/docs/manual/media/develop-denoise-medium.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1dc3a44ddfb440704d749e96495908fc7834c940e18067efdbbf8123a3f96c77 +size 251267 diff --git a/docs/manual/media/develop-denoise.gif b/docs/manual/media/develop-denoise.gif deleted file mode 100644 index b650b53..0000000 --- a/docs/manual/media/develop-denoise.gif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f2fecb1a22fdba6745ed0e208ae69528fc9999316acffe5ac780fc580e26faf -size 1186287 diff --git a/tools/manual/scenes.py b/tools/manual/scenes.py index c0403a9..5fdf58f 100755 --- a/tools/manual/scenes.py +++ b/tools/manual/scenes.py @@ -842,13 +842,21 @@ def develop_zoom(): pause(1.2) -@scene(media=['develop-denoise.gif', 'develop-denoise-before.png', 'develop-denoise-after.png'], +# The methods in the order the scene visits them: `Best` is what the +# photograph opens with, then each smaller network, then none. +DENOISE_METHODS = ['Best', 'Medium', 'Fast', 'Bilinear'] +DENOISE_CLOSE_UP = 560 # pixels of canvas, square, around the lamp at 1:1 + + +@scene(media=[f'develop-denoise-{m.lower()}.png' for m in DENOISE_METHODS], sources=DEVELOP_SRC + ['ui/dr-ui/src/develop/denoise.rs', 'core/dr-denoise/**', - 'core/dr-gpu/src/grain.rs', 'models/denoise/**']) + 'core/dr-pipeline/src/learned_denoise.rs', 'models/denoise/**']) def develop_denoise(): - """A night frame at ISO 8000 at 1:1, AI Denoise switched on and landed, - then some grain kept. Waits for the network rather than for a fixed - time: on the CPU it takes several times what it does on a GPU.""" + """The lit lamp and railing of an ISO 8000 night frame at 1:1, once per + AI Denoise method, each cut to the same square of the canvas. Waits for + each network rather than for a fixed time: on the CPU, which the demo + profile uses, Best takes several times what Fast does.""" + mark = log_size() at_develop(DENOISE) a = dr.photo(0.45, 0.55) # the lit lamp, the railing and the skyline over the water dr.move(*a) @@ -857,32 +865,31 @@ def develop_denoise(): pause(1.5) group('Detail') in_column('AI Denoise@Text') - shot('develop-denoise-before') - rec('develop-denoise') - pause(0.8) - mark = log_size() - dr.click(*denoise_switch()) - t0 = time.time() - while time.time() - t0 < 300 and not denoise_landed(mark): - pause(0.5) - pause(1.5) - shot('develop-denoise-after') - slide('Keep grain', 60) - pause(2.0) - cut() + for method in DENOISE_METHODS: + if method != 'Best': + mark = log_size() + dr.click(*in_column(f'{method}@RadioButton')) + if method != 'Bilinear': + t0 = time.time() + while time.time() - t0 < 600 and not denoise_landed(mark): + pause(0.5) + pause(1.5) + close_up(f'develop-denoise-{method.lower()}', a) undo_all() dr.move(*a) dr.x('click', '--repeat', 2, '--delay', 80, 1) pause(1.2) -def denoise_switch(): - """The `Apply` box under the AI Denoise heading — the lens profile's - switch is also called Apply, so it is found by where it sits.""" - head = dr.matches('AI Denoise@Text', within=column())[0] - below = [e for e in dr.matches('Apply@CheckBox', within=column()) if e['y'] > head['y']] - e = min(below, key=lambda e: e['y']) - return int(e['x'] + e['w'] / 2), int(e['y'] + e['h'] / 2) +def close_up(name, p, size=DENOISE_CLOSE_UP): + """A square of the canvas centred on `p`, kept inside the canvas.""" + shot(name) + x0, y0, x1, y1 = dr.rect('id:canvas-image') + half = size // 2 + cx = min(max(p[0], x0 + half), x1 - half) + cy = min(max(p[1], y0 + half), y1 - half) + subprocess.run(['mogrify', '-crop', f'{size}x{size}+{cx - half}+{cy - half}', '+repage', + f'{OUT}/{name}.png'], check=True) def log_size(): @@ -899,7 +906,9 @@ def denoise_landed(since): try: with open(f'{dr.HOME}/app.log', 'rb') as f: f.seek(since) - return b'learned denoise:' in f.read() + # The result's line, "learned denoise: W×H on …", not the + # repair's, which comes first. + return re.search(rb'learned denoise: \d+\xc3\x97', f.read()) is not None except OSError: return False