Traiter les brutes d'un Seestar S50 avec Siril et darktable
Une chaîne complète, automatisée de bout en bout, où chaque réglage est choisi sur une mesure et non sur une habitude. Siril empile, mesure et finit ; darktable termine. Elle tourne chez moi depuis le Champ du Feu ; les scripts sont en bas de page.
01 Ce que tu vas obtenir
Ton Seestar sait empiler tout seul, en direct, et il le fait bien. Ce que tu vas gagner en reprenant la main, ce n'est pas une image « plus jolie » : c'est une image dont tu décides, et dont chaque étape est justifiable.
Le temps que ça coûte, une fois la chaîne en place : tu branches le télescope, tu lances deux commandes, tu reviens plus tard.
Une nuit entière, de bout en bout
cd F:\Sub_Astro\_outils
.\Traiter-Nuit.ps1
.\Preparer-Darktable.ps1
La première copie les brutes, les range par nuit, empile chaque cible, mesure le bruit qu'elle a obtenu, en déduit les réglages de finition et écrit les images. La seconde applique un rendu darktable à toutes les cibles et sort les JPEG. Tu n'interviens à aucun moment.
Sur une nuit de cinq cibles et six cents poses, compte une dizaine de minutes en tout — dont l'essentiel part dans le débruitage, qui est aussi l'étape la plus rentable de la chaîne.
02 Pourquoi ne pas laisser faire l'app
L'application du Seestar empile en direct et jette les poses individuelles. C'est un choix défendable — elle est faite pour donner un résultat sur le terrain, pas pour alimenter un atelier. Mais tout ce qui suit devient impossible dès que les poses ont disparu.
Le rejet. Sur cent poses, il y en a toujours quelques-unes qu'un avion, un satellite, une rafale ou un nuage a gâchées. Un empilement avec rejet statistique les écarte pixel par pixel : là où une valeur s'écarte trop de la médiane de la pile, elle est ignorée. L'avion disparaît. L'app, elle, additionne tout.
L'étalonnage couleur par photométrie. Siril sait reconnaître le champ, y retrouver des étoiles cataloguées dont la couleur réelle est connue, et corriger les canaux pour que ces étoiles retrouvent leur couleur. Ce n'est pas un réglage de balance des blancs à l'œil : c'est une mesure sur des références.
Le débruitage et la séparation des étoiles. Deux traitements qui exigent une image linéaire — c'est-à-dire non étirée. Une fois que l'app a appliqué sa courbe, l'information nécessaire n'est plus là.
La raison de fond est toujours la même : ces traitements ont besoin de la pile et de données linéaires. Un JPEG déjà étiré ne les rend pas difficiles, il les rend impossibles.
03 Sortir les brutes du télescope
Un seul réglage à changer, une fois pour toutes, dans l'application : « Save each frame in enhancing ». À partir de là, chaque pose est écrite sur la mémoire du télescope en plus de l'empilement en direct.
Les poses atterrissent dans une arborescence prévisible :
MyWorks/
NGC 6888_sub/
Light_NGC 6888_20.0s_LP_20260903-0125.fit
Light_NGC 6888_20.0s_LP_20260903-0126.fit
…
Ce nom de fichier n'est pas décoratif. C'est la seule source d'information dont disposera la chaîne : le Seestar n'écrit ni journal de séance, ni fichier de métadonnées. Tout ce que le script sait, il le lit là.
Deux façons de récupérer tout ça : en USB, le télescope se monte comme un disque ; ou par le partage réseau, à l'adresse \\seestar\EMMC Images\MyWorks\. Le script accepte les deux — c'est le paramètre -Seestar.
04 La règle de minuit
Le Seestar ne connaît pas la notion de nuit. Il range par cible, séance après séance, et empile dans le même dossier ce que tu as photographié en mars et en septembre. Si tu veux raisonner par sortie — et tu le veux, car c'est l'unité qui a un sens : un ciel, une transparence, une Lune — il faut regrouper toi-même.
La seule date disponible est celle du nom de fichier. Et une nuit traverse minuit. Sur ma sortie du 2 septembre, trois cibles sur cinq portent la date du 3 : tout ce que j'ai pointé après minuit a été horodaté au lendemain. Un regroupement naïf par date aurait éclaté une seule et même nuit en deux.
La règle
Si l'heure inscrite dans le nom est avant midi, la pose appartient à la nuit de la veille.
Midi est le moment de la journée où personne n'observe. C'est donc la coupure naturelle entre deux nuits — la seule qui ne tombera jamais au milieu d'une séance.
En code, ça tient en six lignes, et c'est exactement la même fonction dans les deux scripts :
function Get-Nuit([string]$nom) {
if ($nom -match '(\d{8})-(\d{2})\d{4}') {
$d = [datetime]::ParseExact($matches[1], 'yyyyMMdd', [System.Globalization.CultureInfo]::InvariantCulture)
if ([int]$matches[2] -lt 12) { $d = $d.AddDays(-1) }
return $d.ToString('yyyy-MM-dd')
}
return $null
}
L'expression régulière capture les huit chiffres de la date puis les deux premiers de l'heure — c'est tout ce qu'il faut pour savoir de quel côté de midi on se trouve.
Si tes dossiers sont déjà rangés d'une autre façon, Ranger-Par-Nuit.ps1 les réorganise. Il gère les deux cas de figure — pas de niveau date, ou une date de traitement — et les ramène tous les deux à la nuit réelle.
Piège
En PowerShell, les noms de variables ne distinguent pas les majuscules. $racine et $Racine sont la même variable : une faute de casse n'est pas une erreur, c'est un écrasement silencieux. Le script s'exécute, il fait autre chose que ce que tu crois, et rien ne le signale.
Sécurité
Ranger-Par-Nuit.ps1 ne déplace rien tant que tu n'ajoutes pas -Appliquer. Lancé nu, il te montre ce qu'il ferait. Un script qui déplace des milliers de fichiers doit se relire avant de s'exécuter.
05 Installer Siril et ses catalogues
Ce chapitre vient avant le premier empilement, et ce n'est pas de la pédagogie : sans les bons catalogues installés, une cible sur cinq échouera au hasard, et tu passeras la soirée à chercher pourquoi.
Installe Siril 1.4.4. La chaîne n'utilise pas l'interface graphique mais siril-cli.exe, qui vit dans le même dossier. Le script le cherche tout seul aux emplacements habituels ; sinon tu le lui donnes avec -Siril.
Piège
Siril n'écrit ses préférences qu'à la fermeture, et siril-cli relit ce fichier au démarrage. Si tu installes des catalogues depuis l'interface graphique et que tu la laisses ouverte, la ligne de commande ne les verra pas. Ferme Siril avant de lancer le script. C'est le genre de détail qui donne l'impression que l'installation a échoué alors qu'elle est parfaite.
Viennent ensuite les catalogues Gaia locaux. Et là il faut être très précis, parce que c'est le piège qui coûte le plus cher.
Le piège qui rend fou
Il y a DEUX catalogues Gaia locaux, et ils sont différents.
- le catalogue astrométrique, dont se sert platesolve pour reconnaître le champ ;
- le catalogue photométrique, dont se sert spcc pour étalonner les couleurs.
Installer l'un ne dispense pas de l'autre. Et voici pourquoi c'est vicieux : sans le photométrique, SPCC ne s'arrête pas — il interroge Zenodo sur Internet. Zenodo répond en 504 par intermittence. Résultat : ça marche quatre fois, ça échoue la cinquième, sans que rien ait changé dans ta commande. Tu cherches un bug dans ton script alors que le problème est un serveur distant qui tousse.
Installation : Scripts → Python Scripts → Siril_Catalog_Installer, section SPCC Catalog, méthode « Visible from Latitude ». Le catalogue complet fait 48 morceaux ; cette méthode ne télécharge que la portion de ciel visible depuis chez toi.
06 La première pile
La passe 1 transforme des centaines de poses en une image unique, linéaire, aux couleurs justes. C'est la plus longue, et c'est celle qu'on ne veut refaire sous aucun prétexte — d'où tout le chapitre suivant.
Commandes — passe 1
calibrate light -cfa -equalize_cfa -debayer
register pp_light -2pass
seqapplyreg pp_light -framing=min -filter-round=2.5k
stack r_pp_light rej 3 3 -norm=addscale -output_norm -rgb_equal -out=result
load result
mirrorx -bottomup
subsky -rbf -samples=20 -tolerance=1.0 -smooth=0.5 -dither
platesolve -catalog=localgaia
spcc -oscsensor="IMX462" -narrowband -rwl=656 -rbw=20 -gwl=500 -gbw=30 -bwl=500 -bbw=30
save ../lineaire
stat
calibrate -cfa -equalize_cfa -debayer
-cfa dit à Siril que le capteur est en couleur, avec une matrice de Bayer : les pixels voisins ne mesurent pas la même couleur, et la détection des pixels chauds doit en tenir compte. -equalize_cfa égalise le niveau moyen des quatre positions de la matrice — sans ça, un quadrillage fin subsiste. -debayer reconstruit les trois couleurs par interpolation.
Pas de darks, pas de flats — et c'est assumé
Le Seestar ne donne pas accès à ses images d'étalonnage. Pas de trappe pour faire un dark, pas de moyen propre de faire un flat. On travaille donc sans, et c'est le rejet statistique de l'empilement qui reprend une partie du travail : les pixels chauds sortent de la pile parce que le dithering les déplace d'une pose à l'autre. Ce n'est pas équivalent à un vrai étalonnage. C'est ce que le matériel permet.
register -2pass puis seqapplyreg
Deux passes, parce que Siril doit d'abord mesurer tout le monde avant de décider. La première passe relève la position et la qualité de chaque pose sans rien écrire ; la seconde applique la transformation. Faire les deux d'un coup obligerait à choisir l'image de référence avant de les avoir toutes vues.
-framing=min conserve l'intersection commune à toutes les poses : les bords, où seules quelques poses contribuent, sont coupés. C'est ce qui évite le liseré bruité tout autour de l'image. -filter-round=2.5k écarte les poses dont les étoiles sont trop allongées — au-delà de 2,5 écarts-types de rondeur. Une rafale, un passage de vent, un raté de suivi.
Piège — quand l'intersection se réduit à un ruban
-framing=min est parfait tant que le suivi tient : aucun bord rongé, aucun recadrage à faire ensuite. Mais l'intersection de toutes les poses n'a aucune raison d'être grande si la monture a dérivé ou tourné pendant la séance.
Cas réel : 466 poses sur près de quatre heures, des brutes de 1080 × 1920 pixels, et un empilement de 145 × 1751 — onze pour cent de la largeur. Un ruban.
Et le symptôme n'accuse pas le coupable : platesolve échoue sur ce ruban, faute d'y trouver assez d'étoiles, et se plaint de l'astrométrie. On passe alors l'après-midi à réinstaller des catalogues qui n'avaient rien fait.
Le script mesure donc la sortie au lieu de lui faire confiance : il lit dans le journal de Siril la taille des brutes et celle du résultat, et compare.
function Test-CadrageEffondre([string]$log) {
$lm = [regex]::Match($txt, 'light_\d+[^,]*,[^,]*, (\d+)x(\d+)')
$rm = [regex]::Match($txt, 'result[^,]*,[^,]*, (\d+)x(\d+)')
...
return (($rw / $lw) -lt 0.4 -or ($rh / $lh) -lt 0.4)
}
En dessous de quarante pour cent dans l'une ou l'autre dimension, la passe 1 est refaite en -framing=current, qui garde le cadrage de l'image de référence : on récupère des bords un peu plus bruités, et une image. Aucune intervention n'est demandée, et le journal de la nuit dit que le repli a eu lieu.
stack rej 3 3 -norm=addscale -output_norm -rgb_equal
rej 3 3, c'est le rejet sigma : trois écarts-types de chaque côté. Un pixel qui s'écarte davantage de la médiane de la pile est ignoré pour ce pixel-là. C'est ce qui efface l'avion sans toucher au reste de l'image.
-norm=addscale ramène toutes les poses au même niveau et à la même échelle avant de les combiner — indispensable quand la transparence change ou que la Lune se lève en cours de séance. -rgb_equal égalise les trois canaux, ce qui donne à SPCC un point de départ neutre plus loin.
mirrorx -bottomup
Convention d'orientation. Les FITS n'ont pas tous le même sens de lecture vertical ; cette ligne remet l'image à l'endroit avant l'astrométrie.
subsky -rbf
Retrait du fond de ciel. La Lune, l'éclairage public, l'aube qui monte : tout cela dépose un gradient sur l'image, plus clair d'un côté que de l'autre. Siril échantillonne le fond en une grille de points, ajuste une surface souple — radial basis function — et la soustrait.
Le prix à payer arrive au chapitre suivant, et il est réel : après subsky, une partie des pixels du fond est négative. C'est normal — on a soustrait une moyenne. Mais ça rend un certain débruitage impossible.
platesolve puis spcc
platesolve reconnaît le champ : il identifie les étoiles et en déduit où pointe l'image, à quelle échelle et avec quelle rotation. spcc s'en sert pour retrouver, dans le catalogue photométrique, la couleur vraie des étoiles présentes, et corrige les canaux en conséquence.
Piège
Le bloc -narrowband est propre au filtre du Seestar. Quand le filtre anti-pollution est engagé, le capteur ne reçoit plus que deux bandes étroites : il faut le dire à SPCC, sinon il étalonne comme si toutes les longueurs d'onde passaient. Mais sur une cible photographiée sans filtre, ce même bloc serait faux et donnerait des couleurs aberrantes.
D'où la détection automatique : le script regarde si _LP_ figure dans les noms de fichiers, sur un échantillon de vingt poses, et choisit le bon étalonnage.
$echantillon = $fits | Select-Object -First 20
$avecLP = ($echantillon | Where-Object { $_.Name -match '_LP_' }).Count -gt ($echantillon.Count / 2)
La majorité des vingt premières, et non la première seule : une séance peut commencer par une pose d'essai sans filtre.
Piège
Siril refuse un commentaire # en fin de ligne de commande. Il lit la ligne entière comme un argument. Les commentaires doivent occuper leur propre ligne — c'est pour ça que les gabarits ont cette forme :
# @@COMMENT_SPCC@@
@@SPCC@@
La dernière ligne de la passe 1, stat, ne produit aucune image. C'est le sujet du chapitre suivant, et c'est le cœur de la méthode.
07 Lire la mesure
C'est le chapitre qui distingue cette chaîne d'une recette. Tout le reste, on le trouve ailleurs.
Un tutoriel ordinaire te donne des valeurs : « mets 0,12 », « active -da3d ». Ces valeurs viennent du matériel de celui qui les a écrites, de son ciel, de ses durées. Chez toi, elles sont au mieux approximatives.
L'idée est donc simple : ne pas régler la finition avant de savoir ce que l'empilement a donné. Entre les deux passes, on relit le bruit de fond réellement obtenu, et on en déduit les réglages.
Où est la mesure
La commande stat écrit dans le journal de Siril une ligne par couche :
Red layer: Mean: 258.1, Median: 93.1, Sigma: ..., bgnoise: 21.9
bgnoise est l'écart-type du bruit dans le fond de ciel, exprimé sur l'échelle 16 bits. C'est la seule valeur qui nous intéresse. Le script en prend la moyenne des trois couches et la ramène entre 0 et 1 :
function Get-Bruit([string]$log) {
if (-not (Test-Path $log)) { return $null }
$v = @()
foreach ($m in [regex]::Matches((Get-Content $log -Raw), 'bgnoise:\s*([0-9]+(?:\.[0-9]+)?)')) {
$v += [double]::Parse($m.Groups[1].Value, [System.Globalization.CultureInfo]::InvariantCulture)
}
if ($v.Count -eq 0) { return $null }
return (($v | Measure-Object -Average).Average) / 65535.0
}
Le bruit seul ne suffit pas
Le bruit de fond dépend de trois choses : la qualité du ciel, la durée d'intégration, et la cible. Comparer directement le bruit de deux nuits n'a donc aucun sens — trois heures sur une nébuleuse brillante donneront toujours moins de bruit que quarante minutes sur une galaxie faible, quel que soit le ciel.
Or le bruit d'une pile décroît comme la racine du temps d'intégration. Multiplier le bruit mesuré par la racine du nombre de minutes annule donc cette dépendance :
Cette quantité ne bouge plus ni avec la durée ni avec la cible. Elle ne réagit qu'au ciel — la Lune, la transparence, la hauteur de l'objet sur l'horizon. C'est exactement ce qu'on veut mesurer.
La référence, c'est toi
Chaque cible traitée ajoute une ligne à un fichier _mesures.csv. Au bout de trois mesures, la médiane des nuits précédentes devient la référence :
$refIndice = $null
if ($indices.Count -ge 3) {
$tri = $indices | Sort-Object
$refIndice = $tri[[int]($tri.Count/2)]
}
La médiane et non la moyenne : une seule nuit catastrophique — la pleine Lune, un voile d'altitude — décalerait une moyenne pour longtemps.
Et le point important : cette référence est la tienne. Elle sort de ton matériel, de ton site, de ta façon de pointer. Aucune constante n'a été inventée, aucun seuil recopié. Le même script chez quelqu'un d'autre s'étalonnera sur son ciel à lui, et donnera d'autres valeurs — c'est le comportement souhaité.
Ce que la comparaison décide
Le rapport entre l'indice de la nuit et la référence fait monter ou descendre d'un cran le profil de traitement :
if ($refIndice -and $indice) {
$r = $indice / $refIndice
if ($r -gt 1.30) {
$niveau = [math]::Max(0, $niveau - 1)
$cMes = "Ciel {0:P0} plus bruite que ta reference : traitement d'un cran plus prudent." -f ($r - 1)
} elseif ($r -lt 0.75) {
$niveau = [math]::Min(2, $niveau + 1)
$cMes = "Ciel {0:P0} plus propre que ta reference : on peut aller plus loin." -f (1 - $r)
}
}
Trente pour cent plus bruité que d'habitude : on recule. Vingt-cinq pour cent plus propre : on peut pousser. Entre les deux, on garde le profil déduit de la durée. Ces deux bornes sont asymétriques à dessein — se tromper en poussant trop coûte une image plastifiée, se tromper en restant prudent ne coûte presque rien.
Le repli
Tant que la référence n'existe pas — moins de trois mesures — le profil est choisi sur la durée d'intégration seule : moins de 90 minutes, niveau 0 ; moins de 240, niveau 1 ; au-delà, niveau 2. C'est grossier, et c'est précisément ce que la mesure vient remplacer dès qu'elle est disponible.
08 La finition
La passe 2 repart de lineaire.fit et ne réempile rien. C'est tout l'intérêt du découpage, et il vaut la peine d'insister dessus.
Refaire la finition coûte quelques dizaines de secondes contre plusieurs minutes pour un réempilement. C'est là que se font les essais : tu changes une valeur, tu relances -Finition, tu regardes. Si l'esthétique et l'empilement étaient dans le même script, tu paierais un réempilement complet à chaque essai — et de fait, tu n'essaierais pas.
Commandes — passe 2
load lineaire
makepsf stars -sym
rl -iters=10
denoise -da3d
autostretch -linked -2.8 0.12
rmgreen
satu 0.35
save final_32bits
starnet
pm "$starless_final_32bits$ + 0.5*$starmask_final_32bits$"
save final_starnet
savetif final_16bits
savejpg web 92
Les valeurs montrées ici sont celles du niveau 1 avec filtre. Le script les remplace selon la mesure — voir le chapitre suivant.
Déconvolution
makepsf stars -sym construit la fonction d'étalement du point à partir des étoiles de l'image elle-même : Siril mesure comment un point s'est étalé, et en déduit la déformation à inverser. -sym force une PSF symétrique, plus robuste sur des données bruitées.
rl est la déconvolution de Richardson-Lucy. Elle se fait sur données linéaires — donc avant l'étirement. Après, les relations d'intensité ne sont plus celles du capteur et l'algorithme travaille sur une fiction.
Piège — le ringing
Une déconvolution trop poussée entoure les étoiles brillantes d'un halo sombre, comme un cerne. C'est du ringing : l'algorithme, en cherchant à concentrer la lumière, creuse autour. Repère-le en zoomant sur les étoiles les plus brillantes du champ. Si tu le vois, redescends avec -Deconv 5.
Débruitage
Trois variantes selon le niveau, du plus agressif au plus retenu — les chiffres sont au chapitre suivant.
Piège — l'incompatibilité qui n'a l'air de rien
denoise -vst est incompatible avec subsky.
La transformation d'Anscombe, sur laquelle repose -vst, suppose des valeurs positives : elle stabilise la variance d'un bruit de Poisson, et un comptage de photons n'est jamais négatif. Or subsky vient de soustraire un fond, ce qui crée des pixels négatifs — c'est le fonctionnement normal d'une soustraction de gradient.
Le message est no suitable data in src fits, qui ne dit rien de tout ça. Les deux commandes sont correctes ; c'est leur ordre qui ne l'est pas.
Étirement
autostretch -linked -2.8 0.12. Le -linked applique la même courbe aux trois canaux — les délier réintroduirait une dominante que SPCC vient justement de corriger. Le troisième argument, 0,12, est le niveau où l'on pose le fond de ciel : c'est le réglage le plus lourd de conséquences de toute la chaîne, et il a droit à son tableau au chapitre suivant.
rmgreen retire la dominante verte, artefact classique des capteurs à matrice de Bayer — deux photosites verts pour un rouge et un bleu. satu remonte la saturation : 0,35 en bande étroite, 0,25 en large bande, parce que le filtre double bande produit des couleurs déjà très tranchées.
Séparation des étoiles
starnet sépare l'image en deux : la nébuleuse seule et les étoiles seules. On les recompose ensuite avec un coefficient inférieur à 1 :
pm "$starless_final_32bits$ + 0.5*$starmask_final_32bits$"
0,5 en bande étroite, 0,8 en large bande. Pourquoi atténuer les étoiles ? Parce que sur un champ riche, elles saturent le regard et écrasent les extensions faibles de la nébuleuse — celles qu'on a passé trois heures à recueillir. On ne les supprime pas, on leur rend leur place.
09 Les réglages, et pourquoi ces valeurs
Toutes les mesures ci-dessous ont été faites sur des images de synthèse : un champ fabriqué dont je connais la vérité — position et intensité de chaque étoile, forme et niveau de la nébuleuse, bruit ajouté. C'est la seule façon de mesurer un gain de résolution ou un rapport signal sur bruit sans dépendre de ce qu'on croit voir.
Le niveau du fond de ciel
Troisième argument d'autostretch. Plus il est bas, plus le fond est sombre et plus la nébuleuse ressort. Contraste mesuré = (nébuleuse − fond) / fond.
| Niveau du fond | Contraste | Bruit de fond | |
|---|---|---|---|
| 0,25 | 1,21 | 0,060 | valeur par défaut |
| 0,18 | 1,49 | 0,054 | |
| 0,12 | 1,82 | 0,046 | retenu |
| 0,08 | 2,10 | — | extensions faibles écrasées |
| 0,05 | 2,37 | — | extensions faibles écrasées |
Le contraste continue de monter jusqu'en bas du tableau, et pourtant on s'arrête à 0,12. Parce que le chiffre de contraste ne dit pas tout : sous 0,12, les extensions les plus faibles de la nébuleuse passent sous le niveau du fond et disparaissent purement et simplement. On gagne en contraste ce qu'on perd en matière. 0,12 est le point où les deux s'équilibrent.
Remarque au passage : le bruit de fond mesuré descend quand on baisse le niveau. Ce n'est pas magique — on comprime simplement les valeurs basses, donc l'écart-type du fond diminue avec elles.
Le débruitage
Rapport signal sur bruit mesuré sur les extensions faibles, celles qui sont à la limite de la détection — le seul endroit où la question se pose.
| Variante | RSB des extensions faibles | |
|---|---|---|
| sans denoise | 0,54 | référence |
| denoise | 1,63 | ×3 |
| denoise -da3d | 2,24 | ×4 — le plus efficace |
| denoise -sos=3 | 1,66 | équivalent au standard |
| denoise -mod=0,5 | 0,75 | atténué, à réserver aux données propres |
-da3d multiplie le rapport signal sur bruit par quatre. C'est énorme, et c'est pour ça qu'il est réservé au niveau 0 — celui des données limitées par le bruit, où il n'y a rien à perdre. Sur des données propres, la même agressivité lisserait du détail réel : d'où -mod=0.5 au niveau 2, qui fait délibérément moins bien sur ce tableau parce que ce n'est pas ce tableau qu'on cherche à optimiser.
-sos=3 coûte trois passes pour le résultat du débruitage standard. Écarté.
La déconvolution
FWHM mesurée sur les étoiles du champ de synthèse — plus elle est petite, plus les étoiles sont fines.
| Itérations | FWHM (px) | Gain résolution | Coût en bruit |
|---|---|---|---|
| 0 | 1,696 | — | — |
| 5 | 1,512 | +10,8 % | +8,2 % |
| 10 | 1,397 | +17,6 % | +19,5 % |
| 15 | 1,325 | +21,9 % | +27,7 % |
| 20 | 1,291 | +23,9 % | +35,4 % |
| 30 | 1,293 | +23,7 % | +49,5 % |
Deux lectures de ce tableau. D'abord, le gain sature à 20 itérations : entre 20 et 30, la FWHM passe de 1,291 à 1,293 px, c'est-à-dire qu'elle ne bouge plus, tandis que le bruit passe de +35,4 % à +49,5 %. Trente itérations, c'est payer quatorze points de bruit pour rien.
Ensuite, jusqu'à 10 itérations le gain de résolution et le coût en bruit progressent presque à parité — +17,6 % contre +19,5 %. Au-delà, le bruit prend l'avantage : +21,9 pour +27,7 à quinze, +23,9 pour +35,4 à vingt. Comme le débruitage passe ensuite et récupère une partie de ce bruit, 10 itérations est le point d'équilibre au niveau moyen. Le script en met 5 au niveau 0 et 15 au niveau 2 — la déconvolution est proportionnée à la propreté des données, exactement comme le débruitage.
if ($Deconv -ge 0) { $iters = $Deconv }
else { $iters = @(5, 10, 15)[$niveau] }
10 Ce que j'ai essayé et écarté
Un tutoriel qui ne montre que ce qui a marché cache la moitié du travail. Voici quatre pistes réputées bonnes, mesurées, et abandonnées. Chacune est recommandée quelque part sur un forum.
Écarté — pondération de l'empilement par le bruit
stack … -weight_from_noise
Résultat : −0,35 %. Légèrement pire que sans.
L'idée est séduisante : donner plus de poids aux poses les moins bruitées. Mais le rejet sigma écarte déjà les valeurs aberrantes, et -norm=addscale ramène déjà toutes les poses à la même échelle. Le travail est fait deux fois, et la seconde fois ajoute sa propre variance d'estimation.
Écarté — filtrage des poses par FWHM
seqapplyreg … -filter-fwhm=85%
Résultat : +1,1 % de résolution pour +1,2 % de bruit. Échange nul.
Jeter 15 % des poses, c'est perdre 15 % du temps d'intégration — donc gagner du bruit. Le gain de finesse ne compense pas exactement la perte. Autant garder les poses : à qualité égale, plus de signal vaut mieux.
Le filtre de rondeur, lui, est conservé : une pose bougée n'apporte pas de signal utilisable, elle étale des traits.
Écarté — CLAHE
Résultat : contraste de 1,81 à 0,95, et bruit doublé.
L'égalisation d'histogramme à contraste limité travaille par tuiles locales. Sur une photo de paysage, elle révèle des ombres. Sur une astrophoto, le fond de ciel est presque uniforme : l'algorithme y voit un manque de contraste local à corriger, et amplifie le bruit en croyant révéler du détail. Il fait exactement le contraire de ce qu'on lui demande.
Écarté — masque flou
Résultat : +0,07 de contraste pour −40 % de rapport signal sur bruit.
Sept centièmes de contraste contre quatre dixièmes du RSB. Il n'y a pas d'arbitrage à faire, il y a un refus.
Ces quatre mesures ont un point commun : elles ne se devinent pas. Trois d'entre elles paraissent raisonnables sur le papier, et la quatrième est largement conseillée. Sans champ de synthèse pour mesurer, j'aurais gardé au moins deux d'entre elles en me disant que ça ne pouvait pas faire de mal.
11 La finition darktable
Siril s'arrête au bon endroit. Ce qui reste à faire après lui n'est plus du traitement du signal : c'est du goût, et ça se décide en regardant l'image.
À la sortie de la passe 2, le TIFF 16 bits est empilé, dégradienté, étalonné en couleur, débruité, étiré et allégé de ses étoiles. darktable ne refait aucune de ces choses — il n'en a ni les moyens ni l'intérêt. Il apporte trois outils que Siril n'a pas : le contraste local, la couleur par plage, et un recadrage qu'on voit pendant qu'on le fait.
Ouvre le TIFF, jamais le JPEG
final_16bits.tif et non web.jpg. Le JPEG est en 8 bits et déjà compressé : les tons faibles — c'est-à-dire toutes les extensions de nébuleuse pour lesquelles tu as posé quatre heures — y sont déjà perdus. Les récupérer ensuite ne se peut pas.
Une croyance vérifiée, et fausse
On lit partout qu'il faut basculer le flux de travail par défaut sur « aucun » avant d'ouvrir une image astro, sans quoi darktable applique exposure et filmic rgb par-dessus l'étirement de Siril et écrase tout. Le conseil est répété assez souvent pour qu'on l'applique sans regarder.
Mesuré : le flux relatif à la scène ne s'applique pas à un TIFF
En exportant un TIFF 16 bits et en relevant la pile de modules réellement appliquée, on ne trouve que quatre entrées : colorin, colorout, gamma et flip. Ni exposition, ni filmic.
Les préréglages du flux relatif à la scène sont conditionnés aux fichiers raw. Un TIFF n'en est pas un, la condition ne se déclenche pas, et le réglage qu'on croyait indispensable ne changeait rien. Vérifie chez toi en une minute : ouvre une image, regarde la liste des modules actifs.
L'ordre de travail
Sept modules, dans cet ordre. Les noms sont donnés en anglais : la zone de recherche en bas du panneau de droite les reconnaît tous, y compris en interface française, où les traductions changent d'une version à l'autre.
| Module | Ce qu'on y fait |
|---|---|
| crop | couper les bords d'empilement, et cadrer l'objet |
| rgb levels | poser le point noir |
| tone equalizer | assombrir le fond, relever l'objet |
| color balance rgb | le module central |
| local contrast | faire ressortir la structure |
| color zones | séparer le Hα du OIII |
| contrast equalizer | détail fin d'un côté, lissage du fond de l'autre |
L'égaliseur de tons est le plus gros gain des sept. Sur une astrophoto étirée, les deux choses qui comptent ne se touchent pas : le fond de ciel occupe les zones −8 à −5 EV, l'objet les zones −4 à −2 EV. C'est précisément la situation pour laquelle ce module existe. Baisse les zones basses de 0,5 à 1 EV, relève les moyennes de 0,3 à 0,8 : l'écart se creuse sans que rien d'autre bouge.
Piège
Garde le filtre guided. Le mode simple ignore les contours et pose des halos autour des étoiles brillantes — le même défaut que celui pour lequel on a écarté le masque flou au chapitre précédent, obtenu par un autre chemin.
color balance rgb a un intérêt particulier ici, et il vaut d'être dit précisément : ses curseurs de chroma agissent par plage de luminance. Autrement dit, on peut monter la couleur de l'objet sans monter celle du fond de ciel. Un curseur de saturation ordinaire ne sait pas faire cette distinction — il sature aussi le bruit coloré du fond, qui est exactement ce qu'on ne veut pas voir.
Ce qu'il ne faut pas utiliser
| filmic rgb · sigmoid | Conçus pour comprimer la dynamique d'une scène réelle dans un écran. Ici la dynamique a déjà été traitée par autostretch, sur des données linéaires et avec le fond posé où on voulait : les repasser dessus écrase le contraste qu'on vient de construire. |
| sharpen | C'est un masque flou. Halos sombres autour de chaque étoile — mesuré au chapitre 10, et refusé là aussi. |
| denoise (profiled) | Son profil est calibré pour un capteur qui lit du raw, une pose à la fois. Devant un empilement de cinq cents poses déjà passé par -da3d, il n'a plus d'objet — et il lisse ce qui restait. |
| velvia | Sature tout, donc aussi le fond de ciel et son bruit. |
Le point de départ, mesuré
Régler sept modules à la main sur chaque cible d'une nuit, ce n'est pas tenable. Preparer-Darktable.ps1 fabrique donc un réglage de départ et l'applique à toutes les cibles — un point de départ, pas un point d'arrivée : on l'affine ensuite en chambre noire, sur les deux ou trois images qui le méritent.
Ses valeurs viennent d'une vraie image, un NGC 6888 de quarante-quatre minutes, et non d'un champ de synthèse :
| Contraste / lum. / satu. | Fond | R−G | Bruit chroma | Contraste | Surface de signal |
|---|---|---|---|---|---|
| aucun réglage | 30,7 | 1,0 | 8,79 | 2,87 | 18,65 % |
| 0,35 / −0,05 / 0,45 | 12,0 | 3,0 | 14,56 | 8,11 | 26,54 % |
| 0,40 / −0,12 / 0,15 | 7,3 | 2,0 | 10,07 | 12,41 | 28,97 % |
| 0,50 / −0,18 / 0,00 | 4,3 | 1,0 | 6,60 | 19,77 | 29,56 % |
Une colonne mérite qu'on s'y arrête : R−G, l'écart moyen entre le rouge et le vert dans le fond de ciel. Un fond neutre vaut 1. À 0,45 de saturation il monte à 3 : le fond a viré au rouge. C'est visible à l'œil, et c'est un défaut qu'on ne rattrape plus ensuite.
Ce que ce tableau enseigne
La saturation coûte cher et ne rapporte presque rien. De 0 à 0,45, la couleur de l'objet gagne un tiers pendant que le bruit coloré du fond double et que le fond rougit. Le contraste et une luminosité négative obtiennent le même résultat visuel sans cet effet — et laissent plus de surface de signal visible, 29,6 % contre 26,5 %.
La raison est en amont : Siril a déjà appliqué sa propre saturation, dosée selon le profil de la cible — satu 0.35 en bande étroite, 0,25 en large bande. Remonter la saturation dans darktable, c'est la passer deux fois. D'où -Saturation 0 par défaut.
Et Lightroom ?
C'est le même type d'outil, et il ne fait rien de plus pour ce travail. Son seul avantage réel est le masquage, plus rapide et plus intuitif que celui de darktable — ce qui n'est pas rien, puisque les vrais gains restants sont locaux.
Quant au débruitage par intelligence artificielle, que beaucoup espèrent ici : il n'accepte que les raw matriciels, Bayer ou X-Trans. TIFF et JPEG sont explicitement exclus, et l'option reste grisée. Ce n'est pas une limitation arbitraire — l'algorithme dématrice et débruite dans le même mouvement, il lui faut donc une matrice à dématricer. Un empilement de cinq cents poses n'en a plus.
12 Tout automatiser
Sept fichiers, dans un dossier _outils posé à côté des données. Cinq scripts PowerShell qui décident, deux gabarits Siril qui exécutent.
Les deux derniers se répondent. Preparer-Darktable.ps1 part des valeurs mesurées du chapitre précédent et n'a besoin de rien ; Finir-Darktable.ps1, lui, part d'une image que tu as réglée à la main jusqu'à ce qu'elle te plaise. darktable écrit alors l'historique dans un fichier .xmp posé à côté du TIFF : ce fichier devient la recette, et le script l'applique aux autres cibles. On peut aussi lui donner le nom d'un style darktable plutôt qu'un chemin.
Les deux scripts de rangement, et lequel prendre
Importer-Vrac.ps1 attaque un dossier où tout est mélangé — plusieurs cibles, plusieurs nuits, à plat — et le déplie. C'est celui qui sert quand quelqu'un t'envoie ses brutes. Ranger-Par-Nuit.ps1 reprend des dossiers de cible déjà constitués et les remet sous la bonne nuit.
Les deux ne font rien tant qu'on n'a pas ajouté -Appliquer : ils décrivent ce qu'ils feraient et s'arrêtent là. Un script qui déplace des fichiers doit se lire avant de s'exécuter, et la seule façon d'en être sûr est qu'il refuse d'agir par défaut.
Ce que ça donne sur le disque
Rien n'est à créer à la main : le premier lancement pose l'arborescence et s'y tient.
F:\Sub_Astro\
_outils\ les sept fichiers, et _mesures.csv
2026-09-02_Champ-du-Feu\ créé tout seul, nuit + lieu
web\ les JPEG sortis de Siril
web-darktable\ les JPEG finis
NGC 6888\
lights\ les brutes de la nuit
lineaire.fit le point de reprise de la passe 2
final_16bits.tif à ouvrir dans darktable
_pile.ssf / _finition.ssf les recettes réellement exécutées
siril-pile.log / siril-finition.log
Les deux .ssf posés dans le dossier de la cible ne sont pas des copies des gabarits : ce sont les scripts remplis, avec les valeurs de cette nuit-là et les commentaires qui les expliquent. Six mois plus tard, on peut donc relire pourquoi cette image a reçu denoise -da3d et pas autre chose — et la rejouer à l'identique.
Comment les gabarits deviennent des scripts
Les fichiers .ssf ne sont pas exécutés tels quels : ils contiennent des marqueurs que PowerShell remplace avant chaque exécution. Y compris les commentaires — c'est ce qui fait que le script Siril généré explique lui-même pourquoi il fait ce qu'il fait, avec les chiffres de la nuit en cours :
$ssf = $txtFin
foreach ($cle in $champs.Keys) { $ssf = $ssf.Replace($cle, [string]$champs[$cle]) }
$restants = [regex]::Matches($ssf, '@@\w+@@')
if ($restants.Count -gt 0) {
Write-Host ("placeholders non remplaces : {0}" -f ($restants.Value -join ', ')) -ForegroundColor Red
continue
}
Le contrôle des marqueurs restants vaut d'être signalé : si un @@…@@ survit au remplacement, la cible est abandonnée avant d'appeler Siril. Sans lui, Siril recevrait une ligne incompréhensible et échouerait en donnant un message sans rapport avec la cause.
Les commandes
| .\Traiter-Nuit.ps1 | la dernière nuit trouvée sur le télescope |
| -Toutes | toutes les nuits présentes |
| -Nuit 2026-09-02 | une nuit précise |
| -SkipCopy | ne relit pas le télescope, travaille sur ce qui est déjà copié |
| -Finition | refait la passe 2 seulement — la commande des essais |
| -Refaire | refait tout, empilement compris |
| -Deconv 0 | coupe la déconvolution ; -Deconv 5 la réduit |
| -Recadrer 60 | recadrage centré, en pourcentage du champ |
| -Etoiles 0.45 | dose d'étoiles réinjectées après StarNet |
| -Cadrage current | force le cadrage de l'image de référence |
| -SansStarnet | garde les étoiles telles quelles |
| -Drizzle | expérimental — voir plus bas |
-Recadrer mérite plus qu'une ligne de tableau. Sur une galaxie ou une petite planétaire, l'objet occupe le quart du champ du Seestar : une galaxie de 11′ dans un champ de 43′ est un point au milieu du vide. Recadrer change davantage l'impression visuelle que n'importe quel réglage de courbe — et ça ne coûte rien puisque la passe 2 se rejoue en quelques dizaines de secondes.
Piège
StarNet refuse les images de moins de 512 × 512 pixels. Un recadrage un peu trop serré fait donc échouer toute la finition, pas seulement la séparation des étoiles. Le script relève le recadrage au minimum viable plutôt que de s'arrêter.
Et pour darktable, les mêmes principes :
| .\Preparer-Darktable.ps1 | fabrique le réglage de départ et exporte toutes les cibles |
| -Contraste 0.5 -Saturation 0 | les valeurs mesurées, modifiables |
| -Cible "NGC 6888" -Ouvrir | une seule cible, puis ouvre darktable dessus |
| -Largeur 2048 -Qualite 95 | la taille et la qualité des JPEG produits |
| .\Finir-Darktable.ps1 -Reglage … | applique ton propre .xmp, ou un style nommé |
Ce que le script refuse de traiter
Deux garde-fous. D'abord un minimum de poses :
if ($n -lt $MinBrutes) {
Write-Host (" {0,-22} {1,4} brutes ignore (moins de {2})" -f $cible, $n, $MinBrutes)
continue
}
Trente poses par défaut. En dessous, le rejet sigma n'a plus assez d'échantillons pour distinguer un satellite d'une étoile : la statistique sur laquelle tout repose n'existe plus.
Ensuite, les planètes — le sujet du dernier chapitre.
Le drizzle
Le drizzle reconstruit une image à plus haute résolution en exploitant le fait que les poses ne sont jamais exactement superposées. Il exige donc que le pointage bouge légèrement d'une pose à l'autre — ce que fait le dithering. Et il travaille sur la matrice de Bayer brute :
if ($Drizzle) {
$calibrate = "calibrate light -cfa -equalize_cfa"
$cCal = "Drizzle : PAS de -debayer ici, le drizzle travaille sur la matrice de Bayer brute."
$blocDrizzle = " -drizzle"
}
Pas de -debayer à la calibration : dématricer d'abord, ce serait interpoler puis demander au drizzle de retrouver une information qu'on vient de moyenner.
Pourquoi ça vaut le détour
Un Seestar sort des images de 1080 pixels de large. Le drizzle ×2 en donne 2160. Sur un écran moderne, la différence n'est pas subtile — et c'est du détail réellement reconstruit, pas de l'agrandissement.
Télécharger
Version —
Les sept fichiers vont dans le même dossier : Traiter-Nuit.ps1 y cherche ses gabarits sous leurs noms exacts, et y écrira _mesures.csv. Sous Windows, les fichiers téléchargés arrivent marqués comme venant d'Internet et PowerShell refuse de les exécuter : une fois pour toutes, Get-ChildItem …\_outils\*.ps1 | Unblock-File. Libres d'usage et de modification, fournis sans garantie — les valeurs ont été mesurées sur du matériel précis, vérifie-les sur tes propres images.
13 Ce que cette chaîne ne fait pas
Trois choses qu'aucun réglage de ce document ne remplacera.
Elle ne remplace pas le temps de pose
Le rapport signal sur bruit croît comme la racine du temps d'intégration. Le grain qu'on voit à 100 % sur une image de quarante-cinq minutes est du bruit de photons : il vient du fait que les photons arrivent en nombre fini et irrégulier, et aucun logiciel ne peut inventer ceux qui ne sont pas venus. Quatre heures sur la même cible le diviseraient par deux. Aucun curseur ne fera jamais ça.
C'est aussi pourquoi la chaîne mesure au lieu de supposer : quand le bruit est ce qu'il est, la seule décision qui reste est de savoir jusqu'où on peut pousser sans le rendre visible.
Elle ne remplace pas le jugement
Le point de départ darktable est global : il agit sur toute l'image de la même façon. Or les gains qui restent, une fois la chaîne passée, sont locaux — éclaircir la nébuleuse sans relever le fond autour d'elle, retenir une étoile trop brillante, ouvrir une zone d'ombre. Cela demande un masque, donc une main, donc quelqu'un qui regarde. C'est précisément la part que je ne cherche pas à automatiser.
Elle ne fait pas non plus de mosaïque, ni de calibration par darks et flats, auxquels le Seestar ne donne pas accès.
Elle ne fait pas de planétaire
Une planète n'a rien à y faire, et il vaut mieux savoir pourquoi que de découvrir le résultat.
Vingt secondes de pose sur Saturne donnent un disque brûlé : la planète est des milliers de fois plus brillante qu'une nébuleuse, elle sature bien avant la fin de la pose. Ensuite, subsky modélise le fond de ciel autour d'elle et le soustrait — sur une image dont l'essentiel de la surface est du fond, la planète est traitée comme une anomalie locale. Enfin starnet la prend pour une étoile et la range dans le masque d'étoiles.
Trois traitements successifs qui font exactement leur travail, et dont l'enchaînement détruit l'image. Le script détecte donc les noms de planètes et passe son chemin :
$planetes = @('saturn','saturne','jupiter','mars','venus','mercury','mercure',
'uranus','neptune','moon','lune','sun','soleil','pluto','pluton')
Avec une précaution : un nom contenant ngc, ic, m, nebula ou nebuleuse annule la détection. « Mars » est une planète ; « NGC 2237, la nébuleuse de la Rosette près de Mars » ne l'est pas.
Le planétaire, c'est un autre métier : vidéo et lucky imaging. On filme des milliers d'images très courtes, on ne garde que celles où l'atmosphère s'est tenue tranquille, et on empile celles-là. Rien à voir avec la chaîne décrite ici.
— Les pièges, en un coup d'œil
Chacun m'a coûté un aller-retour. Ils sont expliqués à l'endroit où ils mordent ; les voici rassemblés pour la relecture.
| Commentaire # en fin de ligne | Siril lit la ligne entière. Le commentaire doit occuper sa propre ligne. |
| denoise -vst après subsky | Anscombe exige des valeurs positives, subsky en crée des négatives. Erreur no suitable data in src fits. |
| Interface Siril restée ouverte | Les préférences ne sont écrites qu'à la fermeture. siril-cli ne voit pas les catalogues. |
| Un seul catalogue Gaia installé | Astrométrique et photométrique sont deux catalogues distincts. Sans le second, SPCC interroge Zenodo, qui répond en 504 par intermittence. |
| Bloc -narrowband sur cible sans filtre | Étalonnage faux. D'où la détection de _LP_ dans les noms. |
| Une planète dans la chaîne | Disque brûlé, fond modélisé autour d'elle, prise pour une étoile par StarNet. |
| -framing=min sur une nuit qui a dérivé | L'intersection de toutes les poses se réduit à un ruban. Mesuré : 145 × 1751 sur des brutes de 1080 × 1920. Et c'est platesolve qui se plaint, ce qui envoie chercher au mauvais endroit. Repli automatique sous 40 %. |
| StarNet sous 512 × 512 | Il refuse. Un recadrage trop serré fait échouer toute la finition, pas seulement les étoiles. |
| bgnoise : en interface française | Siril insère une espace fine insécable avant le deux-points. Chercher bgnoise: collé ne trouve jamais rien — et la mesure tombe à l'eau en silence, sans erreur. Accepte n'importe quelle ponctuation entre le mot et le nombre. |
| $racine et $Racine | PowerShell ne distingue pas la casse : l'une écrase l'autre en silence. Observé : à partir de la deuxième nuit, tout partait dans un sous-dossier de la dernière cible traitée. |
| Un chemin passé à un exécutable natif | PowerShell mange les antislashs. F:\…\NGC 6888.jpg arrive en F:…NGC 6888.jpg, et le fichier atterrit ailleurs. Remède : se placer dans le dossier et ne passer qu'un nom de fichier. |
| La virgule décimale française | Le formatage -f suit la culture courante : 0.45 devient 0,45, et Siril reçoit une virgule au milieu d'une commande. Tout ce qui est numérique passe en culture invariante. |
| -replace | C'est une expression régulière, qui interprète $ et \ dans le remplacement. .Replace() est littérale et sans surprise. |
| Set-Content -Encoding UTF8 | Ajoute une marque d'ordre d'octets sous PowerShell 5.1, et Siril ne lit alors plus la ligne requires. Écrire avec UTF8Encoding($false). |