Show AI denoise in the manual on sharp, noisy frames

The ISO 8000 Brooklyn Bridge frame was soft at 1:1 before any denoising,
so it could not show that Best keeps detail. The section now shows five
sharp frames from ISO 4000 to 16000, each at 1:1 where hard edges meet
flat areas, Bilinear beside Best: a subway poster, a cathedral portal, a
circus clock, a clinic sign and graffiti. Fast is described, not shown.

at_develop opens a DNG when the name carries its extension. The scene
now fails when Best never lands instead of capturing the undenoised
frame twice.
This commit is contained in:
2026-10-08 22:22:40 -04:00
parent fc3b1ca440
commit f813014e80
16 changed files with 98 additions and 56 deletions
+11 -6
View File
@@ -236,13 +236,18 @@ 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.
The lamp and railing of a night frame at ISO 8000, at 1:1, by each method: Five sharp photographs at high ISO, each at 1:1 where hard edges meet
flat areas, as the camera's ordinary conversion gives them and as `Best`
develops them. The grain goes from the flat paper, stone, canvas and paint; the
lines, the lettering and the carving keep their edges:
| Bilinear | Fast | | | Bilinear | Best |
|---|---| |---|---|---|
| ![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) | | ISO 4000 | ![A subway poster's masthead at ISO 4000, at 1:1, as the camera recorded it](media/develop-denoise-poster-bilinear.png) | ![The same with Best](media/develop-denoise-poster-best.png) |
| **Best** | | | ISO 8000 | ![The carving round a cathedral door at ISO 8000, at 1:1, as the camera recorded it](media/develop-denoise-portal-bilinear.png) | ![The same with Best](media/develop-denoise-portal-best.png) |
| ![The same, with the Best network](media/develop-denoise-best.png) | | | ISO 12800 | ![A clock's numerals over a circus ring at ISO 12800, at 1:1, as the camera recorded it](media/develop-denoise-clock-bilinear.png) | ![The same with Best](media/develop-denoise-clock-best.png) |
| ISO 16000 | ![Lettering on a white panel at ISO 16000, at 1:1, as the camera recorded it](media/develop-denoise-sign-bilinear.png) | ![The same with Best](media/develop-denoise-sign-best.png) |
| ISO 16000 | ![Graffiti on a white wall at ISO 16000, at 1:1, as the camera recorded it](media/develop-denoise-graffiti-bilinear.png) | ![The same with Best](media/develop-denoise-graffiti-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
+10 -5
View File
@@ -315,11 +315,16 @@ or exported, does not wait a second time, and switching back to a method
already used is quick. 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>
<p>The lamp and railing of a night frame at ISO 8000, at 1:1, by each method:</p> <p>Five sharp photographs at high ISO, each at 1:1 where hard edges meet
<table><thead><tr><th>Bilinear</th><th>Fast</th></tr></thead><tbody> flat areas, as the camera's ordinary conversion gives them and as <code>Best</code>
<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> develops them. The grain goes from the flat paper, stone, canvas and paint; the
<tr><td><strong>Best</strong></td><td></td></tr> lines, the lettering and the carving keep their edges:</p>
<tr><td><img src="media/develop-denoise-best.png" alt="The same, with the Best network" /></td><td></td></tr> <table><thead><tr><th></th><th>Bilinear</th><th>Best</th></tr></thead><tbody>
<tr><td>ISO 4000</td><td><img src="media/develop-denoise-poster-bilinear.png" alt="A subway poster&#39;s masthead at ISO 4000, at 1:1, as the camera recorded it" /></td><td><img src="media/develop-denoise-poster-best.png" alt="The same with Best" /></td></tr>
<tr><td>ISO 8000</td><td><img src="media/develop-denoise-portal-bilinear.png" alt="The carving round a cathedral door at ISO 8000, at 1:1, as the camera recorded it" /></td><td><img src="media/develop-denoise-portal-best.png" alt="The same with Best" /></td></tr>
<tr><td>ISO 12800</td><td><img src="media/develop-denoise-clock-bilinear.png" alt="A clock&#39;s numerals over a circus ring at ISO 12800, at 1:1, as the camera recorded it" /></td><td><img src="media/develop-denoise-clock-best.png" alt="The same with Best" /></td></tr>
<tr><td>ISO 16000</td><td><img src="media/develop-denoise-sign-bilinear.png" alt="Lettering on a white panel at ISO 16000, at 1:1, as the camera recorded it" /></td><td><img src="media/develop-denoise-sign-best.png" alt="The same with Best" /></td></tr>
<tr><td>ISO 16000</td><td><img src="media/develop-denoise-graffiti-bilinear.png" alt="Graffiti on a white wall at ISO 16000, at 1:1, as the camera recorded it" /></td><td><img src="media/develop-denoise-graffiti-best.png" alt="The same with Best" /></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
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+47 -36
View File
@@ -63,7 +63,6 @@ ALPS_SKY = '_MG_8330' # an upright alpine frame, its top third sky and clo
TOWER = '_MG_8693' # towers shot looking up: verticals that converge TOWER = '_MG_8693' # towers shot looking up: verticals that converge
ROAD = '_MG_8672' # a road under a sky, with marks on it: masks and repair ROAD = '_MG_8672' # a road under a sky, with marks on it: masks and repair
ROAD_MARK = (0.305, 0.794) # a dark mark on its tarmac ROAD_MARK = (0.305, 0.794) # a dark mark on its tarmac
DENOISE = '_MG_8862' # Brooklyn Bridge at ISO 8000: a lit railing, a lamp and a camera against the night
# --- the registry ----------------------------------------------------------- # --- the registry -----------------------------------------------------------
SCENES = {} SCENES = {}
@@ -259,14 +258,17 @@ def cell_width():
def at_develop(photo=CHINATOWN): def at_develop(photo=CHINATOWN):
"""`photo` open in develop, on the Photo tool, the All group, the """`photo` open in develop, on the Photo tool, the All group, the
column at its top, and the edit as it was opened.""" column at its top, and the edit as it was opened. A name without an
if dr.present('‹ Library@Button') and dr.present(f'{photo}.CR2'): extension is a CR2."""
stem, ext = os.path.splitext(photo)
name = photo if ext else f'{photo}.CR2'
if dr.present('‹ Library@Button') and dr.present(name):
pass pass
else: else:
at_library() at_library()
grid_top() grid_top()
dr.click(*cell(photo)) dr.click(*cell(stem))
dr.wait_for(f'{photo}.CR2', 30) dr.wait_for(name, 30)
wait_canvas() wait_canvas()
for done in ('Done Composing', 'Done Masking', 'Done Repairing'): for done in ('Done Composing', 'Done Masking', 'Done Repairing'):
if dr.present(f'{done}@Button'): if dr.present(f'{done}@Button'):
@@ -842,43 +844,52 @@ def develop_zoom():
pause(1.2) pause(1.2)
# The methods in the order the scene visits them: `Best` is what the # Sharp, noisy frames, each with a point on it at 1:1 where hard edges meet
# photograph opens with, then each smaller network, then none. # flat areas — where a denoiser either keeps the edge or smears it: a slug
DENOISE_METHODS = ['Best', 'Fast', 'Bilinear'] # for its pictures, the file, and the point as fractions of the photograph.
DENOISE_CLOSE_UP = 560 # pixels of canvas, square, around the lamp at 1:1 DENOISE_FRAMES = [
('poster', '_MG_8953', (0.40, 0.31)), # ISO 4000: a subway poster's masthead, lines on paper
('portal', '_MG_4762', (0.18, 0.22)), # ISO 8000: carving round a cathedral door, smooth stone
('clock', '_MG_4810', (0.47, 0.39)), # ISO 12800: a circus clock's numerals on flat canvas
('sign', 'IMG_2515.dng', (0.66, 0.52)), # ISO 16000: lettering and a swoosh on a white panel
('graffiti', 'IMG_2041.dng', (0.695, 0.655)), # ISO 16000: ink lines and dots on a white wall
]
DENOISE_CLOSE_UP = 480 # pixels of canvas, square, around the point at 1:1
@scene(media=[f'develop-denoise-{m.lower()}.png' for m in DENOISE_METHODS], @scene(media=[f'develop-denoise-{slug}-{m}.png' for slug, _, _ in DENOISE_FRAMES
for m in ('bilinear', 'best')],
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-pipeline/src/learned_denoise.rs', 'models/denoise/**']) 'core/dr-pipeline/src/learned_denoise.rs', 'models/denoise/**'])
def develop_denoise(): def develop_denoise():
"""The lit lamp and railing of an ISO 8000 night frame at 1:1, once per """Each frame at 1:1 on its point, once as Best develops it — what a
AI Denoise method, each cut to the same square of the canvas. Waits for raw opens with — and once by Bilinear, the camera's ordinary
each network rather than for a fixed time: on the CPU, which the demo conversion, cut to the same square of the canvas. Waits for the network
profile uses, Best takes several times what Fast does.""" rather than for a fixed time: on the CPU, which the demo profile uses,
mark = log_size() it takes many seconds."""
at_develop(DENOISE) for slug, photo, (fx, fy) in DENOISE_FRAMES:
a = dr.photo(0.45, 0.55) # the lit lamp, the railing and the skyline over the water mark = log_size()
dr.move(*a) at_develop(photo)
pause(0.3) a = dr.photo(fx, fy)
dr.x('click', '--repeat', 2, '--delay', 80, 1) dr.move(*a)
pause(1.5) pause(0.3)
group('Detail') dr.x('click', '--repeat', 2, '--delay', 80, 1)
in_column('AI Denoise@Text')
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) pause(1.5)
close_up(f'develop-denoise-{method.lower()}', a) t0 = time.time()
undo_all() while not denoise_landed(mark):
dr.move(*a) if time.time() - t0 > 600:
dr.x('click', '--repeat', 2, '--delay', 80, 1) raise TimeoutError(f'{photo}: Best never landed')
pause(1.2) pause(0.5)
pause(1.5)
close_up(f'develop-denoise-{slug}-best', a)
group('Detail')
dr.click(*in_column('Bilinear@RadioButton'))
pause(3.0)
close_up(f'develop-denoise-{slug}-bilinear', a)
undo_all()
dr.move(*a)
dr.x('click', '--repeat', 2, '--delay', 80, 1)
pause(1.2)
def close_up(name, p, size=DENOISE_CLOSE_UP): def close_up(name, p, size=DENOISE_CLOSE_UP):