第一次在PixInsight里把M42的线性图拉伸开的时候我盯着满屏又圆又亮的星点看了很久。它们确实漂亮但当我开始拉曲线、做反卷积的时候这些星点就成了最大的捣乱分子——高光全爆外圈套着Luminance叠加出来的光晕星云本身的云气反而被压得死死。也就是从那时候起我认识了StarNet这套免费的去星工具。这篇稿子不是官方文档翻译是从我第一次跑通到后来处理了几十张深空照片的实际使用记录内容包括网络原理、两个版本的部署差异、完整实战流程以及我踩过的各类坑。如果你也拍深空、正准备处理自己的星云图这篇文章应该能帮你少走不少弯路。1. StarNet解决的去星痛点为什么天体摄影非要跟星星过不去1.1 我们到底在折腾什么深空摄影里真正想拍出来的信号往往是暗弱的弥漫天体——发射星云的电离氢云气、反射星云的尘埃散射、星系盘里弥散的恒星集体光。恒星本身是点光源又亮又小在未经拉伸的线性图像里一颗普通亮星的中心峰值可以轻松是星云最亮区域的几十甚至上百倍。这就产生了一个经典矛盾为了让暗弱云气在拉伸后可见我们必须给整个图像施加很强的非线性拉伸曲线、Arcsinh、直方图变换都行。但同样这一套拉伸作用在星点上星点会立刻过曝、涨成一大团旁边还拖出衍射十字和内部反射产生的鬼影。反过来如果为了保住星点而限制拉伸幅度那么云气永远是灰蒙蒙的一层细节根本出不来。处理这种矛盾的老办法是分区域操作用星点蒙版保护星星然后放心地拉伸背景和云气。但蒙版本身做得准不准直接决定成片质量而星点蒙版恰恰是最难做的——亮星周围一圈渐变晕、暗星和噪声区分不开、密集星场里蒙版边缘断裂……这些问题能让一个晚上都耗在蒙版上。1.2 传统去星方案的尴尬所以才有了把星点跟云气彻底分成两张图的思路先得到一张无星版本拿它去拉伸云气、做反卷积、降噪再单独处理一张星点版本最后用图层混合把两者合回来。这套思路在计算机视觉里叫图像分解在后期软件里最常见的实现是PixInsight的MorphologicalTransformation形态学变换配合各种星点削减脚本。形态学变换的原理是假设星点是平滑的圆对称凸起用结构元素做腐蚀、膨胀来抹掉它们。对孤立的亮星效果还行但遇到致密星团、大小悬殊的星点混合、或者有明亮HII区核心的图像算法的抹除会伤到云气自身的高频纹理也会留下大量腐蚀边缘的暗环伪影。参数调起来更让人头疼结构元素大小、迭代次数、强度每一档都和具体图相关换一张图就重来。也正因为这样当基于神经网络的去星工具冒出来时整个后期圈子的反应是这东西要是真能用等于把大家从形态学参数里解放出来。StarNet就是其中最早免费开放、使用门槛也最低的一个。它的目标简单粗暴输入一张含星图像输出一张网络认为的无星版本剩下的就是各种下游处理了。2. 原理拆解一个UNet如何学会分辨恒星和星云2.1 网络架构与训练思路StarNet的底层结构是裁剪过的U-Net。U-Net最早是医学图像分割用的编解码结构编码器一路下采样把图像压成越来越小的特征图让网络看到全局上下文解码器一路上采样把特征图恢复成原尺寸中间用skip connection把编码器每一层的细节直接接到解码器对应层。这样网络既知道这块区域整体是一片很亮的扩散云气又保得住这里有一条细细的暗线这类局部细节。对去星任务来说有趣的地方在于网络要学的不是分割出每个星点像素而是直接回归出一张无星目标图。训练时给它成对的输入——同一场景的有星版本和无星版本——网络不断调整权重让输出越来越接近无星目标。这个过程本质上是在学星点与云气的形态学差异星点有明确的点扩散函数能量集中在很小的范围内而云气是弥散的、连续的、有纹理的。只要训练数据够丰富网络能学会把点状分量和弥散分量分开而不只是简单地把所有亮的东西都擦掉。从公开论文和仓库说明来看训练集的构造偏重配对思路既有人工合成背景叠合模拟星点的样本也有从真实深空图里整理出来的图像对。训练数据刻意覆盖了不同星点密度、不同背景亮度、不同成像风格这也是为什么它在大多数真实素材上都能给出一个至少能用的底图。说到底这就是一个监督回归问题和超分辨率、去马赛克这类任务没有本质区别。2.2 输入归一化这件事90%的翻车都出在它身上原理听起来简单但实际用起来最影响成败的不是网络结构而是输入数据的形态。神经网络对输入的数值范围非常敏感训练的时候如果喂的是归一化到[0,1]或[0,255]的图推理时突然塞进一个峰值几万甚至几十万的32位浮点线性图网络根本不知道该怎么处理输出大概率是一张灰蒙蒙的灾难现场。我一开始就犯过这个错误。当时刚叠完图兴致勃勃把一张32位TIF直接丢进StarNet跑完一看所谓无星图整个变成了中灰色雾气云气结构全糊了星确实没了但星云也没了。后来才意识到那个版本在官方文档里明确写着建议把输入图像归一化到一定范围最稳妥的做法是导出成16位TIF让软件自己处理归一化或者提前在PixInsight里用统计信息把图像除以一个合适的归一化系数。同理图像的状态也很关键。线性图尚未拉伸和拉伸后的图数值分布完全不同。StarNet在训练时见过的主要是线性或者轻微拉伸的数据你拿一张已经强力拉伸、背景被抬到很高、星点全部过曝的图去跑结果就会像我在第5节要讲的那样翻车。所以圈子里大家约定俗成的纪律是在拉伸之前、甚至在做完初步背景矫正之后就跑StarNet拿到无星线性图再去走后面的拉伸流程。3. StarNet 与 StarNetv2两个版本的部署差异3.1 版本对比StarNet目前大家用得最多的两个版本名字相似但部署方式是两回事。我一开始用StarNet的时候还以为它是StarNet的加强版实际上只是Windows下的图形界面版本模型和命令行v2版并不完全是一套。两者的差异集中在以下几个方面项目StarNetStarNetv2界面Windows图形界面点选图片即可Python命令行脚本适合批处理和自动化硬件要求需要NVIDIA显卡CUDA显存不足会直接报错CPU也能跑但极慢有GPU会快很多输入格式常见TIF/JPG/PNG通过文件对话框加载指定输入/输出目录批量处理整批图像模型新旧较早的模型训练数据规模较小较新的模型对复杂星场表现更好适用范围Windows单机用户上手快Linux/macOS/服务器都可用适合嵌入工作流另一个常被拿来和它对比的付费工具是Russ Croman的StarXTerminator。那个插件直接挂在PixInsight里处理速度和效果确实更好对致密星团、星系核心这类极端场景的容错也高。但它要花钱。星野摄影爱好者起步阶段先用免费的StarNet完全够用等作品质量要求上去了再考虑付费工具也不迟。3.2 实操部署步骤StarNet的部署大概是所有深度学习后期工具里最简单的去GitHub的Release页下载Windows安装包装好之后第一次运行会自动检测显卡。它的依赖是TensorFlow那一套老环境所以NVIDIA驱动得装好显卡算力不要太老起码得支持CUDA 3.0以上的算力。我在一张GTX 1060上跑过4000x3000的图一次推理大概两三分钟属于可接受范围显存只有2G的小卡可能会在快到2560分辨率时吃力这时候建议先把图缩一半再跑。StarNetv2的部署稍微有点门槛但好处是跨平台。以我当时在Linux工作站上的安装流程为例大致是这样的# 拉代码和权重 git clone https://github.com/rljacobson/starnetv2.git cd starnetv2 # 建虚拟环境装PyTorch python3 -m venv venv source venv/bin/activate pip install torch torchvision # 下载预训练权重放到weights目录 wget -O weights/starnet_v2.pth 权重下载链接具体命令参数以你拉下来的版本README为准不同fork之间的差异不小。我当时用的v2版本推理命令大概是python starnet.py --input ./images/in --output ./images/starless它会把输入目录下的所有TIF都处理一遍输出到指定目录。CPU跑起来是真的慢我试过在纯CPU的笔记本上跑一张3000x2000的图愣是跑了半个多小时后来果断换成GPU。所以如果你只有CPU时间不急倒可以凑合急着看效果还是建议缩图或者换机器。3.3 跑通第一次推理第一次跑通验证很重要别一上来就全尺寸处理。我建议这样先在原图中央裁一块1024x1024的小区域按16位TIF保存分别丢进两个版本跑一遍。这样做的目的有三个一是确认环境没装错二是在小图上对比两个版本的输出质量三是对比时间。我第一次对比时的实际感受是v2在星点更密集的区域残留更少背景纹理也比更干净。所以后来主力就换成了v2。但v2需要命令行操作对不习惯终端的Windows用户来说StarNet图形界面还是更方便。这两者并不冲突——我现在的习惯是Windows机器上装StarNet应急用正式批量处理丢到Linux工作站跑v2。4. 实战从线性彩色图到可用的无星底图4.1 预处理阶段的纪律拿到一张深空图先别急着开软件跑去星预处理阶段有几个纪律必须坚持。第一跑StarNet的输入必须是线性图。如果你在Siril或者PixInsight里已经把图拉伸过了先用ScreenTransferFunction把显示拉伸摘掉导出一份真正线性状态的数据最简单的方法是直接回到集成后的原图重新导出。第二格式建议选16位TIF。32位浮点TIF有时会因为归一化问题让网络输出异常8位则动态范围不够。16位TIF是StarNet训练时常见的输入形态最省事。第三如果图像有明显的光学渐晕或大梯度先做一个快速背景提取把梯度抹平再送进去。原因我在第2节说过网络对背景的绝对值和分布敏感不均匀的背景会干扰它区分什么该留、什么该去。实际操作时我通常会在PixInsight里做一次DBE或者GradientCorrection然后复制一份做去星原图保留不动。DBE这一步去星之后再精确重做一遍也不迟甚至效果更好原因后面专门说。4.2 用PixelMath提取星点层StarNet输出的是无星图。有了它星点层的获取就是个算术题。理论上星点 原图 - 无星图就行但直接相减会出现一些细节问题无星图在亮星周围可能有轻微过冲相减后星点中心出现了一个负的暗环。为了保险我在PixInsight的PixelMath里用的表达式是max(original - starless, 0)也就是把负值截断到0星点层只保留正值信息。对大多数图这个星点层已经足够干净可以直接拿去拉伸和混合。如果想要更平滑的星点层可以用除法思路original / starless。这个结果的物理意义近似增益图在云气区域接近1在星点处远大于1。再做一次归一化和非线性压缩能得到一个轮廓更柔和的星点蒙版或星点层。两种方法我都用过减法适合保留星点实际亮度除法适合生成蒙版和星点增强。4.3 分图层处理的完整链路下面以一张M42的彩色图为例给一套我验证过的完整链路。前提是已经拿到线性原图和StarNet产出的线性无星图无星底图处理把线性无星图先交给DBE做背景提取。没有星点的干扰自动背景采样的误判率大幅下降这是我用StarNet之后感受最明显的提升。之后做颜色校准、Arcsinh拉伸、云气区域的HDR合成、反卷积和降噪。因为全程没有星点参与云气的结构可以放心拉到很极端的状态不用担心星星过曝或星点蒙版边缘出问题。星点层处理用PixelMath算出星点层存成一张独立图。拉伸幅度要比无星图保守很多只让星点恢复到一个自然的亮度峰值即可如果星点周围仍有大光晕可以稍微用形态学收缩一圈或者直接对星点层做一次轻微的高斯模糊模拟自然的大气/PSF效果。图层混合最简单的做法是把两张拉伸好的图都转到Photoshop里无星图作底层星点层用Screen滤色模式叠上去。屏幕混合的本质是1 - (1 - A) * (1 - B)星点的亮度贡献被叠加到底图的暗部以上云气不会变灰。在PixInsight里也可以用PixelMath写同样的公式1 - (1 - background) * (1 - stars)注意两个输入都必须是归一化到0到1之间的拉伸图。收尾合成完毕后做一次整体色彩平衡和星点饱和度微调。StarNet处理后的星点层通常在色度上偏淡我会用星点蒙版单独给星点上一层饱和。这套链路跑顺了之后处理一张图从原来的整晚折腾蒙版压缩到大概半小时而且成片质量稳定得多。云气该有的细节全在星点又不会喧宾夺主。5. 翻车现场与排查思路星点残留、背景发灰、显存不足再好的工具也会翻车StarNet也不例外。下面这些情况我基本都遇到过按排查思路逐个说比直接给结论有用。5.1 星点残留与致密星团最典型的失败模式是星点没有完全去掉输出图里留下一个个浅浅的星点幽灵。最容易触发这种情况的题材是双星团NGC 869/884、球状星团、以及M31的核心区——这些地方恒星密度极高星点互相重叠单个星点的PSF形态已经不成立网络很难分辨哪些高频信号属于恒星、哪些属于星团的弥漫光。我的排查思路是先确认输入归一化没问题再确认星点没有大面积过曝。如果这两点都没问题那就是场景本身超出了模型的训练分布。此时别硬跑改用两个小技巧。一是把图像放大两倍再跑星点的形态会变得更接近网络常见输入跑完再缩回原尺寸。二是做局部覆盖——用蒙版把致密星团区域保护起来只对周围区域去星星团区域用传统形态学或者干脆保留星点后面混合时单独处理。这不是妥协深空后期本来就应该按区域分别处理。5.2 背景发灰、云气被误伤输出变成一张中灰色的图这是我在第2节提到的归一化问题。排查时先检查输入是不是16位TIF、有没有经过强力拉伸。如果是回到线性重新导出。更隐蔽的一种失败是云气被误伤明亮的星系核心M31核心、M51核心被当成恒星抹掉了或者大面积亮星云的核心也被削平。这个其实好理解——网络学到的点状光源特征在尺度上并不固定一个又亮又集中的星系核心形态上确实有点像超大号的星点。解决思路是对症下药跑去星之前先手工做一个星点蒙版的反向保护蒙版把星系核心和强亮云气区域圈出来在混合阶段用这个蒙版控制StarNet输出的参与强度。我处理M31时就是这么干的核心区完全保留原图结构外围盘面和尘埃带用无星图两者在交界处做了羽化过渡最终效果比一刀切好得多。5.3 显存、速度与格式问题显存不足是StarNet的常见报错。图形界面窗口可能直接弹出CUDA out of memory。这不是模型坏了纯粹是图太大。排查顺序如下先确认是独立显卡在跑而不是集成显卡把输入图降到2048x2048以内试一次把32位TIF转成16位有时能省一半显存还不行就在StarNetv2里改用CPU跑慢一点但能出结果。时间预期上我实测一张4000x3000的16位彩图GTX 1060大约2到3分钟RTX 3060大概半分钟到一分钟纯CPU可能需要半小时以上甚至更久。心里有个数别等得心慌。另外注意格式兼容。某些环境下StarNet打开FITS会报格式错误这时候先用PixInsight或Siril把FITS转成TIF再喂进去。反正去星之后再回到原工作流TIF和FITS的精度差异在16位级别可以忽略。5.4 一个M31核心的排查实例把上面几条串起来说一个我印象最深的翻车过程。第一次给M31做去星时我没有做任何预处理直接把一张32位FITS转成的16位TIF丢给了StarNet。输出结果有三宗罪M31核心被削成了一个扁平的土包核心周边的球状星团基本全残留盘面的尘埃带被磨掉了一层。排查链路是这样的先检查输入归一化没问题再检查拉伸状态发现那张图是从PS导出过的实际上已经包含了一次轻微的非线性拉伸数值分布已经偏离线性。回到PixInsight从集成原图重新导出纯线性16位TIF后残留问题好转了大半但M31核心还是被误伤。接着我做了两个改动一是用范围选择生成一个保护核心区的蒙版二是对整图做了一次2倍放大。最终输出里球状星团干净了核心保住了盘面结构也基本完整。整个过程大概浪费了一个晚上但换来的是对工具边界非常清楚的认知。6. 用无星图能多干些什么去星之后的扩展玩法把去星当成一个独立步骤就太亏了。它一旦跑通能改变后面一整串流程的处理方式。6.1 梯度提取与背景矫正的质变没有星点的图像背景梯度提取的准确度会提升一个台阶。之前用DBE时自动采样点如果恰好落在亮星上那块区域会被当成异常高值剔除或者反过来干扰背景模型。无星图不存在这个问题采样点随便撒背面模型和最后的背景均匀度都非常干净。为了这个优势我现在处理任何带强渐变的图都是先去星再DBE最后才拉伸。噪声处理也跟着受益。降噪算法无论是ACDNR、TGV还是各种AI降噪对边界和高频细节都会有意收着星点亮度过高时常被误判为细节而保留噪声。无星图的降噪对象就是纯粹的云气和暗背景可以开更激进的强度获得更光滑的背景而这种操作不会损失任何星点细节因为星点早就被单独拉出来了。6.2 星点层的复用与自动化有了无星图和原图提取星点层变成了一次性操作。这个星点层可以做很多事拉伸后当星星图层用做一份星点蒙版用于调整星点颜色和大小甚至可以给星点做一个独立的HDR处理解决亮星中心过曝完全变白的问题。我现在的半自动化流程是一批图叠好之后写一个简单的批处理脚本统一调用StarNetv2生成无星图然后在PixInsight里批量执行PixelMath提取星点层。这样同一晚拍的一整套素材后期流程完全是流水线式的。批量处理时StarNetv2明显更合适这也是我最终常驻Linux工作站跑v2版本的原因。6.3 几个我形成了习惯的操作纪律最后分享几条这几年沉淀下来的个人纪律都是常规文档里不会写的东西第一不要把StarNet的结果当成最终底图的一个成品它只是中间产物。网络输出难免带一些过度平滑最终的纹理和色彩必须用原图再次校准尤其是颜色校准我会用原图统计信息对无星图做一次色彩匹配。第二同一张图别只跑一次。我经常会在线性、轻微拉伸和2倍分辨率三种状态下各跑一次三个输出放在PixInsight里用蒙版混合取长补短。这个方法听起来玄学但对于M31这种极端目标效果确实比单次运行稳。第三也是最重要的永远保留线性原图。StarNet只是一个分解工具不是处理终点。我见过很多人跑出去星图之后觉得完成了直接拿它发图结果星云是虚的背景是光的整体像一张塑料片。正确顺序永远是线性原图存好无星图只作为中间产物最终成片要回到原图数据做确认。至于StarNet和付费的StarXTerminator怎么选我的建议是新手先用免费的StarNet把整套去星工作流跑熟理解星点层、无星层、图层混合这些核心概念。等你发现StarNet在某些极端目标上确实兜不住再考虑花那份钱。工具永远在迭代但分图层处理这个思路换什么工具都不会过时。