邮件发出去了。
键盘的嗒嗒声停了。办公室安静了几秒,然后像开水泼进油锅,轰地炸开。椅子滑轮滚动声,急促的脚步声,压低的惊呼和议论混在一起。
陈默起身。他走到办公室中央,拍了拍手。声音不高,但所有人都停了下来,转头看他。
“都看到了。”他说,声音有点沙,“两周。我们要拿出能下地八百米的东西。”
沈清澜站在白板旁。她手里还握着笔,笔尖指着那句“湿度百分之百”。墨迹没干,在灯光下反着幽暗的光。
“这不是升级。”她开口,声音很平,“是重写。从底层逻辑开始。”
王薇抱着文件从走廊跑进来。她脸颊发红,喘着气。“赵主任那边……资料补全了。”她把u盘放在桌上,“现场实测视频,还有掘进机的传感器日志。”
陈默插上u盘。
文件很大,拷贝进度条走得很慢。百分之十三,百分之二十七,百分之五十六。硬盘灯闪烁,发出轻微的咔哒声。
百分之百。
他点开第一个视频。
画面跳出来,是手持设备拍的。镜头晃得厉害,光线暗得像蒙了层黑布。只有矿灯的光柱在粉尘里切开一道惨白,照见粗糙的岩壁和扭曲的钢筋。
水珠不断砸在镜头上。
啪嗒。啪嗒。声音闷重,混着掘进机刀盘旋转的轰鸣。那轰鸣不是持续的声音,是一阵一阵的,像巨兽在黑暗深处喘息。
沈清澜俯身盯着屏幕。她鼻尖几乎碰到显示器,呼吸在屏幕上凝出白雾。
“湿度百分之百。”她喃喃道,“镜头永远蒙着水膜。”
视频播了四分钟。识别算法尝试了十七次,失败了十七次。红色的错误框在画面上乱跳,最后定格在“目标丢失”的警告上。
陈默关掉视频。
会议室里只剩下空调出风的声音。那声音嗡嗡的,带着某种低频振动,让人的太阳穴跟着一跳一跳。
“分两组。”陈默说。他语速很快,像在和自己赛跑。“沈总监带算法组,重构补偿模型。我带队去实验室,搭模拟环境。”
没人说话。
只有笔尖划过纸面的沙沙声,还有椅子挪动时轮子摩擦地板的吱呀。
沈清澜已经回到白板前。她擦掉之前的架构图,动作很用力。板擦刮过白板,留下大片的空白,像雪后的荒地。
然后她开始画新的。
第一笔很重,线条直直地劈下来。那是主框架,骨骼。接着是细枝末节,神经网络节点,数据流管道,异常处理回路。她的手很稳,稳得不像在画图,像在雕刻。
陈默转身往外走。
实验室在三楼走廊尽头。门是厚重的隔音门,推开时铰链发出沉闷的呻吟。里面很大,挑高五米,像个小型厂房。
温度控制系统发出低频嗡鸣。
左侧是高温区,加热管阵列排成蜂窝状,红外测温仪的激光点在地面上投出细小的红点。右侧是低温舱,舱门开着,白色的冷气像瀑布一样从门缝里泻下来,在地板上积成薄薄的霜。
中间是振动台。
四根粗壮的液压柱撑着钢制平台,平台表面焊满了螺栓孔。现在空着,像张等待被填满的钢床。
硬件组的李工已经在了。他蹲在振动台旁,手里拿着扳手,正在拧一个松动的螺栓。扳手和金属碰撞,发出清脆的铛声。
“陈总。”他抬头,脸上有油污,“要模拟到什么程度?”
陈默走过去。他伸手摸了摸振动台的钢面,冰凉,粗糙,指尖能感到细微的沙粒感。
“掘进机工作时的震动谱。”他说,“赵主任给的资料里有。峰值加速度能到十五个g。”
李工吹了声口哨。很轻,像口哨刚出口就被空气吃掉了。
“那得加固。”他站起来,用袖子擦了把额头,“现有的夹具撑不住。镜头会飞出去。”
“加固需要多久?”
“三天。”李工想了想,“如果加班,两天半。”
“两天。”陈默说,“给你调两个人。”
李工没吭声。他蹲回去,继续拧那个螺栓。这次拧得很慢,很用力,指节因为用力而发白。
陈默走向粉尘模拟区。
那里像个透明的玻璃房子。进气口在上方,连接着粉尘发生器。现在机器关着,玻璃内壁干净得像不存在,只有角落积了层薄灰,是上次测试留下的。
他推门进去。
门轴有点涩,推开时发出吱呀的摩擦声。里面很安静,安静得能听见自己的心跳。空气里有股淡淡的铁锈味,混着某种化学品的甜腻。
系统在脑海里展开推演。
不是完整的路径,是碎片。像打碎的镜子,每一片都映出不同的可能性。他看见数据流在极端湿度下扭曲,看见震动让特征点像受惊的鱼群一样四散,看见粉尘在镜头前筑起一堵灰色的墙。
然后墙塌了。
不是物理的塌,是逻辑的塌。算法在连续的错误积累后崩溃,像雪崩,从一个小小的误判开始,连锁反应,最后吞噬整个识别流程。
他睁开眼。
玻璃映出他自己的脸。眼圈还是黑的,但瞳孔很亮,亮得像里面烧着火。
“得留条生路。”他低声说,像在对自己说,“不是防止错误,是让错误有路可走。”
手机震了。
沈清澜发来消息:“初步思路有了。用时间轴冗余,不是空间轴。”
陈默打字:“具体?”
“别把一帧图像当完整信息。”沈清澜回得很快,“把它切成时间切片。这一帧丢了,用上一帧和下一帧的碎片拼出来。像……考古复原。”
陈默盯着屏幕。
切成时间切片。不是防止水珠遮住画面,是承认水珠永远会遮住画面。然后从遮不住的缝隙里,一点一点把真相抠出来。
他手指在屏幕上悬停了几秒。
然后回复:“试试。需要算力跟我说。”
退出聊天界面,他看见顾维钧的消息还留在通知栏。那句“技术扎实,人有骨气”像枚钉子,钉在屏幕左上角。
他锁了屏。
屏幕暗下去,映出头顶的日光灯管。灯管有两根,一根亮得发白,一根边缘发黑,光线暗黄。它们并排挂着,像某种隐喻。
李工在背后喊:“陈总,夹具图纸发您邮箱了!”
陈默应了一声。他走出玻璃房,门在身后轻轻合上,橡胶密封条发出轻微的噗声。
回到办公区时,天已经黑了。
窗户映出城市的灯火,一片一片,连成光的海洋。但办公室里没人看窗外。所有人都盯着屏幕,屏幕的光映在脸上,蓝幽幽的。
沈清澜的工位被包围了。
她坐着,三个算法工程师站着,围成半圆。白板上画满了公式,有些被划掉,划掉的线条很重,几乎要划破纸面。
“湿度补偿这里不对。”说话的是周峰,团队里最年轻的骨干。他头发乱糟糟的,眼镜滑到鼻尖,“水膜不是均匀的。它会在镜头边缘积成水珠,然后在某个瞬间滑落。那一下,画面会剧烈抖动。”
沈清澜没抬头。
她盯着自己的屏幕,手指在触摸板上滑动。画面里是模拟的水膜效果,一层半透明的灰色覆盖在图像上,像蒙了层脏玻璃。
“所以不能做均匀补偿。”她说,“得预测水珠的轨迹。它什么时候积,什么时候滑,滑落的路径是什么。”
“这不可能。”另一个工程师说,“变量太多。水流,震动,镜头倾角……”
“那就让它可能。”
沈清澜的声音不高,但很硬。她终于抬起头,眼睛里有血丝,但目光很锐。“我们不是在写完美算法。我们是在写一个……能在烂泥里爬出来的算法。”
她站起来,走到白板前。
拿起板擦,擦掉一大片公式。粉末飘起来,在灯光下像细小的灰尘。然后她画了个圆圈,代表镜头。在圆圈边缘点了个点,代表水珠。
“水珠受重力。”她说,“也受离心力——如果镜头在震动。还受表面张力和水流影响。这些力,传感器都能测。”
她在圆圈外画箭头。重力向下,离心力向外,水流沿着镜头弧度。
“把它们建模。”她转头看周峰,“用物理引擎,实时计算水珠的动力学。算它什么时候会掉,掉之前会遮住哪些像素。”
周峰愣住了。
他嘴巴微微张开,像想说什么,但没发出声音。过了两秒,他推了推眼镜。“这计算量……”
“分摊。”沈清澜打断他,“用fpga做预处理。硬件组不是刚到了一批新芯片吗?”
陈默站在人群外。
他听见了。fpga,现场可编程门阵列,专为并行计算而生。把水珠动力学这种规则清晰但计算密集的任务扔给它,正好。
他转身走向硬件组。
李工还在工位上,戴着放大镜焊电路板。电烙铁尖冒出细小的青烟,空气里有松香和焊锡的味道。
“fpga还有多少?”陈默问。
李工没抬头。“新的那批?十二片。但还没调通,驱动有问题。”
“什么问题?”
“时序对不上。”李工放下烙铁,揉了揉眼睛,“厂家的参考设计有问题。我们得自己改。”
“多久?”
“顺利的话,一晚。”李工说,“不顺利……就不知道了。”
陈默拉过一把椅子坐下。椅子是普通的办公椅,轮子有点松,坐下去时晃了一下。他伸手:“原理图给我看看。”
李工递过来平板。
屏幕上密密麻麻全是线条和符号。时钟线,数据线,控制线,像纠缠的血管。陈默放大,找到时钟树那一块。确实有问题,缓冲器的延迟参数设错了。
“这里。”他指给李工看,“差了一个纳秒。一个纳秒在四百兆赫兹的时钟下,就是半个周期。”
李工凑过来看。他看了三秒,猛地拍了下大腿。“操!还真是!”
他抢过平板,手指在屏幕上狂点。改参数,保存,重新生成配置文件。进度条开始走,从百分之零到百分之百,用了四十七秒。
然后他跳起来,冲向测试台。
陈默没跟过去。他靠在椅背上,闭上眼睛。系统推演的碎片又出现了,这次是fpga的时序波形。整齐的方波,上升沿陡峭,下降沿干净。没有毛刺,没有抖动。
成了。
他睁开眼。李工正对着测试仪挥舞拳头,仪器的绿色指示灯亮得像翡翠。
“陈总!”他喊,声音有点哑,“时序对了!”
陈默点头。他站起来,腿有点麻,针扎似的。他跺了跺脚,血液回流的感觉热辣辣的。
回到算法组时,沈清澜已经写出了第一版动力学模型。
代码在屏幕上滚动,黑色的背景,彩色的语法高亮。很长,像“predict_droplet_trajectory_under_vibration”这种,读起来拗口,但意思清晰。
周峰在跑模拟。
他按了回车。屏幕黑了一下,然后跳出实时渲染的画面。虚拟的水珠在虚拟的镜头上生成、积聚、滑动。滑落的瞬间,画面边缘的确出现了预测中的扭曲。
但还不够快。
帧率显示在角落:每秒七帧。离实时处理还差得远。
“优化。”沈清澜说,声音里听不出情绪,“把浮点运算改成定点。不需要那么高精度,够用就行。”
周峰又开始敲键盘。
这次敲得更快,更急。删掉大段代码,重写,编译。错误提示弹出来,他看都不看就关掉,继续改。
陈默走到窗边。
窗外已经完全黑了。远处写字楼的灯还亮着,一格一格的,像巨大的蜂巢。有车流在楼下经过,红色的尾灯拖成长线。
他想起父亲论文里那张图。
动态平衡。不是静止,是在扰动中维持某种稳定的轨迹。星海在挖人,是扰动。国家队给项目,是锚点。现在算法要面对的湿度、粉尘、震动,也是扰动。
而他们要做的,是在所有这些扰动里,让识别框稳稳地锁住目标。
像在飓风里穿针。
手机又震了。这次是王薇:“陈总,晚饭到了。大家吃点?”
陈默回头。
办公区里没人动。所有人都盯着屏幕,像屏幕里有什么东西会跑掉。只有沈清澜站起来,走向茶水间。她走得很慢,背有点僵。
“拿过来吧。”陈默回消息,“在工位上吃。”
王薇推着小车进来。车上摞着快餐盒,塑料盖子上凝着水汽。有炒饭,有面条,有盖浇饭。味道混在一起,闻起来有点腻。
她一份一份发。
发到周峰时,周峰没接。他盯着屏幕,眼睛一眨不眨。王薇把饭盒放在他手边,他过了五秒才反应过来,哦了一声,打开,扒了一口。
嚼得很慢,像在嚼木头。
沈清澜回来了。她手里拿着杯咖啡,黑咖啡,没加糖也没加奶。杯子是公司的马克杯,印着“默视科技”的logo,边缘有个小缺口。
她喝了一口,眉头皱了皱。
“凉了。”她说,但还是又喝了一口。
陈默接过自己的饭盒。是鱼香肉丝盖饭,肉丝切得很细,胡萝卜丝和青椒丝混在一起,酱汁把米饭染成褐色。他吃了一口,咸,甜,辣,味道很重。
他吃了半盒,吃不下了。
胃里像塞了团东西,沉甸甸的。他放下筷子,塑料筷和饭盒碰撞,发出清脆的咔哒声。
周峰忽然站起来。
他动作太猛,椅子往后滑,轮子撞在隔断板上,砰的一声。所有人都抬头看他。
“定点运算搞定了。”他说,声音有点抖,“帧率上到二十五了。”
沈清澜放下咖啡杯。她走到周峰工位,俯身看屏幕。画面里,虚拟水珠滑落的模拟已经流畅了,帧率数字稳定在二十五,偶尔跳到二十六。
“跑真实数据。”她说。
周峰点头。他导入下午那个掘进机视频,拖到水雾最浓的那一段。按下播放键。
画面还是那么暗,那么晃。水珠砸在镜头上,炸开,滑落。但这次,屏幕边缘多了个小窗口,实时显示水珠的预测轨迹。绿色的虚线,随着震动微微颤抖。
然后,就在水珠滑落的瞬间,主画面的扭曲区域被标记出来了。
红色的半透明蒙版,盖住被水膜严重影响的像素。算法没有尝试去“看透”这些像素,而是直接把它们标记为“不可信”。
然后从前后帧借信息。
借来的像素碎片像拼图,一块一块填进红色区域。有些碎片对不上,边缘有锯齿。但大部分能拼出轮廓,岩壁的轮廓,钢筋的轮廓。
虽然不是高清,但能认出来。
能认出来,就够了。
办公室里安静极了。
只有散热风扇的嗡嗡声,还有周峰因为激动而略显粗重的呼吸声。他盯着屏幕,盯了十秒,二十秒。然后他猛地转身,看向沈清澜。
沈清澜没说话。
她伸出手,在周峰肩膀上按了一下。按得很轻,但周峰整个人都僵住了,像被那一下按进了地里。
然后她转身,走回自己工位。
她没坐下,而是拉开抽屉,拿出一板巧克力。掰了两块,递给周峰一块,自己塞了一块进嘴里。嚼得很慢,像在品尝什么珍贵的东西。
陈默感到胸口有什么东西松开了。
不是完全的轻松,是绷紧的弦稍微松了一扣。他深吸口气,空气里有咖啡的苦,有快餐的油,有电子设备发热的塑料味。
他走回自己办公室。
关上门,外面的声音被隔开,只剩模糊的背景音。他坐在椅子上,椅子因为他的重量发出轻微的吱呀。
打开邮箱。
收件箱里又堆了十几封新邮件。有供应商的报价更新,有客户的咨询,有行业会议的邀请函。他全选,标记为未读。
然后点开和顾维钧的聊天窗口。
打字:“动力学模型有突破了。用fpga做实时水珠轨迹预测。”
发送。
过了大概三分钟,顾维钧回了两个字:“不错。”
就两个字,没有表情,没有标点。但陈默盯着那两个字,看了很久。
他知道顾维钧的风格。能说“不错”,已经是很好的评价。
窗外有车按喇叭。声音很远,闷闷的,像从水底传上来。陈默看向玻璃,玻璃映出他自己的脸,还有身后办公室的景象。
沈清澜已经回到白板前,又在画新的东西。
周峰和其他人围着她,指指点点,争论着什么。声音透过门缝传进来,听不清内容,但能听出那股劲。
那股非要把它做成的劲。
陈默靠在椅背上,闭上眼睛。
系统推演没有出现。这次没有碎片,没有画面,只有一种感觉。像站在黑暗的隧道里,远处有光,光还很远,但你知道它在那个方向。
而你已经迈开了腿。
他睁开眼,重新看向屏幕。顾维钧的消息还停在“不错”两个字上。他想了想,又打字:“但粉尘模拟还没开始。震动台也要后天才能搭好。”
这次顾维钧回得快了:“一步步来。赵主任要的不是神仙,是能解决问题的工程师。”
陈默盯着这句话。
能解决问题的工程师。不是发明完美技术的神,是挽起袖子,跳进泥坑,一点一点把问题啃下来的人。
他忽然笑了。
笑得很轻,几乎没发出声音。但嘴角扬起来了,脸上的肌肉松弛了。他感到眼眶有点热,用力眨了眨。
然后他站起来,推门出去。
沈清澜听见脚步声,转头看他。她脸上有倦色,但眼睛很亮,像擦了把雪。
“粉尘模型我有个想法。”陈默说,“不把它当噪声,把它当介质。”
沈清澜挑眉。
“光在粉尘里会散射。”陈默走到白板前,拿起笔,“散射不是完全随机。它遵循某种分布。如果我们能建模这个分布……”
“就能从散射光里反推原始图像。”沈清澜接上。她语速很快,像子弹射出枪膛,“像ct。用多个角度的散射数据,重建。”
她抢过笔,在粉尘模拟区画了个示意图。光源,粉尘云,摄像头。光线不是直线,是弯弯曲曲的路径,像蛛网。
“但这需要多摄像头阵列。”周峰插嘴,“掘进机上没那么多位置。”
“用时间代替空间。”陈默说,“摄像头在震动,位置在变。每一帧,摄像头都在新的位置。把这些位置连起来,就是虚拟的阵列。”
办公室里又安静了。
这次安静得更久。所有人都盯着白板,盯着那些弯曲的光路,盯着那个用时间换空间的想法。
沈清澜第一个动。
她回到工位,开始敲代码。不是写完整程序,是写验证脚本。一百行,两百行,三百行。屏幕上的字符瀑布一样往下滚。
然后她按了运行。
进度条走得很慢。百分之十,百分之二十。机器风扇转得更响了,发出呜呜的声音,像在抗议。
百分之百。
结果跳出来。是一张对比图。左边是原始粉尘图像,灰蒙蒙一片。右边是重建后的,虽然还有噪点,但岩壁的纹理已经能看见了。
能看见纹理,就能做特征匹配。
就能锁定目标。
周峰张大了嘴。他看看屏幕,看看沈清澜,看看陈默。然后他猛地转身,冲向自己电脑。“我来写正式版!”
声音因为激动而破了音。
陈默和沈清澜对视一眼。
沈清澜嘴角弯了一下。很浅的弧度,几乎看不见,但陈默看见了。他也笑了笑,这次笑出了声,很短促,像叹息。
然后他看向窗外。
天还是黑的,但远处天际线那里,开始透出一点深蓝。很淡,像水彩画的第一层底色。夜晚正在过去,早晨正在到来。
而他们的算法,也正在从混乱的极端环境里,一点一点长出自己的眼睛。
不是完美的眼睛。是会在水雾里模糊、在粉尘里迷路、在震动里发抖的眼睛。但它会认路。会在迷路后找回来,会在模糊后努力看清,会在发抖后重新站稳。
这就够了。
陈默走回自己办公室。他重新打开邮箱,点开那封“深地项目技术攻坚”的邮件。看了一遍,又看了一遍。
然后他在末尾加了一句。
“我们不是在创造奇迹。我们是在用所有已知的工具,去够那个未知的目标。而工具不够时,我们就发明新的工具。”
他敲下回车。
句子发送出去,成了这封邮件的一部分,也成了这个夜晚的一部分。窗外,深蓝正在变浅,变成鱼肚白。
实验室里,振动台的钢架在灯光下泛着冷光。
粉尘模拟器的玻璃房静静立着,等待被充满。
而算法,正在进化。