第三章 系统总体架构:四层职责划分
好,咱们今天聊聊超声系统的骨架——总体架构。
很多人一上来就扎进算法细节,结果发现代码越写越乱。我早期也犯过这个错。后来才明白,架构设计才是真正的「磨刀不误砍柴工」。
超声系统,说白了就是一条数据流水线。从探头采集信号,到最终在屏幕上显示图像,中间要经过好几道关卡。我习惯把这套体系拆成四层:前端采集层、后端处理层、应用层、通信层。每一层各司其职,互不干扰。
3.1 前端采集层:信号的起点
这一层是系统最「硬」的部分。它直接跟硬件打交道,负责把声波变成数字信号。
具体职责包括:
- 发射/接收控制:控制探头阵元发射超声波,并接收回波信号
- 模拟前端处理:包括TGC(时间增益补偿)、滤波、放大等
- ADC采样:把模拟信号转成数字信号,采样率通常在40MHz以上
- 波束合成:对多通道数据进行延时叠加,形成一条扫描线
关键点:前端采集层是实时性要求最高的地方。我曾经在一个项目里,因为ADC的时钟抖动没处理好,导致图像出现条纹噪声。排查了整整三天才找到原因——嗯,从那以后我对时钟树设计格外敏感。
这一层的输出是什么?是经过波束合成后的射频数据(RF Data)。说白了,就是一条条扫描线的原始信号。
3.2 后端处理层:从信号到图像
后端处理层,负责把原始信号变成人眼能看懂的图像。这一层是算法的天下。
主要模块包括:
- 包络检测:从RF信号中提取幅度信息,去掉载波分量
- 对数压缩:把动态范围从100dB以上压缩到人眼可识别的范围
- 数字滤波:去噪、增强边缘、平滑等
- 扫描变换:把极坐标下的扫描线数据,转换成直角坐标的像素矩阵
- 图像后处理:伽马校正、伪彩映射、空间复合等
我的经验:扫描变换这一步最容易出性能瓶颈。你想想看,每秒钟要处理30帧图像,每帧可能有几十万像素点。如果算法没优化好,帧率直接掉到个位数。我建议用查表法代替实时计算,能省下不少CPU开销。
后端处理层的输出,就是最终要显示的图像帧数据。通常是8位或16位的灰度图,或者RGB彩图。
3.3 应用层:用户看到的和操作的
应用层是离用户最近的一层。它负责两件事:显示图像、响应用户操作。
具体包括:
- 图像显示:把后端送来的图像帧渲染到屏幕上
- 测量与标注:距离、面积、血流速度等测量功能
- 参数调节:深度、增益、焦点位置等用户可调参数
- 报告生成:生成图文报告,支持打印和导出
- 病人管理:录入、查询、编辑病人信息
注意:应用层最容易出现「功能蔓延」的问题。我曾经见过一个团队,在应用层里塞了太多业务逻辑,结果底层一改接口,上层全崩。记住:应用层只做界面展示和交互调度,不要越界去处理数据。
这一层通常跑在操作系统上,比如Linux、Android或者Windows。开发语言以C++、Qt、C#为主。
3.4 通信层:连接各层的纽带
通信层,说白了就是各层之间的「高速公路」。它不负责具体业务,只负责把数据从一个模块搬到另一个模块。
职责划分:
| 通信场景 | 常用方式 | 关键要求 |
|---|---|---|
| 前端→后端 | DMA、共享内存 | 低延迟、高吞吐 |
| 后端→应用 | 消息队列、回调函数 | 实时性、帧同步 |
| 应用→前端 | 命令通道、控制总线 | 可靠性、优先级 |
| 系统外部 | TCP/IP、DICOM、USB | 标准化、兼容性 |
避坑指南:我曾经在一个项目里,用全局变量来传递图像数据。结果多线程竞争导致图像撕裂,画面一半是上一帧一半是下一帧。后来改成环形缓冲区加信号量,问题才解决。所以——共享数据一定要加锁,或者用无锁队列。
通信层的设计原则,我总结了三句话:
- 接口要稳定:一旦定下来,尽量不改。否则牵一发而动全身。
- 协议要简洁:别搞复杂的序列化,超声数据量大,能传二进制就别用JSON。
- 要有监控:通信链路的状态、延迟、丢包率,都要能实时看到。不然出了问题你都不知道是哪层在卡。
3.5 四层架构的协作流程
咱们串起来看一遍完整流程:
- 医生按下「开始扫描」按钮(应用层)
- 应用层通过通信层下发命令给前端采集层
- 前端开始发射超声波,接收回波,做波束合成
- 原始RF数据通过DMA传到后端处理层
- 后端做包络检测、对数压缩、扫描变换,生成图像帧
- 图像帧通过共享内存送到应用层
- 应用层把图像渲染到屏幕上
- 医生看到图像,调整深度或增益(回到步骤1)
整个过程,从探头到屏幕,延迟不能超过100毫秒。否则医生会感觉「卡顿」。你想想看,做心脏检查时,如果图像跟不上心跳,那还怎么诊断?
我的建议:在架构设计阶段,就要明确每一层的接口协议。我习惯先写一个「接口定义文档」,把数据结构、函数签名、通信协议都定死。这样各层团队可以并行开发,最后联调时少吵架。
好了,这一章的核心就这些。四层架构听起来简单,但真正落地时,每一层都有不少坑。后面几章咱们会逐层深入,把每个模块的细节掰开揉碎了讲。