信息速览
胎心音是一个在物理上先天吃亏的测量对象。心脏瓣膜开合产生的振动要穿过羊水、子宫壁、脂肪与皮肤才能到达腹壁,能量在这一路上衰减得厉害,而同一块腹壁上还叠着母体心音、肠鸣与呼吸肌运动、胎盘血流湍流、胎动,以及房间里的环境噪声。真正能清楚看到第一心音与第二心音成对出现的片段,往往只占整段录音的一小部分。
2010 年,那不勒斯的一组研究者在一家私人诊所里用便携心音设备录下了 26 段这样的信号。他们的目的不是做一份评测基准,而是回答一个更靠前的问题:真实的胎儿与母体心音,波形到底长什么样。当时的文献在这一点上写得含糊,而要把胎心音模拟器做对,就必须先有这批真实录音当参照。2015 年 12 月,这批原始录音以 Fetal PCG Database 的名字单独发布在 PhysioNet 上。
它的规格按今天的标准并不起眼:26 段、单通道、8 位、333 赫兹、没有标注、全部文件加起来不到 20 MB。它的价值也不在规模上,而在于它是那套合成胎心音数据的真实底座——想判断一条合成波形像不像人,得先有一批真人的录音摆在旁边。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | Fetal PCG Database(FPCGDB) |
| 数据性质 | 真实录音,非合成 |
| 采集机构 | 那不勒斯费德里科二世大学(页内两种系名并列:作者栏写生物医学工程系,合作者栏写电气工程与信息技术系) |
| 提交者 | Mariano Ruffo;合作者 Mario Cesarelli、Maria Romano、Paolo Bifulco |
| 采集时间与地点 | 2010 年,意大利那不勒斯一家私人诊所 |
| 采集设备 | Pentavox 公司的 Fetaphon Monitoring System 便携心音记录仪 |
| 受试者 | 26 名健康孕妇,年龄 25 至 35 岁,单胎生理妊娠 |
| 孕周范围 | 31 至 40 周(文件名中实际出现 31、34 至 40 周) |
| 记录数 | 26 段,每人一段 |
| 单段时长 | 平均 20 分钟;按采样点折算 19.97 至 20.53 分钟 |
| 总时长 | 约 521.6 分钟,合 8.69 小时 |
| 通道数 | 1 |
| 采样率与位深 | 333 Hz,8 位(官方写 Format 80) |
| 幅度标度 | 无量纲归一化值,头文件增益 0.005 |
| 标注 | 无任何标注文件 |
| 文件数 | 52 个数据与头文件,加清单与校验和 |
| 体积 | 解压后 19.9 MB,ZIP 同为 19.9 MB |
| 许可与 DOI | ODC-BY 1.0;10.13026/C2PD5B |
| 上线时间 | 2015 年 12 月 16 日,版本 1.0.0 |
§1 它要解决的具体麻烦
1.1 做模拟器之前,得先知道真实波形长什么样
胎心音研究在 2010 年前后遇到一个很具体的困难:想测试胎心率提取算法,就需要大量带真值的录音;可真实录音的真值要靠专家逐拍听辨,成本高、一致性差;于是大家转向模拟器造数据。但模拟器的每一个参数——S1 与 S2 的时长、幅度比、间隔、噪声的频谱形状——都必须有真实录音作依据,否则造出来的信号只是一段听起来像心跳的声音,算法在上面调好了也迁移不到真人。
同组 2012 年那篇论文把这件事写得很直白:在开发模拟软件之前,先做了一次数据采集预研,专门用来确认胎儿与母体心音的波形特征,理由是现有文献在这个问题上不够严谨。这批预研录音就是后来的 FPCGDB。它不是为了被当成基准而录的,而是为了给一个建模任务提供原始素材;这一点决定了它日后所有的形态特征——小、无标注、单通道、按孕妇编号平铺。
| 需求 | 常规做法 | 卡在哪 | 这批录音的位置 |
|---|---|---|---|
| 拿到真实 S1/S2 波形 | 查文献里的示意图 | 图是重绘的,参数不可回溯 | 原始录音可直接重测 |
| 给模拟器定参数 | 凭经验设 | 设出来的信号不像真人 | 官方称用它确认波形特征 |
| 测胎心率算法 | 用合成信号 | 合成信号的噪声过于理想 | 可作为真实侧的对照 |
| 建公开可引用的底稿 | 各实验室自留 | 数据不公开、无法复现 | 2015 年起公开在 PhysioNet |
1.2 三条常见的错误期待
第一条,期待它是胎心电。 名字里的 PCG 指 phonocardiography,声学的图,不是心电图。它记录的是瓣膜开合传到腹壁的机械振动,采的是声音,传感器是心音探头,不是电极。拿它去验证 QRS 检测算法会立刻发现没有 QRS 可找。
第二条,期待它带胎心率真值。 目录里只有数据文件与头文件,没有任何标注文件,头文件里也没有注释行。官方提到可以用听辨认出 S1 与 S2,那是在描述信号质量,不是在承诺标注。所有以「有胎心率标签」为前提的使用方式,第一步就会卡住。
第三条,期待它够大、能做训练集。 26 段、8.69 小时、单通道、8 位。这个体量做小规模自监督预训练也许勉强,做监督学习完全不够;它更像一本波形样册,而不是一座语料库。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 看真实胎儿心音的原始波形 | 26 段腹部录音,覆盖孕 31 至 40 周 | 够,这正是它的用途 |
| 校准心音模拟器的 S1/S2 参数 | 真实波形与真实噪声的混合样本 | 够,官方就是这么用的 |
| 测胎心率提取算法的准确率 | 无真值,需自行标注 | 不够,得自己补标注 |
| 研究母体心音与胎心音的叠加 | 混合信号在,但未分源 | 部分够,分离要靠算法 |
| 做深度学习训练 | 8.69 小时单通道 | 不够,量级差一到两个数量级 |
| 研究病理妊娠的心音特征 | 全部为健康单胎 | 不够,结构上没有 |
| 做教学演示 | 真实波形、体积极小、免注册 | 够,几乎零门槛 |
| 复现 2012 年论文的模拟器 | 论文的参照数据即此库 | 够,这是唯一公开的原始素材 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你写了一个基于包络的胎心率提取器,只在自采的几段上试过 | 26 段真实录音,同一设备同一流程录成,条件相对一致 | 先在其中几段上人工点出 S1 位置,建立小规模真值,再报数 |
| 你在用 simfpcgdb 那套合成信号调参,怀疑模拟得不像 | 提供真实侧的对照片段,可逐段比对 S1/S2 的形态与噪声底色 | 取同孕周的几段,把真实与合成的波形并排画出来看差异 |
| 你要向评审说明算法的输入是真实录音而非仿真 | 公开可引用的真实录音,带 DOI 与固定许可 | 在方法节写明用的是 26 段中的哪几段、如何划分 |
| 你在做心音分割,缺 S1/S2 边界标签 | 波形本身可用,标签需自建 | 按 §4.2 的案例先标一段,跑通流程再扩量 |
| 你在教生物医学信号处理,需要一个真实腹部录音样本 | 19.9 MB 能整个拷给学生,无需申请 | 用 §9.2 的流程读入并画包络,课上演示十分钟够用 |
| 你在评估设备差异对胎心音的影响 | 只有一种设备、一个诊所 | 不够,需另找多设备数据做对照 |
1.5 一句话判断
它是一块原始木料,不是一件成品家具:价值在于纹理是真的,而不在于它已经被刨平、上漆、标好了尺寸。
1.6 不适合谁:四条边界
不适合要标注的人。 没有胎心率、没有 S1/S2 时间戳、没有孕产妇病史字段。任何以「标签已就绪」为前提的流水线,在它身上必须先从人工标注开始。
不适合要规模的人。 8.69 小时单通道,且全部来自健康单胎。把它当作训练集,模型的容量会被数据量而不是被任务难度限制住。
不适合要病理谱的人。 26 名孕妇全部健康,孕 31 至 40 周,没有早产、没有双胎、没有妊娠合并症。想研究异常胎心音的形态,它一段都给不了。
不适合要做物理声学定量的人。 单位是无量纲的归一化值,增益 0.005 是为了显示刻度而不是物理标定。任何以分贝、帕斯卡为单位的结论都无法落在它上面。
§2 数据构成与规格
2.1 一个平铺目录与文件名里的三段信息
这个库没有子目录。26 个记录全部躺在根目录下,每个记录一对文件:.dat 装二进制样本,.hea 装两行纯文本头信息。身份信息不在头文件里,而在文件名里,被下划线切成四段:前缀 fetal_PCG、孕妇编号 pNN、孕周标记 GW、两位孕周数。
| 位置 | 形态 | 取值 | 含义 |
|---|---|---|---|
| 目录 | 无分层 | 根目录 | 52 个数据与头文件全部平铺 |
| 文件名第 1 段 | fetal_PCG |
固定 | 标识这是胎儿心音图记录 |
| 文件名第 2 段 | pNN |
p01 至 p26 |
孕妇编号,每人只出现一次 |
| 文件名第 3 段 | GW |
固定 | 孕周的标记前缀 |
| 文件名第 4 段 | 两位数字 | 31 至 40 | 录制时的孕周 |
| 扩展名 | .hea / .dat |
两种 | 头文件与二进制样本 |
| 根目录另外两个文件 | RECORDS / SHA256SUMS.txt |
520 B / 4.6 KB | 记录清单与校验和 |
这种命名法的好处是身份信息一眼可见,缺点是信息全在字符串里——任何按目录结构组织的工具都会在这里失效。要按孕周分组,就必须先解析文件名;头文件里没有任何字段能替代它。
2.2 字段与记录的完整字典
信息分三处:文件名、头文件首行、头文件第二行。头文件只有两行,没有任何注释行,这与多数 PhysioNet 波形库不同——那些库往往在头文件末尾堆十几行 # 注释,把采集条件、受试信息、设备参数全写进去;这里一行都没有。
| 信息项 | 所在位置 | 取值形态 | 含义 |
|---|---|---|---|
| 记录名 | .hea 首行第 1 列 |
与文件名相同 | 记录标识,含孕妇编号与孕周 |
| 通道数 | .hea 首行第 2 列 |
1 |
单通道 |
| 采样率 | .hea 首行第 3 列 |
333 |
赫兹 |
| 采样点数 | .hea 首行第 4 列 |
399000 至 410001 | 除以 333 得秒数 |
| 数据文件名 | .hea 第二行第 1 列 |
同名 .dat |
指向二进制文件 |
| 存储格式 | .hea 第二行第 2 列 |
16 |
WFDB 格式码 16 |
| 增益 | .hea 第二行第 3 列 |
0.005 |
每单位对应的显示标度 |
| 位分辨率 | .hea 第二行第 4 列 |
8 |
8 位 |
| ADC 零点 | .hea 第二行第 5 列 |
128 |
8 位量化的中点 |
| 首样本值 | .hea 第二行第 6 列 |
各文件不同 | 首点原始整数 |
| 校验和 | .hea 第二行第 7 列 |
各文件不同 | WFDB 的校验字段 |
| 块大小 | .hea 第二行第 8 列 |
0 |
不分块 |
| 信号名 | .hea 第二行第 9 列 |
PCG |
唯一的通道名 |
| 单位 | 无字段 | 无量纲 | 官方称设备输出已归一化 |
| 孕周 | 仅文件名 | 31 至 40 | 头文件里没有对应字段 |
| 孕妇编号 | 仅文件名 | p01 至 p26 | 头文件里没有对应字段 |
| 年龄、身高、体重 | 无 | 无 | 官方只给总体范围 |
| 标注文件 | 无 | 无 | 目录里不存在任何标注扩展名 |
这张表最需要注意的是最后三行。孕周与编号只存在于文件名,年龄只有「25 至 35 岁」这一个总体范围、没有逐人取值,标注则完全不存在。想在分析里用到这些变量,只能自己从文件名解析孕周,其余变量无从获得。
2.3 一段录音的完整解剖
以 fetal_PCG_p02_GW_31 为例。它的头文件只有两行,全文如下:
fetal_PCG_p02_GW_31 1 333 402000
fetal_PCG_p02_GW_31.dat 16 0.005 8 128 124 25063 0 PCG
第一行说明这一段叫 fetal_PCG_p02_GW_31、单通道、333 赫兹、402000 个采样点。402000 除以 333 得 1207.2 秒,也就是 20.12 分钟。第二行是通道描述:数据在同名 .dat 里,格式码 16,增益 0.005,位分辨率 8,零点 128,首样本 124,校验和 25063,不分块,名字叫 PCG。
用标准工具读出来是这样:
import wfdb
import numpy as np
rec = wfdb.rdrecord("fetal_PCG_p02_GW_31", physical=True)
print(rec.fs, rec.sig_len, rec.n_sig, rec.sig_name)
#-- 333 402000 1 ['PCG']
print(rec.p_signal.shape, rec.units[0], rec.adc_gain[0])
#-- (402000, 1) 'NU' 0.005
x = rec.p_signal[:, 0]
print(float(np.min(x)), float(np.max(x)), round(len(x) / rec.fs / 60, 2))
#-- 约 -0.64 0.635 20.12 分钟量级
读出后有一个细节值得记住:physical=True 会把整数乘上增益再减去基线,得到的浮点数在正负零点几之间来回。这个量级完全是 0.005 这个显示标度造出来的,不代表任何物理单位。设 physical=False 拿原始整数,范围就在 0 到 255 之间,因为量化是 8 位、零点 128。
2.4 四种规模口径
同一个库可以有四种数法,四种都对,只是回答的问题不同:
| 口径 | 数值 | 单位是什么 | 什么时候用它 |
|---|---|---|---|
| 记录数 | 26 | 段 | 说「有几个人、几段」时 |
| 采样点 | 10422007 | 点 | 算存储、算训练步数时 |
| 时长 | 521.6 分钟 / 8.69 小时 | 分钟与小时 | 与其它库比体量时 |
| 体积 | 19.9 MB | 兆字节 | 判断能不能一次下完时 |
四个数之间可以互相验算:10422007 除以 333 得 31297 秒,即 521.6 分钟;52 个数据与头文件合计约 19.9 MB,其中数据文件每个约 780 KB,正好等于采样点数乘 2 字节再除 1024。
2.5 与同类资源的字段差异
| 对比项 | FPCGDB | simfpcgdb(同组合成) | IIScFHSDB(印度胎心音) | 一般腹部 fECG 库 |
|---|---|---|---|---|
| 数据性质 | 真实录音 | 合成 | 真实录音 | 真实电生理 |
| 模态 | 心音 | 心音 | 心音 | 心电 |
| 通道数 | 1 | 单通道 | 单通道 | 通常 4 至 8 |
| 采样率 | 333 Hz | 1 kHz | 2 kHz | 250 Hz 至 1 kHz |
| 位深 | 8 位 | 16 位 | 未在页内强调 | 16 位 |
| 单段时长 | 约 20 分钟 | 分段生成 | 平均数分钟 | 数分钟 |
| 标注 | 无 | 文件名带 SNR | 带临床信息 | 常带 QRS |
| 单位 | 无量纲 | 无量纲 | 视设备而定 | 毫伏 |
第一列与第二列的对照最能说明这个库的定位:同一组人、同一套物理模型、同一种模态,一边是真人录音,一边是模拟输出,采样率与位深还都不一样。把它们当作同一份数据的不同版本是错的,它们是链条上的两环。
§3 它记录的是什么:腹部表面的一次听诊
3.1 一声心音怎么变成一串整数
整条链路很短。心音探头贴在腹壁上,把空气或皮肤表面的微小压力变化转成电压;前置放大把这点电压抬到模数转换器能分辨的量级;转换器以 333 赫兹的节拍每分钟取两万次左右的样本,每个样本压成 8 位整数;最后按孕妇编号与孕周命名落盘。中间没有滤波环节的说明,没有增益校准记录,也没有设备固件的版本信息。
| 环节 | 做了什么 | 留下的痕迹 | 对使用者的影响 |
|---|---|---|---|
| 拾音 | 探头把腹壁振动转成电压 | 只有一条波形 | 无法区分声音来自胎儿还是母体 |
| 放大 | 抬到转换器可分辨的量级 | 增益未在页内给出物理值 | 绝对幅度无从还原 |
| 采样 | 333 Hz | 头文件第 3 列 | 奈奎斯特上限约 166 Hz |
| 量化 | 8 位,零点 128 | 头文件第 4、5 列 | 256 个台阶,细微信号会被压平 |
| 命名 | 孕妇编号加孕周 | 文件名 | 头文件里没有对应字段 |
333 赫兹这个采样率决定了能看到的频率上限约 166 赫兹。心音的主要能量集中在几十赫兹到一百多赫兹,这个采样率刚好覆盖得住;但想把心音的高频成分拿来做更细的形态分析,就到此为止了。同一组后来那套合成数据用的是 1 千赫兹,正好把这个缺口补上。
3.2 噪声不是一种,是一层一层叠上去的
官方在数据说明里列了噪声的来源,措辞很朴素:母体心音造成的振动、母体器官的声音(消化、呼吸肌运动、胎盘血流湍流)、胎动、周围环境。这份清单的价值在于它把「噪声」拆成了有物理来源的几类,而不是笼统的一个「背景噪声」参数。这一点在建模时影响很大:加性白噪声可以随便加,母体心音的节律性干扰不能。
把这些来源逐个摊开,能看清哪几种有可能被事后处理掉。母体心音是母体瓣膜开合的振动经腹壁传导过来的,与胎心音处在同一频段,表现为规律的双击,几乎无法靠滤波分开;消化与肠鸣是胃肠蠕动和气体移动造成的不规则低频声,没有固定节律,也难以用参数描述;呼吸肌运动带来的是缓慢的基线起伏,用高通就能压掉大半;胎盘血流的湍流是持续的宽带嘶声,频段与目标信号重合,压不掉;胎动是突发的宽带冲击,可以靠瞬态检测识别出一部分;环境噪声取决于场地,一旦录进来就已经混在信号里,事后再想剔除只能靠谱减,而谱减会连带削掉信号本身。
这六类里只有呼吸起伏与部分胎动是真的可以被事后处理掉的,其余四类都与目标信号争夺同一段频谱。这也解释了为什么胎心音的分割比胎心电更难:胎心电里母体成分与胎儿成分在时间上可分辨,模板减除就能压掉大半;胎心音里母体的每一次瓣膜开合都和胎儿的心音撞在同一个频段上,压掉母体的同时必然带走胎儿的一部分。
3.3 单通道意味着什么
单通道带来的第一个限制是没有空间信息。多导联可以用空间滤波或盲源分离,把来自不同方向的成分分开;一路信号做不到这一点,分离只能落在时频域。第二个限制是没有通道间的一致性校验:临床上探头松动、贴合不良会立刻在另一路信号上显出异常,这里只有一个探头,坏了就是整段不可用,也没有旁证。
还有一个容易被忽略的差异:临床听诊会在腹部四个象限分别听,找出胎心音最清楚的位置;这份数据每个孕妇只对应一个听诊位置,库内没有记录那个位置在哪里。§4.2 的案例就落在这样的单通道录音上——波形里既有胎心也有母体成分,而唯一能用来判断哪一簇峰属于胎儿的信息,是节律的规律性。
反过来说,单通道也降低了使用门槛:不需要考虑通道顺序、不需要对齐、不需要处理缺失通道,一条曲线读进来就能画。做教学演示时这是优点,做方法研究时这是硬约束。
3.4 8 位与 0.005:一条被放大的相对刻度
8 位量化意味着整段录音被压进 256 个整数台阶。零点定在 128,实际样本就落在这个中点两侧。官方给出的增益 0.005 有一句明确解释:为了让 WAVE 显示刻度与之前那套模拟 PCG 数据保持一致。换句话说,这个增益是为显示服务的,不是为物理标定服务的。
把这四个字段逐个读一遍,会发现它们描述的全是显示层面的约定,而不是物理量。位分辨率 8 表示整段录音被压进 256 个台阶,这是量化精度,不是有效位数——扣掉噪声之后真正能用的级别只会更低;ADC 零点 128 是整数序列的中点,不是零声压的对应点;增益 0.005 是显示标度的换算系数,不是探头灵敏度;单位一栏干脆没有值,官方用一句话交代设备输出已经归一化。
合起来说明一件事:这个库里的数值只在库内可比。同一段录音内部比较 S1 与 S2 的幅度比是合法的;跨录音比较绝对幅度就要小心,因为不同孕妇的腹壁厚度、探头贴合程度都会改变整体电平,而库内没有任何字段能把这些因素剥出来。
3.5 它记录不了的生理
| 想知道的量 | 这个库能给吗 | 原因 |
|---|---|---|
| 胎心率的逐拍序列 | 不能 | 无标注,需自行从波形检测 |
| S1 与 S2 的边界时刻 | 不能 | 同上 |
| 母体心率的同步记录 | 不能 | 无第二通道,也未单独记录 |
| 孕妇体重、腹壁厚度 | 不能 | 只有年龄范围,无个体形态数据 |
| 胎位与胎盘位置 | 不能 | 未记录,也未随数据发布 |
| 宫缩活动 | 不能 | 未记录,录音也不在产程中 |
| 新生儿结局 | 不能 | 全部为生理妊娠,未随访 |
这张表最后一行常被忽略。因为受试者全部是健康单胎、录音在孕晚期而非产程,所以库内不存在任何与不良结局相关的样本。想用它做「胎心音能否预测胎儿窘迫」这类研究,连阴性样本都凑不出来。
§4 它最独特的东西:为模拟器校准的原始录音
4.1 为什么「先录音、后造模拟器」这个顺序值得记住
多数合成数据集是先有模拟器、后用数据检验模拟器像不像;这一组人的顺序是反的:先在 2010 年录下真实信号,把胎儿与母体心音的波形特征摸清楚,再据此写模拟器。这个顺序决定了两件事——模拟器的参数有出处,真实录音也留下来成了公开资产。
这条链上有四个节点。2010 年先有 26 段腹部录音,也就是本库;2012 年这批录音被抽象成参数模型,写成模拟器与配套论文;2015 年录音本身被公开,从课题组内部素材变成可引用的资源;同一时期模拟器批量生成合成信号,形成另一份独立发布的数据。
四个节点里,本库占的是第一格。这意味着它不是「模拟数据的验证集」,而是「模拟数据的原料」——两者的差别在于,验证集要覆盖模拟器可能出错的全部情形,原料只要足够真实、足够典型就行。用验证集的标准去要求它,会得出病例谱不全的结论;用原料的标准去看它,26 段真实录音已经够用。
4.2 案例:p02 那段 31 周的录音
选 fetal_PCG_p02_GW_31 作贯穿案例,理由有三条。第一,它落在孕周范围的最下端,31 周是库内最早的孕周,拿来讨论「孕周边界」最直观。第二,它的采样点数是 402000,比常见的 400000 略多,正好用来说明这个库的时长并不整齐。第三,它的首样本值是 124,离零点 128 只差四个台阶,说明这段录音起始处信号很弱,适合演示「为什么不能只看波形开头」。
这一段的规模参数如下:
| 参数 | 值 | 说明 |
|---|---|---|
| 记录名 | fetal_PCG_p02_GW_31 | 含孕妇编号与孕周 |
| 采样点数 | 402000 | 除以 333 得 1207.2 秒 |
| 时长 | 20.12 分钟 | 略高于 20 分钟的均值 |
| 通道 | 1 | 单通道 PCG |
| 格式码与位深 | 16 与 8 | 存储 16 位码、分辨率 8 位 |
| 首样本 | 124 | 零点 128 偏下四个台阶 |
把它读进来,先看包络,再看自相关的峰间距,是这个库最省事的一条入门路径:
import wfdb
import numpy as np
from scipy.signal import hilbert, butter, filtfilt
rec = wfdb.rdrecord("fetal_PCG_p02_GW_31", physical=True)
x = rec.p_signal[:, 0]
fs = rec.fs
b, a = butter(4, [20 / (fs / 2), 120 / (fs / 2)], btype="band")
env = np.abs(hilbert(filtfilt(b, a, x)))
print(len(x), round(len(x) / fs, 2), float(env.max()))
#-- 402000 1207.21 约 0.3 量级
seg = env[: fs * 60]
ac = np.correlate(seg - seg.mean(), seg - seg.mean(), mode="full")[len(seg) - 1:]
lag = np.argmax(ac[fs // 3: fs]) + fs // 3
print(round(60 * fs / lag, 1))
#-- 一分钟后自相关峰的位置,折算成每分钟次数,量级在 110 到 160 之间
这段代码的输出不是胎心率的准确值,只是一个量级判断。原因是包络里混着母体心音的节律,自相关峰可能落在母体周期上。要用它做正式测量,得先分段选出胎儿成分占优的窗口——这正是没有标注带来的第一道麻烦。
4.3 从录音里被搬进模拟器的四样东西
| 被搬走的东西 | 在真实录音里怎么看出来 | 在模拟数据里变成什么 |
|---|---|---|
| S1 与 S2 的成对结构 | 噪声小的片段里两个尖峰成对出现 | 一帧一帧的 S1、S2 小波 |
| 心音波形的基本形态 | 单次搏动的上升、持续、衰减 | 参数化的波形模板 |
| 噪声的构成 | 母体心音、器官声、胎动、环境叠加 | 多路噪声相加,另加白噪声 |
| 噪声的量级范围 | 不同段落的信噪比差别很大 | 按 SNR 档位批量生成 |
第三行最能说明这批录音的作用。合成库的噪声不是随便加的白噪,而是按「母体心音加器官声加胎动加环境加高斯白噪声」这个配方叠出来的——这个配方正是从真实录音的听感里总结出来的。没有真实录音当参照,配方里的每一项都没有依据。
4.4 与同组模拟库的分工
| 对比项 | FPCGDB | simfpcgdb |
|---|---|---|
| 数据来源 | 真实录音 | 模拟器输出 |
| 采样率 | 333 Hz | 1 kHz |
| 位深 | 8 位 | 16 位 |
| 信噪比 | 未给出,随录音而变 | 文件名标注,负 26.7 至负 4.4 分贝 |
| 单段时长 | 约 20 分钟 | 按帧生成 |
| 标注 | 无 | 文件名带 SNR |
| 体积 | 19.9 MB | 视生成量而定 |
| DOI | 10.13026/C2PD5B | 10.13026/C2GW25 |
两列合起来才是一套完整的方法论:先用真实录音定形态,再用模拟器批量造带真值的样本,然后在合成数据上把算法调稳,最后回到真实录音上确认没有跑偏。只用左边,样本太少、无法统计;只用右边,结论只对模拟器成立。
4.5 边界条件:什么时候它不再适用
| 条件 | 是否适用 | 判断依据 |
|---|---|---|
| 观察真实 S1/S2 形态 | 适用 | 这是采集目的 |
| 校准合成心音的波形参数 | 适用 | 官方即如此使用 |
| 论证算法在真实录音上的检出率 | 受限适用 | 需自建真值,样本仅 26 段 |
| 训练深度网络 | 不适用 | 8.69 小时单通道,量级不够 |
| 研究病理妊娠 | 不适用 | 全部健康单胎 |
| 研究早产或孕中期 | 不适用 | 只覆盖孕 31 至 40 周 |
| 做声压级定量 | 不适用 | 单位无量纲,增益为显示标度 |
| 研究多通道阵列 | 不适用 | 单通道 |
§5 怎么拿到:19.9 MB 的平铺目录
5.1 目录与体积
| 路径 | 内容 | 量级 |
|---|---|---|
/files/fpcgdb/1.0.0/RECORDS |
26 行记录名 | 520 字节 |
/files/fpcgdb/1.0.0/SHA256SUMS.txt |
52 个文件的校验和,另含 RECORDS 一行 | 4.6 KB |
fetal_PCG_pNN_GW_NN.dat |
单通道二进制样本 | 每个约 780 KB |
fetal_PCG_pNN_GW_NN.hea |
两行头文件 | 每个 89 至 91 字节 |
| 整包 ZIP | 全部内容 | 19.9 MB |
这个体量小到可以直接进内存:26 段、每段四十万点左右,用 64 位浮点展开也不过八十多兆。全量下载不会成为负担,因此不必像几十 GB 的库那样先做子集规划。
5.2 批量获取
#-- 清单与校验和先落地
curl -sL https://physionet.org/files/fpcgdb/1.0.0/RECORDS -o RECORDS
curl -sL https://physionet.org/files/fpcgdb/1.0.0/SHA256SUMS.txt -o SHA256SUMS.txt
#-- 按清单逐条取一对文件,平铺目录不需要建子目录
mkdir -p data
while IFS= read -r rel; do
for ext in hea dat; do
curl -sL --retry 3 -C - \
"https://physionet.org/files/fpcgdb/1.0.0/${rel}.${ext}" \
-o "data/${rel}.${ext}"
done
done < RECORDS
#-- 核对:应有 26 个 dat、26 个 hea,且校验和全部通过
ls data/*.dat | wc -l
cd data && sha256sum -c ../SHA256SUMS.txt 2>&1 | grep -c OK
第三段核对里两个数字都应当是 26。若校验和输出里出现 FAILED,说明下载中断,重取该文件即可——-C - 会从断点续传,不必从头来。
5.3 把文件名解析成结构化表
import os
import re
import pandas as pd
PAT = re.compile(r"^fetal_PCG_(?P<pid>p\d{2})_GW_(?P<gw>\d{2})$")
rows = []
for fn in sorted(os.listdir("data")):
if not fn.endswith(".hea"):
continue
m = PAT.match(fn[:-4])
rows.append({"name": fn[:-4], "pid": m["pid"], "gw": int(m["gw"])})
df = pd.DataFrame(rows).sort_values(["gw", "pid"])
print(len(df), df["gw"].min(), df["gw"].max(), df["pid"].nunique())
#-- 26 31 40 26
最后一行三个数字把库的边界说清楚了:26 段,孕周从 31 到 40,编号 26 个互不重复。也就是说每人只录了一段,不存在同一孕妇的多次纵向记录。这一点在建模时很关键——不能把同一个人当多次观测,也不存在「同一个体的孕周变化」这条信息。
5.4 读一段并画出包络
import wfdb
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import hilbert, butter, filtfilt
def envelope(name, lo=20.0, hi=120.0):
rec = wfdb.rdrecord(f"data/{name}", physical=True)
fs = rec.fs
b, a = butter(4, [lo / (fs / 2), hi / (fs / 2)], btype="band")
x = filtfilt(b, a, rec.p_signal[:, 0])
return fs, x, np.abs(hilbert(x))
fs, x, env = envelope("fetal_PCG_p02_GW_31")
t = np.arange(len(x)) / fs / 60
fig, ax = plt.subplots(2, 1, figsize=(11, 5), sharex=True)
ax[0].plot(t, x, lw=0.4)
ax[1].plot(t, env, lw=0.8)
ax[1].set_xlabel("minutes")
plt.tight_layout()
plt.savefig("p02_overview.png", dpi=150)
这段用的是 §4.2 的案例。画出来的上图是原始波形,下图是包络;包络上的峰簇对应一次次心搏,但峰簇之间还夹着母体成分造成的次级起伏。判断哪一簇是胎儿的,目前只能靠人工对照——没有标注就没有别的办法。
5.5 按孕周分组
import pandas as pd
df = pd.read_parquet("index.parquet")
bins = [30, 34, 37, 41]
labels = ["31-33", "34-36", "37-40"]
df["band"] = pd.cut(df["gw"], bins=bins, labels=labels, right=True)
print(df.groupby("band", observed=True)["name"].count())
print(df.groupby("band", observed=True)["gw"].agg(["min", "max"]))
分组时要注意 32 与 33 周在库里没有对应记录,所以按三段切分后,第一段的样本会明显少于其余两段。这不是筛选造成的,而是原始覆盖如此;报告里若要按孕周分层,得先说明这一点,否则会被误读成抽样偏差。
5.6 六个最容易出错的地方
| 位置 | 错误写法 | 后果 | 正确做法 |
|---|---|---|---|
| 目录假设 | 以为有子目录 | 找不到文件 | 全部平铺在根目录 |
| 身份信息 | 去头文件里找孕周 | 头文件只有两行,无此字段 | 解析文件名 |
| 单位理解 | 当帕斯卡或分贝用 | 定量结论全部失效 | 无量纲,只做库内相对比较 |
| 标注假设 | 按 .atr 找标注 |
一个都没有 | 需要自建真值 |
| 时长假设 | 以为每段都是整二十分钟 | 实际 19.97 至 20.53 分钟不等 | 按 sig_len 除采样率算 |
| 性别与孕周口径 | 把 p01 至 p26 当 26 次独立观测 | 实为 26 人各一段 | 按人划分训练与测试 |
最后一行在做小规模实验时尤其重要。26 段里若随机按窗口切片划分训练与测试,同一段录音的前后窗会同时出现在两侧,指标会被高估;正确做法是按记录划分,比如 18 段训练、8 段测试。
§6 与库内条目的关系
6.1 关系图谱
| 词条 | 模态与性质 | 与本库的关系 |
|---|---|---|
| simfpcgdb | 心音,合成 | 同组同源的模拟版本,本库是它的参数来源 |
| IIScFHSDB | 心音,真实 | 同一任务的新一代真实库,人数更多、采样率更高 |
| CirCor 心音库 | 心音,真实,儿科 | 模态相同、人群不同,方法可迁移、结论不可迁移 |
| adfecgdb | 心电,真实 | 模态不同、生理系统相同,可做跨模态对照 |
| fecgsyndb | 心电,合成 | 同样是「为算法造的真值」,但走的是电生理路线 |
| CTU-UHB 与 UCI 的 CTG 库 | 胎心率与宫缩,真实 | 任务层级更高,输入是已提取的心率曲线 |
| 胎儿腹部超声分割库 | 影像,真实 | 看结构不看声学,任务无交集 |
真正有直接关系的是前两行。simfpcgdb 与本库是一对:同一批人的建模思路,一边真实一边合成,采样率与位深都不同;IIScFHSDB 则是同一任务在十年后的重做,人数从 26 涨到 60,采样率从 333 赫兹涨到 2 千赫兹。三代资源摆在一起,可以看出这个领域十年间的取舍变化:早期优先把波形录清楚,后期优先把人数与采样率做上去。
6.2 检索路径
| 你要找的东西 | 检索词 | 会落到哪里 |
|---|---|---|
| 胎心音的原始波形 | fetal phonocardiography、fPCG |
§2 与 §3 |
| 胎心率提取的方法史 | fetal heart rate、S1 S2 detection |
§8.2 |
| 合成心音的来源 | simfpcgdb、PCG simulator |
§4.4 |
| 同类真实库的对比 | fetal heart sound database |
§2.5 与 §6.1 |
| 采集设备信息 | Fetaphon、Pentavox |
§3.1 |
| 许可与引用 | ODC-BY、PhysioNet citation |
§9.3 |
6.3 与其他库的分工判据
| 任务 | 主粮仓该用什么 | 本库的位置 | 原因 |
|---|---|---|---|
| 心音分割算法的初步验证 | 带标注的真实库 | 辅助 | 波形可用,标签要自建 |
| 模拟器的形态校准 | 本库 | 主力 | 唯一公开的原始素材 |
| 胎心率提取的规模化评测 | 合成库加真实库 | 边缘 | 样本仅 26 段 |
| 跨模态(心音对心电)研究 | 本库加心电库 | 主力之一 | 同一生理系统的另一模态 |
| 临床决策支持 | 无 | 不适用 | 全部为健康妊娠 |
| 教学演示 | 本库 | 主力 | 体积极小、免注册 |
第三行值得展开。胎心率提取的评测需要真值,而真值要靠标注;26 段录音的标注量对统计检验来说偏少,因此它更适合当「真实性校验」而不是「性能排名」的场地。把它与合成库搭配使用,才是它最合适的位置:合成库给规模,本库给真实感。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
评价这个库时最容易发生的一次误判,是拿它和今天的胎心音基准库放在同一根尺子上比,然后得出「26 段、8 位、没标注,参考价值有限」的结论。这个比较本身错位:它的目标不是充当一份评测集,而是给一个建模任务留下原始素材。用「够不够训练」去评它,就像用「够不够当教材」去评一本实验记录本。
完成这个校正之后,分数才读得准。它在标注维度上得低分,不是因为它偷懒没标,而是因为 2012 年那项工作的目标里根本没有「标注」这一项——先把波形录下来、把参数测出来就完成了任务。它在可获取性上得高分,也不是因为做了什么优化,而是因为总共只有 19.9 MB。评分必须分开看这两件事,否则会把一种任务定位误读成一种质量缺陷。
7.1 五维评分
按 DAIMS 的常规划分(规模、标注、任务适配、文档、可获取性)逐项打分,每项 1 至 5 分,锚定在「作为胎心音波形参照与模拟器校准素材」这个用途上:
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 2 | 26 段、8.69 小时单通道,覆盖孕 31 至 40 周 |
| 标注质量 | 1 | 无任何标注文件,头文件亦无注释行 |
| 任务适配 | 3 | 对「看真实波形」极合适,对「测算法」需自建真值 |
| 文档完整 | 3 | 采集条件写得清楚,但设备参数、滤波设置、标注规范均未给 |
| 可获取性 | 5 | 19.9 MB、免注册、ODC-BY、带校验和清单 |
合计 14 分(满分 25)。这个分数结构很能说明它的性质:可获取性满分,标注接近零分,中间两项居中。它不是一份均衡的资源,而是一份有明显短板的专用素材。
标注给 1 分而不是 0 分,是因为官方至少交代了信号的可读性——在噪声较小的片段里能辨认出 S1 与 S2 成对出现。这句话对使用者有实际帮助,它告诉你哪些片段值得先看;但它不构成标注,也不能替代逐拍的时间戳。
7.2 没有标注这件事的两面
从数据完整性看,没有标注意味着没有任何标注者引入的主观偏差,也意味着没有任何可以对齐的真值;从使用门槛看,拿到就能听、就能画,但想做评测必须自己标一遍;从复现性看,不同团队标出来的结果天然不同,跨团队的指标无法直接比较;从维护成本看,发布方不需要维护标注版本,代价是使用者各自重复劳动。
第二点是绝大多数人第一次用它的真实体验:下载、读入、画图,十分钟就能看到波形;然后想算个检出率,发现无从下手。回到 §4.2 的案例,一段二十分钟的录音里,噪声小的片段只占一部分,人工逐拍标完要花的时间远超下载与读取的总和。官方的说法是这批数据被用来「开发与测试胎心率提取算法」,但那是在论文内部完成的,标注没有随库发布。
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 无标注 | 目录里只有数据与头文件 | 评测需自建真值 |
| 单通道 | 一段录音只有一路 | 无法做空间滤波与通道校验 |
| 8 位量化 | 256 个台阶 | 弱信号细节被压平 |
| 采样率 333 赫兹 | 频率上限约 166 赫兹 | 高频形态不可用 |
| 孕周不连续 | 文件名中缺 32 与 33 周 | 早期孕晚段无样本 |
| 单一设备 | 全部为 Fetaphon | 设备效应与个体效应混在一起 |
| 单一中心 | 一家私人诊所 | 环境噪声构成不可迁移 |
| 全部健康单胎 | 无病理、无双胎、无早产 | 异常形态无样本 |
| 幅度不可标定 | 无量纲、增益为显示标度 | 绝对强度结论无法成立 |
| 时长不整齐 | 19.97 至 20.53 分钟不等 | 按固定长度切窗会截断尾段 |
第五行值得单独说一句。官方写的范围是 31 至 40 周,但 26 个文件名里出现的孕周只有 31、34、35、36、37、38、39、40 这八个值,32 与 33 周没有任何记录。这不是统计推断,而是把 RECORDS 的 26 行逐个读一遍就能看见的事实。做孕周分层时若按每两周切段,最前面一段会明显偏薄。
第六行与第七行合起来是一个常被低估的问题。26 段录音全部来自同一台设备、同一个场所,任何跨录音的差异都同时包含个体差异、贴合差异与设备状况差异,而库内没有字段能把三者分开。想研究「不同孕妇的心音差异」,得先假设设备与操作是一致的——这个假设没法验证。
7.4 外部验证矩阵
从公开的引用关系看,这个库在文献里承担的角色集中在三类:
| 验证角色 | 典型做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 波形参照 | 用真实波形说明 S1/S2 的形态与幅度比 | 素材真实、可公开引用 | 仅 26 段,形态代表性有限 |
| 算法测试集 | 在其上人工标注后测胎心率提取 | 真实噪声、真实传播路径 | 标注质量随团队而异 |
| 模拟器校准 | 用它的统计特征设定合成参数 | 同组同源,参数可追溯 | 校准结果只对同款设备成立 |
第一行是它最稳的用法。论文里要画一张「真实胎儿心音长什么样」的图,用这个库的片段比用自制图更有说服力,因为 DOI 可查、许可清楚。
第二行的问题在于循环:标注由使用者自己做,指标也由使用者自己定义,不同团队的结果无法横向比较。这不是库的缺陷,而是无标注资源在评测场景下的固有约束。
7.5 它为何能持续:一份波形字典不需要更新
这个库自 2015 年上线后没有扩版,也没有修订,却仍在被下载。原因不在规模,而在于它占着一个别人不愿重复劳动的位置:真实胎儿心音的公开原始录音极少,而这类录音的采集需要孕妇配合、需要设备、需要伦理流程,产出的却只是几十兆的数据。对一个想验证「我的合成信号像不像真的」的团队来说,重新组织一次采集的成本远高于直接引用这 26 段。
它的价值也不会因为设备过时而消失。333 赫兹、8 位在今天看是落后规格,但作为「2010 年一台便携设备录到的真实胎心音」这一事实,它不会因为有了 2 千赫兹的新库而失真。旧规格在这里反而成了一种标记:它标定的是那个年代的采集条件,而不是今天的性能上限。
§8 生态位与历史
8.1 历史沿革
这个库的诞生路径是「先有研究问题,再有数据,最后才成为公开资源」。2010 年采集,2012 年论文发表,2015 年数据上线——三年多的间隔里,数据一直作为课题组内部素材存在。这种节奏在生理信号领域并不罕见,它带来一个结果:数据的形态由当年的研究问题决定,而不是由后来的使用需求决定。
| 时间 | 事件 | 意义 |
|---|---|---|
| 2010 年 | 在私人诊所完成 26 段录音 | 原始素材形成 |
| 2012 年 9 月 | 论文发表于 Computer Methods and Programs in Biomedicine | 公开展示模拟器与预研结论 |
| 2015 年 7 月 1 日 | 数据文件落位 | 文件系统时间戳 |
| 2015 年 11 月 12 日 | 头文件落位 | 与数据文件相差四个月 |
| 2015 年 12 月 16 日 | 以 1.0.0 版上线,获得 DOI | 进入可引用状态 |
| 2019 年 2 月 20 日 | 补充 SHA256SUMS.txt | 增加完整性校验,数据未变 |
第三行与第四行的时间差值得留意:数据文件比头文件早四个月落位。对使用者没有影响,但它说明这次发布是分步完成的,不是一次性打包。第六行则是 PhysioNet 平台在 2019 年前后统一补充校验和的批次动作,同一时期很多库都多了这个文件。
8.2 与后续研究的关系
| 阶段 | 主要用法 | 对数据的要求 |
|---|---|---|
| 2012 至 2015 | 课题组内部校准模拟器 | 波形真实、参数可测 |
| 2015 至 2019 | 公开引用,作为真实侧对照 | 可下载、可引用、许可清楚 |
| 2019 年至今 | 与新采集的胎心音库并列比较 | 覆盖孕周、设备条件可描述 |
第二阶段之后,它的角色逐渐从「唯一素材」变成「历史参照」。这不是它退步了,而是这个领域又出现了采样率更高、人数更多、带临床信息的真实库。新旧并列时,它的优势反而清楚:体积极小、结构极简、没有任何需要申请的手续,适合当第一份上手的数据。
8.3 生态位:素材而不是基准
把胎心音相关的公开资源按「有没有真值」和「是不是真实录音」两个轴摆开,会得到四个格子。左上角是真实且有标注的库,数量最少、最贵重;右下角是合成且有真值的库,数量最多、最容易生成;左下角是真实但无标注的,正是本库所在的位置;右上角是合成但无标注的,基本没人做。
这个位置常被误解为「不上不下」。实际上它承担的是一个不可替代的中间角色:向上,它为合成库提供形态依据;向下,它为标注工作提供原始材料。任何要在这条链上往前走的团队,第一站都得先看一眼真实录音长什么样。
四格可以落到具体资源上。真实且有标注的那一格,是带临床信息、带胎心率标签的胎心音库,数量最少也最贵重;合成且有真值的那一格,是 simfpcgdb 一类按信噪比档位批量生成的数据,数量最多、最容易扩大;真实但无标注的那一格就是本库;合成但无标注的那一格基本没人做,因为模拟器既然能造,就没有理由不顺手把标注一起写出来。
8.4 谁在用它,用来做什么
| 使用者 | 用法 | 用到的部分 |
|---|---|---|
| 心音信号处理研究者 | 做 S1/S2 检测与分割的初步验证 | 原始波形与真实噪声 |
| 模拟器开发者 | 校准合成信号的形态与噪声配方 | 波形统计特征 |
| 设备厂商工程师 | 判断自家探头录到的信号是否合理 | 同设备下的参考电平 |
| 教学人员 | 课堂演示腹部录音的波形与包络 | 完整录音,十分钟一段 |
| 数据标注团队 | 作为标注流程的试标材料 | 短片段,先跑通规范 |
第四行的用法最容易被忽视,但它的门槛最低:19.9 MB 拷给学生,装个 wfdb 就能读,不需要申请、不需要签署协议、不需要理解 WFDB 的注释体系——因为这个库压根没有注释。作为教学第一课,它比任何带复杂元数据的库都合适。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 心音算法研究者 | 取全量,跑通读取与包络 | 人工标几段的 S1 位置,建立小真值 | 按记录划分训练与测试,别按窗口切 |
| 模拟器使用者 | 取几段作参照,与合成波形并排画 | 对比 S1/S2 的时长与幅度比 | 采样率差三倍,比较前先重采样 |
| 教学人员 | 取一段,画原始波形与包络 | 做「噪声大与噪声小」的片段对比 | 单位无量纲,坐标轴不要标物理单位 |
第一行的第二格是整个流程里最花时间的部分。26 段里有相当一部分片段噪声偏大,S1 与 S2 只能靠节律的规律性去推;先把噪声小的片段挑出来标,再逐步扩展,比从头标到尾效率高得多。
9.2 一条最短的可用流程
#-- 1. 取清单与校验和
curl -sL https://physionet.org/files/fpcgdb/1.0.0/RECORDS -o RECORDS
curl -sL https://physionet.org/files/fpcgdb/1.0.0/SHA256SUMS.txt -o SHA256SUMS.txt
#-- 2. 全部取回(总共不到 20 MB,不必做子集)
mkdir -p data
while IFS= read -r rel; do
curl -sL --retry 3 "https://physionet.org/files/fpcgdb/1.0.0/${rel}.hea" -o "data/${rel}.hea"
curl -sL --retry 3 "https://physionet.org/files/fpcgdb/1.0.0/${rel}.dat" -o "data/${rel}.dat"
done < RECORDS
#-- 3. 头文件里核对三条:1 通道、333 Hz、采样点数约四十万
head -1 data/fetal_PCG_p02_GW_31.hea
wc -l < RECORDS
import os
import wfdb
rows = []
for fn in sorted(os.listdir("data")):
if not fn.endswith(".hea"):
continue
r = wfdb.rdheader(os.path.join("data", fn[:-4]))
rows.append((fn[:-4], r.n_sig, r.fs, r.sig_len, round(r.sig_len / r.fs / 60, 2)))
for row in rows:
print(*row)
#-- 26 行,n_sig 全为 1,fs 全为 333,时长在 19.97 到 20.53 分钟之间
第二段只读头信息(rdheader 不加载波形),26 个文件跑完不到一秒。它顺带完成了一次全库自检:如果哪一行的通道数不是 1、采样率不是 333,说明文件被替换或下载出错,应当先排查再往下做。
9.3 引用方式
官方页面把引用要求写在最显眼的位置:使用时引用原始论文,即 Cesarelli、Ruffo、Romano、Bifulco 四人在 2012 年《Computer Methods and Programs in Biomedicine》第 107 卷第 3 期 513 至 523 页发表的那篇,同时附上 PhysioNet 平台本身的标准引用。
只引平台不引论文,等于没交代这批录音为什么被录、按什么条件录;只引论文不引平台,别人按论文里的描述复现不出这份具体的 26 段清单。版本号也要写清楚:PhysioNet 路径带 1.0.0,DOI 为 10.13026/C2PD5B,两者对应同一个快照。若引用的是同组的合成数据,DOI 是另一个(10.13026/C2GW25),不要混用。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,结构与事实由编辑把关 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面、RECORDS 与头文件 |
| 页面核验 | 官方项目页 HTTP 200,正文、文件列表、许可与 DOI 均取自该页 |
| 清单核验 | RECORDS 26 行全部取回,逐行解析孕妇编号与孕周 |
| 头文件核验 | 26 个头文件首行全部取回,确认通道数、采样率与采样点数 |
| 文件大小 | 核对了 .dat 的 content-length 与「采样点数乘 2 字节」是否吻合 |
| 论文信息 | 只读 Europe PMC 的摘要,未读全文 |
| 未核验内容 | 录音的滤波设置、探头型号细节、26 段中每一段的信号质量 |
| 图像 | 无配图;封面为生成式提示词,不含真实录音波形 |
| 免责 | 本文不构成临床建议;数据使用须遵守 ODC-BY 1.0 的署名要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 它是一份胎心电数据库 | 是胎心音,模态是声学 | 官方标题写 Fetal PCG Database,正文写 phonocardiographic |
| FPCG 指胎儿心电 | 指胎儿心音图 | 官方同一句里写 fetal phonocardiographic signals |
| 它有胎心率标注 | 没有任何标注文件 | 目录只有 .dat 与 .hea,共 52 个 |
| 它有 26 名以上受试者 | 26 名,每人一段 | 编号 p01 至 p26 各出现一次 |
| 每段都是整二十分钟 | 19.97 至 20.53 分钟不等 | 采样点数 399000 至 410001 除以 333 |
| 孕周从 31 到 40 连续覆盖 | 实际出现 31、34 至 40,缺 32 与 33 | RECORDS 26 行逐个解析 |
| 单位是帕斯卡或分贝 | 无量纲归一化值 | 官方称设备输出为归一化,增益仅供显示 |
| 8 位就是文件里每样本 1 字节 | 头文件格式码 16,每样本占 2 字节 | content-length 800000 除以 400000 点 |
| 它和 simfpcgdb 是同一份数据 | 一个是真实录音,一个是模拟输出 | 采样率 333 对 1000,位深 8 对 16 |
| 采集时间就是上线时间 | 2010 年采集,2015 年上线 | 官方写 recorded in 2010,发布日 2015-12-16 |
第四行需要补一句:官方原文是 26 段来自不同孕妇的信号,编号也确实是 26 个互不重复的值,因此「26 人各一段」是结构与描述共同支持的说法,而不是从文件名反推的猜测。
FAQ
Q1:FPCGDB 里的 FPCG 到底指什么?
指胎儿心音图(fetal phonocardiography)。记录的是胎儿心脏搏动经母体组织传到腹壁的声信号,不是电信号。官方标题是 Fetal PCG Database,正文用 fetal phonocardiographic signals,缩写与全名一致。
Q2:它和 fecgsyndb、adfecgdb 是什么关系?
模态不同。后两者是心电,本库是心音;前两者一个合成一个真实,本库是真实。它们同属胎儿监测这条线,可以并列对照,但不能互相替代——心音里没有 QRS,心电里没有 S1 与 S2。
Q3:26 段是怎么数出来的?
RECORDS 共 26 行,每行一个记录名;目录里对应 26 个 .dat 与 26 个 .hea。编号从 p01 到 p26,每个编号只出现一次,因此 26 段对应 26 名孕妇,每人一段。
Q4:总时长到底多少?
把 26 段的采样点数相加得 10422007 点,除以 333 赫兹得 31297 秒,即 521.6 分钟、8.69 小时。单段在 19.97 至 20.53 分钟之间,官方表述是平均二十分钟。
Q5:为什么没有标注?
因为采集时的目标不是做评测集。官方说这批数据被用来设计心音模拟器、并开发与测试胎心率提取算法,但标注没有随数据发布。目录里不存在任何标注扩展名,头文件也没有注释行。
Q6:单位为什么是无量纲的?
官方写明心音设备输出的是归一化值,因此测量单位是任意的。头文件里的增益 0.005 是为了让波形显示刻度与之前的模拟 PCG 数据一致,属于显示标度。数值只在库内可比。
Q7:头文件为什么只有两行?
这个库的头文件只声明记录名、通道数、采样率、点数与通道参数,没有任何注释行。所有采集条件(孕周、编号、设备、地点)都写在官方页面的正文里,而不是随文件走。
Q8:8 位和格式码 16 矛盾吗?
两个口径并存:官方正文写 8 位、Format 80,头文件第二行写格式码 16、位分辨率 8,而 .dat 的字节数是每样本 2 字节。存储用 16 位码、量化是 8 位,两者可以同时成立;读的时候以头文件为准,用标准工具读即可。
Q9:能不能直接拿它训练模型?
8.69 小时单通道,量级偏小。做小规模自监督或迁移学习的预训练可以试,做从零训练的监督学习不够,而且没有标签。更合适的用法是当真实侧参照,或当标注流程的试标材料。
Q10:它和 simfpcgdb 该用哪个?
看你要真实还是要真值。要真实波形用它,要带 SNR 标注的批量样本用 simfpcgdb。两者采样率差三倍、位深差八位,混合使用前必须重采样并统一幅度标度。
Q11:能做商用吗?
ODC-BY 1.0 允许包括商业用途在内的使用,条件是署名。官方要求引用 2012 年那篇论文,具体条款以许可全文为准。
Q12:还会更新吗?
只有一个版本 1.0.0。2019 年 2 月补充了校验和清单,数据本身未变。页面没有任何扩版计划,也没有后续版本的入口。
术语表
| 术语 | 解释 |
|---|---|
| PCG | 心音图,记录心脏机械振动产生的声音 |
| fPCG | 胎儿心音图,本库的模态 |
| S1 | 第一心音,房室瓣关闭产生,出现在心室收缩初期 |
| S2 | 第二心音,半月瓣关闭产生,出现在心室舒张初期 |
| 心音探头 | 贴在腹壁拾取振动并转成电压的传感器 |
| Fetaphon | Pentavox 公司的便携心音记录系统,本库的采集设备 |
| 归一化输出 | 设备把电平压到固定刻度后输出,不带物理单位 |
| 增益 | 头文件里把整数换算成显示值的系数,本库为 0.005 |
| ADC 零点 | 量化区间的中点,本库为 128 |
| 位分辨率 | 量化台阶的位数,本库为 8 位,即 256 级 |
| 采样率 | 每秒取样次数,本库为 333 赫兹 |
| 奈奎斯特频率 | 可分辨的最高频率,为采样率的一半,本库约 166 赫兹 |
| 包络 | 把振荡信号变成其幅度轮廓的变换,常用希尔伯特变换求 |
| 自相关 | 信号与自身延迟版本的相关,用于找周期 |
| 胎心率 | 每分钟胎儿心搏次数 |
| 母体心音干扰 | 母体瓣膜振动混入腹部录音形成的规律性噪声 |
| 胎盘血流湍流 | 血流经过胎盘床产生的持续宽带噪声 |
| 胎动伪影 | 胎儿肢体运动造成的突发冲击 |
| 孕周 | 从末次月经起算的妊娠周数,本库覆盖 31 至 40 周 |
| 单胎妊娠 | 一次妊娠只有一个胎儿,本库全部为单胎 |
| WFDB | PhysioNet 的波形数据格式,含头文件与数据文件 |
.hea |
纯文本头文件,本库只有两行 |
.dat |
二进制样本文件,按通道交织存放 |
| ODC-BY | 开放数据共享署名许可,允许商用但须署名 |
| DOI | 数字对象标识,本库为 10.13026/C2PD5B |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 记录数 | 26 | RECORDS 逐行 |
官方文件 |
| 孕妇编号范围 | p01 至 p26 | 文件名 | 官方文件 |
| 孕周范围 | 31 至 40 | 官方页面与文件名 | 官方页面 |
| 文件名中出现的孕周值 | 31、34 至 40 | RECORDS 解析 |
官方文件 |
| 年龄范围 | 25 至 35 岁 | 官方页面 | 官方页面 |
| 采集年份 | 2010 | 官方页面 | 官方页面 |
| 采集地点 | 意大利那不勒斯,私人诊所 | 官方页面 | 官方页面 |
| 采集设备 | Fetaphon Monitoring System(Pentavox) | 官方页面 | 官方页面 |
| 单段平均时长 | 20 分钟 | 官方页面 | 官方页面 |
| 单段实际时长 | 19.97 至 20.53 分钟 | 头文件采样点数折算 | 官方文件 |
| 采样点合计 | 10422007 | 26 个头文件求和 | 官方文件 |
| 总时长 | 521.6 分钟 / 8.69 小时 | 采样点除采样率 | 派生 |
| 通道数 | 1 | 头文件首行 | 官方文件 |
| 采样率 | 333 Hz | 头文件首行 | 官方文件 |
| 位分辨率 | 8 位 | 头文件第二行与官方正文 | 官方文件 |
| 存储格式码 | 16 | 头文件第二行 | 官方文件 |
| 增益 | 0.005 | 头文件第二行 | 官方文件 |
| 每样本字节数 | 2 | content-length 除采样点数 | 派生 |
| 数据文件体积 | 约 780 KB 每个 | 文件列表 | 官方页面 |
| 总解压体积 | 19.9 MB | 官方页面 | 官方页面 |
| 许可 | ODC-BY 1.0 | 官方页面 | 官方页面 |
| DOI | 10.13026/C2PD5B | 官方页面 | 官方页面 |
| 上线日期 | 2015-12-16 | 官方页面 | 官方页面 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 26 段、26 名孕妇、年龄范围、孕周范围、采集年份与地点、设备型号、平均时长、采样率、位深、增益、单位性质、体积、许可、DOI、上线日期,全部取自项目主页的 Data Description 与 Recording information 两节。通道数、采样点数、存储格式码、ADC 零点、首样本值、信号名,取自 26 个头文件的首两行。RECORDS 的 26 行与 SHA256SUMS.txt 的 53 行(52 个数据与头文件加清单自身),是直接取回后逐行读到的。
第二层:论文摘要。 采集预研的目的、模拟器覆盖不同生理与病理状态与不同记录条件的设计、用模拟信号测试胎心率提取算法的做法、以及模拟信号与真实录音接近的结论,来自 2012 年那篇论文的摘要。仅此而已,摘要没有给出逐段的技术参数。
第三层:派生与未核实。 总采样点数、总时长、每样本字节数这三项是算术派生,不是官方直接给出的数字。未核实的内容包括:录音是否经过滤波、滤波器的类型与截止频率、探头的具体型号与耦合方式、26 段中每一段的实际信噪比、以及 2019 年补充校验和之前是否还有别的修订。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | Fetal PCG Database v1.0.0 | https://physionet.org/content/fpcgdb/1.0.0/ | 规模、结构、边界数据 |
| 2 | 该库文件目录 | https://physionet.org/files/fpcgdb/1.0.0/ | 清单、校验和、头文件 |
| 3 | Cesarelli M 等,Comput Methods Programs Biomed 2012;107(3):513-523 | https://doi.org/10.1016/j.cmpb.2011.11.008 | 采集目的与模拟器设计 |
| 4 | 数据集 DOI | https://doi.org/10.13026/C2PD5B | 引用与版本定位 |
| 5 | Simulated Fetal PCGs(同组合成库) | https://physionet.org/content/simfpcgdb/ | 分工对照 |
| 6 | Ruffo M 等,Biomed Signal Process Control 2010;5:131-141 | 见 simfpcgdb 页参考文献 | 胎心率估计算法 |
| 7 | PhysioNet 平台综述(2026,Nature Health) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 8 | Europe PMC 检索入口 | https://www.ebi.ac.uk/[europepmc](https://www.qianfanghub.com/ai-ready-dataset/europepmc/1353)/ | 论文摘要来源 |
附录 D:任务代码
任务一:在一段录音上找出候选心搏
import wfdb
import numpy as np
from scipy.signal import hilbert, butter, filtfilt, find_peaks
def candidates(name, lo=25.0, hi=110.0, min_gap_s=0.25):
rec = wfdb.rdrecord(f"data/{name}", physical=True)
fs = rec.fs
b, a = butter(4, [lo / (fs / 2), hi / (fs / 2)], btype="band")
env = np.abs(hilbert(filtfilt(b, a, rec.p_signal[:, 0])))
thr = np.percentile(env, 92)
peaks, _ = find_peaks(env, height=thr, distance=int(min_gap_s * fs))
return fs, env, peaks
fs, env, pk = candidates("fetal_PCG_p02_GW_31")
rr = np.diff(pk) / fs
print(len(pk), round(float(np.median(rr)), 3), round(60 / float(np.median(rr)), 1))
#-- 候选数、中位间隔(秒)、折算成每分钟次数
这段的意义不在检出率——没有真值就没法算检出率——而在于给出一个可重复的基线:同一套门限在同一段录音上每次跑出的候选数完全一致。把中位间隔折算成每分钟次数,量级落在胎儿心率或母体心率的范围内,哪个更接近要靠人工听辨确认。
任务二:核对全库的规格是否一致
import os
import wfdb
bad = []
for fn in sorted(os.listdir("data")):
if not fn.endswith(".hea"):
continue
r = wfdb.rdheader(os.path.join("data", fn[:-4]))
ok = (r.n_sig == 1 and r.fs == 333 and 390000 < r.sig_len < 420000)
if not ok:
bad.append((fn, r.n_sig, r.fs, r.sig_len))
print(len(bad), bad)
#-- 期望输出 0 []
这段是整个使用流程的第一道体检。若 bad 为空,说明 26 个文件全部符合「单通道、333 赫兹、约四十万点」的规格;若有内容,先查下载是否完整,再查文件是否被替换。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 它是心音,不是心电 | 决定能问什么问题 |
| 2 | 26 段、8.69 小时、19.9 MB | 决定它能承担多重的任务 |
| 3 | 没有标注 | 任何评测都要先自建真值 |
| 4 | 单位无量纲、8 位、333 赫兹 | 三条最容易被误用的规格 |
| 5 | 它是同组合成数据的原料 | 这是它不可替代的地方 |
编辑说明
核对于 2026 年 10 月 28 日完成。核对方式为直接访问 PhysioNet 项目页并读取正文、文件列表、许可与 DOI,取回 RECORDS 26 行与 SHA256SUMS.txt 53 行,逐行解析孕妇编号与孕周;26 个头文件的首行与第二行全部取回,确认通道数恒为 1、采样率恒为 333、采样点数落在 399000 至 410001 之间、格式码恒为 16、位分辨率恒为 8。另取单个 .dat 的响应头核对字节数为 800000,与 400000 点乘 2 字节吻合,并据此说明「存储 16 位码、量化 8 位」这两个口径可以并存。论文侧只读 Europe PMC 摘要,未读全文,因此模拟器的内部参数以同组公开页面的表述为准。未覆盖的内容包括:录音是否滤波、探头型号细节、逐段信噪比、以及 2019 年补充校验和之前是否还有其它修订。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- ehgdb — 共享标签:生理信号 / 可穿戴传感 / 儿科
- gait-maturation-db — 共享标签:生理信号 / 可穿戴传感 / 儿科
- unicaprop — 共享标签:生理信号 / 可穿戴传感
- ppg-dalia — 共享标签:生理信号 / 可穿戴传感
- live-gaitneurokids — 共享标签:生理信号 / 可穿戴传感 / 儿科
- butqdb — 共享标签:生理信号 / 可穿戴传感
- culm — 共享标签:生理信号 / 可穿戴传感
- drivedb — 共享标签:生理信号 / 可穿戴传感
- eda-rest-sedation — 共享标签:生理信号 / 可穿戴传感
- nesfdb — 共享标签:生理信号 / 可穿戴传感
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

