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.
This commit is contained in:
2026-10-04 08:11:24 -04:00
parent 06422a07db
commit b6ca7be185
10 changed files with 99 additions and 55 deletions
+26 -10
View File
@@ -210,23 +210,39 @@ the sensor recorded.
How every raw is developed. `AI Denoise`, at the top of the Adjust panel, 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 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 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 colour that come with it, while keeping the fine detail. Look at it at
raw unless you switch it off with `Apply`. Look at it at 1:1, where noise 1:1, where noise lives.
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 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 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 done — on a laptop's graphics card, about two and a half seconds for a
fifteen on its processor alone, longer on the tablet. The result is kept, 20-megapixel photograph with `Best` and under one with the other two;
so a photograph opened again, or exported, does not wait a second time. 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, `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. 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 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 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 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 estimated from the photograph, and the finished job in the activity list
says which. An export uses says which. An export uses
it whenever the photograph has it switched on. the method the photograph has.
### Moving between photographs ### Moving between photographs
+26 -10
View File
@@ -292,19 +292,35 @@ the sensor recorded.</p>
<p>How every raw is developed. <code>AI Denoise</code>, at the top of the Adjust panel, <p>How every raw is developed. <code>AI Denoise</code>, at the top of the Adjust panel,
replaces how the camera's raw data is turned into colour: a network trained 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 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 colour that come with it, while keeping the fine detail. Look at it at
raw unless you switch it off with <code>Apply</code>. Look at it at 1:1, where noise 1:1, where noise lives.</p>
lives.</p> <p><code>Method</code> chooses how:</p>
<ul>
<li><code>Best</code>, 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.</li>
<li><code>Medium</code>: one network taught by <code>Best</code>. Nearly as clean in smooth areas,
a little softer on hard edges, in about a third of the time.</li>
<li><code>Fast</code>: 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.</li>
<li><code>Bilinear</code>: the camera's ordinary conversion, noise and all.</li>
</ul>
<p>The photograph shows the camera's ordinary conversion while the network <p>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 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 done — on a laptop's graphics card, about two and a half seconds for a
fifteen on its processor alone, longer on the tablet. The result is kept, 20-megapixel photograph with <code>Best</code> and under one with the other two;
so a photograph opened again, or exported, does not wait a second time. 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.
<code>Strength</code> eases it off: below 100 % it puts back some of what was removed, <code>Strength</code> 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.</p> as grain without colour, for a picture that does not look too smooth.</p>
<figure><img loading="lazy" src="media/develop-denoise.gif" alt="An ISO 8000 night frame at 1:1, AI Denoise switched on, then some grain kept"><figcaption>An ISO 8000 night frame at 1:1, AI Denoise switched on, then some grain kept</figcaption></figure> <p>The lamp and railing of a night frame at ISO 8000, at 1:1, by each method:</p>
<table><thead><tr><th>Before</th><th>After</th></tr></thead><tbody> <table><thead><tr><th>Bilinear</th><th>Fast</th></tr></thead><tbody>
<tr><td><img src="media/develop-denoise-before.png" alt="The railing and the lamp at ISO 8000, as the camera recorded them" /></td><td><img src="media/develop-denoise-after.png" alt="The same, with AI Denoise" /></td></tr> <tr><td><img src="media/develop-denoise-bilinear.png" alt="The railing and the lamp at ISO 8000, as the camera recorded them" /></td><td><img src="media/develop-denoise-fast.png" alt="The same, with the Fast network" /></td></tr>
<tr><td><strong>Medium</strong></td><td><strong>Best</strong></td></tr>
<tr><td><img src="media/develop-denoise-medium.png" alt="The same, with the Medium network" /></td><td><img src="media/develop-denoise-best.png" alt="The same, with the Best network" /></td></tr>
</tbody></table> </tbody></table>
<p>It works on raw files from any camera with the usual colour pattern of <p>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 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 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 estimated from the photograph, and the finished job in the activity list
says which. An export uses says which. An export uses
it whenever the photograph has it switched on.</p> the method the photograph has.</p>
<h3 id="moving-between-photographs">Moving between photographs</h3> <h3 id="moving-between-photographs">Moving between photographs</h3>
<p>The roll along the foot of the canvas holds the photographs the grid was <p>The roll along the foot of the canvas holds the photographs the grid was
showing; click one to open it. The right arrow, <code>D</code> or space opens the next, showing; click one to open it. The right arrow, <code>D</code> or space opens the next,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+35 -26
View File
@@ -842,13 +842,21 @@ def develop_zoom():
pause(1.2) 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/**', 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(): def develop_denoise():
"""A night frame at ISO 8000 at 1:1, AI Denoise switched on and landed, """The lit lamp and railing of an ISO 8000 night frame at 1:1, once per
then some grain kept. Waits for the network rather than for a fixed AI Denoise method, each cut to the same square of the canvas. Waits for
time: on the CPU it takes several times what it does on a GPU.""" 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) at_develop(DENOISE)
a = dr.photo(0.45, 0.55) # the lit lamp, the railing and the skyline over the water a = dr.photo(0.45, 0.55) # the lit lamp, the railing and the skyline over the water
dr.move(*a) dr.move(*a)
@@ -857,32 +865,31 @@ def develop_denoise():
pause(1.5) pause(1.5)
group('Detail') group('Detail')
in_column('AI Denoise@Text') in_column('AI Denoise@Text')
shot('develop-denoise-before') for method in DENOISE_METHODS:
rec('develop-denoise') if method != 'Best':
pause(0.8) mark = log_size()
mark = log_size() dr.click(*in_column(f'{method}@RadioButton'))
dr.click(*denoise_switch()) if method != 'Bilinear':
t0 = time.time() t0 = time.time()
while time.time() - t0 < 300 and not denoise_landed(mark): while time.time() - t0 < 600 and not denoise_landed(mark):
pause(0.5) pause(0.5)
pause(1.5) pause(1.5)
shot('develop-denoise-after') close_up(f'develop-denoise-{method.lower()}', a)
slide('Keep grain', 60)
pause(2.0)
cut()
undo_all() undo_all()
dr.move(*a) dr.move(*a)
dr.x('click', '--repeat', 2, '--delay', 80, 1) dr.x('click', '--repeat', 2, '--delay', 80, 1)
pause(1.2) pause(1.2)
def denoise_switch(): def close_up(name, p, size=DENOISE_CLOSE_UP):
"""The `Apply` box under the AI Denoise heading — the lens profile's """A square of the canvas centred on `p`, kept inside the canvas."""
switch is also called Apply, so it is found by where it sits.""" shot(name)
head = dr.matches('AI Denoise@Text', within=column())[0] x0, y0, x1, y1 = dr.rect('id:canvas-image')
below = [e for e in dr.matches('Apply@CheckBox', within=column()) if e['y'] > head['y']] half = size // 2
e = min(below, key=lambda e: e['y']) cx = min(max(p[0], x0 + half), x1 - half)
return int(e['x'] + e['w'] / 2), int(e['y'] + e['h'] / 2) 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(): def log_size():
@@ -899,7 +906,9 @@ def denoise_landed(since):
try: try:
with open(f'{dr.HOME}/app.log', 'rb') as f: with open(f'{dr.HOME}/app.log', 'rb') as f:
f.seek(since) 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: except OSError:
return False return False