686. PhysioNet - Digitization of ECG Images | physionet-ecg-image-digitization
感谢 PhysioNet、竞赛主办方、Kaggle 以及所有参与人员组织了如此具有挑战性和有趣的竞赛。在参加这次竞赛之前,我可能会嘲笑甚至认为这是魔法,所以能够最终理解一种我未曾意识到可行的计算机视觉实际应用,我感到非常欣慰。
特别感谢 @hengck23 以及 @kami1976,他们的 Notebook 为我提供了解决方案的初始起点。还要感谢想出爱因托芬(Einthoven)误差校正算法的人,我在最后将该算法应用到了我的信号中,也许是 @antonoof?
正如我的副标题所示,我的解决方案在很大程度上是 hengck23 原始 demo 提交 Notebook 的扩展,尽管我确实提供了一些重大更改。以下部分描述了我推理 pipeline 的基本流程。
在我 pipeline 的第一阶段,我调用 @hengck23 的 stage0 模型的第一部分,以获得正确方向的图像及其关键点标记的位置。
@hengck23 的 stage0 使用单应性变换来 warp 并输出分辨率为 1440x1152 的标准图像,这显著低于 ecg-image-kit 生成的 2200x1700 的 ECG 图像。在阶段 B 中,我创建了该低分辨率图像以及高分辨率的 2400x1920 图像,旨在尽可能保留原始 ECG 的信息。
阶段 C 包含以下主要步骤:
我基本上遵循 demo 提交 Notebook 中的相同过程,但有以下例外:
对于后处理,我做了两件事:
demo 提交 Notebook 中的网格点检测很好,但并不完美。如果你仔细观察左边的图像,你可以看到 ECG 网格中有微小的变形,那里的网格点检测偏离了一两个像素。当然,这些变形直接影响信号精度,所以尽可能准确地获取它们有助于信噪比 (SNR)。如上所述,我使用 @hengck23 的 stage1 网络初步预测图像网格点,然后将每个网格点通过两个细化网络的级联,以尽可能准确地定位每个点。右边的图像显示了 resulting 网格,几乎是完美的。
| 之前 | 之后 |
![]() |
![]() |
下面是 plotted 在略大半径的原始预测(红色)之上的细化网格点(绿色)。如果你想象将红色预测推入绿色,你可以看到左边图像中的变形是如何发生的。
为了细化网格点,我训练了 2 个 5 层基于热力图的 CNN,每个都利用 31x31 输入 patch 和膨胀 (dilations) 以确保感受野覆盖整个 patch。第一个网络使用 5 像素垂直和水平平移(以及其他增强)进行训练,而第二个仅使用 2 像素平移进行训练。初始网格点预测被传递给第一个网络,其预测被传递给第二个。因为第二个网络的训练是为了解决一个更简单的问题,所以它比第一个取得了更好的精度,代价是它能够容忍的输入偏差较小。如果你相信第二个网络的最终验证误差,预测位置与标签之间的平均欧几里得距离仅为 0.146 像素。
我使用原始网格点预测预训练了细化网格,然后使用一组 800 个手工标注的位置对每个网格进行微调,每种非 0001 图像类型 100 个,验证集 180 个。对于 0001 类型,我从整个图像集中随机选择了网格点位置。我最初使用 labelme 进行手工标注,但最终构建了一个自定义标注器,可以显示原始预测的位置作为参考。
我没有使用硬标签(像素设置为 0 或 1),而是使用软标签,使得信号通过的兩個相邻像素之间的强度设置为与信号距离每个像素中心的接近程度相关。例如,如果信号距离第一个像素中心 0.1 像素,则其值为 0.9,而相邻像素的值为 0.1。在这种情况下,软标签优于硬标签的价值在于它允许以亚像素分辨率指定标签。下图显示了硬标签和软标签。
对于阶段 D,我使用了与原始 stage2 模型基本相同的模型,不同的是,原始模型将图像的 y 坐标添加到网络的最后一层,而我添加了 x 和 y 坐标。这使得进行空间增强(如旋转或透视变换)成为挑战,因为两者都使得正确设置 x 和 y 坐标变得困难。为了解决这个问题,在训练期间,我以 0.5 的概率在最终层之前和之后训练网络。当在最终层之前训练时,我会进行更有问题的旋转和透视变换增强。当在最终层之后训练时,我只进行增强,如水平平移和颜色偏移。