Многим неоднократно приходилось сталкиваться с обследованием сердца в медицинских учреждениях с помощью кардиографа. Данный аппарат измеряет биоэлектрическую активность сердца, регистрируя результат на бумажной ленте. Современные кардиографы записывают результат измерения не на бумагу, а в цифровую память. Однако в качестве конечного носителя записанной информации зачастую применятся бумажная лента. Визуально она представляет собой длинную миллиметровую бумагу небольшой ширины, которая скручена в рулон. На бумаге, помимо миллиметровой сетки, нарисован во всю длину некий график, который отражает закон изменения измеряемой величины во времени. Измеряемая величина, как я понимаю, это есть разность потенциалов между отведениями. Чаще всего на одной ленте представлено сразу несколько графиков, так как регистрируются разности потенциалов между множеством отведений. Однако, не вдаваясь в подробности медицины, в дальнейшем будем рассматривать один из первых основных графиков. Кроме графиков, на ленте имеется дополнительная текстовая информация: масштаб по горизонтали (мм/сек), по вертикали (мм/мВ), измеренная частота сердцебиения (уд/мин) и прочее.

Возникла идея преобразовать данный график в звуковой формат, воспроизвести результат и послушать, как это будет звучать.

По предварительному анализу можно сделать вывод, что частотный состав такой волны не очень насыщенный. Фактически это низкие частоты, включая инфразвук, который, как считается, не слышен. Однако можно будет увидеть, как диффузор НЧ динамика будет повторять колебания, похожие на «колебания» сердца. На самом же деле, ввиду наличия емкостных дифференцирующих цепей на пути распространения сигнала от звуковой карты ПК до НЧ усилителя, колебания динамической головки не будут в точности повторять колебания, представленные на кардиограмме. И это при условии, что нигде не установлены фильтры, срезающие сверхнизкие частоты. Кроме того, будут присутствовать нелинейные искажения, сопровождающиеся кратными гармониками верхних частот. Тем не менее, не принимая во внимание вышеизложенный анализ, поставим задачу так: преобразовать график на бумаге в формат WAV, чтобы при открытии этого файла в звуковом редакторе вид волны совпадал с бумажным вариантом и, кроме того, чтобы соответствовал временной масштаб.

Для начала надо прикинуть глубину квантования (разрешающая способность цифрового аудио по вертикали). Я рассматриваю один из стандартных: 8 или 16 бит. Второй вариант (16 бит) – это 65536 сэмплов по вертикали, что будет соответствовать 65536 пикселей картинки, которая представляет собой скан или фотографию кардиограммы. Это очень много, и смысла в этом нет. Если брать 8 бит – это 256 сэмплов, или 256 пикселей картинки. Вот это уже более подходящий вариант. При этом динамический диапазон аудио составит 6*8=48 дБ. Я не знаю, какой динамический диапазон у кардиограммы, но думаю, что не больше. У самого аппарата он естественно больше, но погрешность неизбежна при выводе кардиограммы на бумагу, особенно если речь идёт о прямой прорисовке пером. Кстати, насчёт последнего. Я не буду брать во внимание старые образцы, которые нарисованы «радиальным» пером. Миллиметровая бумажная лента для таких кардиограмм специфическая: по вертикали вместо прямых линий нанесены дуги окружностей. Что касается масштаба по горизонтали – частота дискретизации – будет рассчитываться исходя из масштаба кардиограммы и размера изображения. От этого параметра будет зависеть скорость воспроизведения, и она должна соответствовать реальной «скорости кардиограммы».

Бумагу с кардиограммой следует отсканировать в ч/б виде с оттенками серого в достаточном разрешении. Затем нужно изменить размер изображения таким образом, чтобы требуемая кардиограмма вписывалась в полосу шириной 256 пикселей. Я нашёл в Интернете множество изображений с кардиограммами. В качестве примера рассмотрим два из них.



Первое изображение, можно сказать, уже почти подготовленное. Высота изображения – 431. Ширина – 1023. Волна по ширине полностью заполняет весь рисунок. А вот по высоте нужно оставить 256, обрезав изображение сверху и снизу так, чтобы волна располагалась приблизительно по центру.



На втором рисунке изображено сразу несколько кардиограмм. Возьмём самую первую. После обрезки получилась картинка размерами 508 на 61.



Не растягивая изображение по вертикали, сделаем картинку по высоте 256, заполнив созданную область белой пустотой. Волна также должна располагаться приблизительно по центру. Ширину 508 при вырезании я выбрал так, чтобы оставить как можно большее число целых миллиметровых клеток, которые также видны на изображении.

Оба изображения нужно преобразовать к такому виду, при котором будет виден только чёрный график на белом фоне и больше ничего. Это делается элементарно. Ввиду того, что график нарисован намного жирнее, чем миллиметровая сетка, в графическом редакторе с помощью регулировок «яркость, контрастность, насыщенность» можно добиться требуемого результата. Если не получается идеального преобразования, лишний оставшийся «мусор» над графиком необходимо стереть инструментом «ластик». Все изображения требуется сохранить в формат монохромного BMP. Таким образом, в картинке уже точно останутся только белые и чёрные цвета.

Прежде приступить к описанию алгоритма преобразования картинки в WAV, стоит оговорить некоторые нюансы, которые упростят программирование. Получившиеся картинки необходимо повернуть на 90 градусов против часовой стрелки (ширина и высота изображения при этом поменяются местами). Это нужно для того, чтобы сориентировать начало кардиограммы с началом BMP файла. Известно, что цветовые данные каждого пикселя BMP файла записываются в файл по порядку построчно, начиная с нижнего левого угла. Затем картинки необходимо открыть в редакторе «MS Paint» (у меня Windows XP) и выполнить сохранение в 8-битный BMP (256 цветов). Конечно же, произойдёт «переопределение информации», но зато при таком формате каждый пиксель изображения соответствует одному байту, что очень удобно при программировании. Байт «0» — пиксель чёрного цвета, а байт «255» — белого. В результате должно получиться примерно следующее (здесь две картинки соединены и уменьшены вдвое).



Что касается выходного формата – будем выводить не в стандартный WAV файл, а в файл RAW-данных (PCM). Это также упрощает программирование, ибо при выводе в WAV необходимо ещё позаботиться о 44-байтном заголовке. В распространённом звуковом редакторе «Adobe Audition 1.5» PCM файл открывается без проблем. Более того, можно даже выводить в текстовый файл десятичные числа PCM данных в столбик, предварительно сформировав специфический текстовый заголовок. Как ни странно, но такие файлы Adobe Audition также открывает.

Опишем алгоритм преобразования. А алгоритм очень простой: нужно проанализировать каждую строчку BMP файла снизу вверх. Анализ будет заключаться в подсчёте слева направо идущих подряд белых пикселей, пока не встретится чёрный. Полученные целочисленные неотрицательные значения нужно записать в выходной PCM файл в бинарном виде. Размер выходного файла будет в точности совпадать с высотой обрабатываемого изображения. Глубина квантования 8 бит PCM формата аудиоданных подразумевает кодировку сэмплов по такому же принципу. Значение «0» — максимальное отрицательное значения сэмпла аудио, значение «255» — максимальное положительное, а «128» — нулевое значение (посередине). К примеру, файл PCM аудио данных тишины будет содержать одинаковые байты значением «128». Стоит оговорить, что в строчке может встретиться несколько подряд идущих чёрных пикселей, в зависимости от толщины линии кардиограммы. Но описанный алгоритм «ловит» верхнюю огибающую, чего вполне будет достаточно. Тем более, острые пики кардиограммы, направленные вверх, лучше будут схватываться этим способом.

Теперь можно приступить к написанию текста программы. Программа, написанная на Си, весьма простая и в подробных комментариях не нуждается.

#include <stdio.h> //Нужная библиотека, как обычно;

int main(){ //Типа начало программы;
    FILE *in,*out; //Входной и выходной файлы;
    unsigned long int h,i; //Высота изображения и итератор цикла;
    unsigned char px,s; //Прочитанный пиксель и насчитанный сэмпл аудио;
    in=fopen("1.bmp","rb"); //Открываем файл на чтение;
    out=fopen("1.pcm","wb"); //Открываем файл на запись;
    fseek(in,22,SEEK_SET); //Позиционируемся в то место заголовка, где записана высота изображения
    fread(&h,4,1,in); //Считываем высоту изображения (4 байта);
    for(i=0;i<h;i++){ //Цикл - пробег по строкам;
        fseek(in,0x436+i*256,SEEK_SET); //Позиционируемся на начало i-ой строки
        s=0; //Инициализируем счётчик (значение сэмпла);
        do{ //Подсчёт нечёрных пикселей;
            fread(&px,1,1,in); //Считываем цвет пикселя;
            s+=1; //Увеличиваем счётчик на единицу;
        }while(px); //И так, пока не встретится чёрный пиксель;
        fwrite(&s,1,1,out); //Записываем получившийся результат в выходной файл;
    }
    fclose(in); //Закрываем входной файл;
    fclose(out); //Закрываем выходной файл;
    return 0; //Типа конец программы;
}


После выполнения программы над файлом «1.bmp» будет создан файл «1.pcm» в том же каталоге с программой. При попытке открытия файла в Adobe Audition должно всплыть следующее окно.



Необходимо выбрать «Моно», «8-бит», а частоту дискретизации в поле ввода напечатать исходя из расчёта: f=h/(s/v), где h – высота рисунка (оно же и число сэмплов в аудио), s – длинна кардиограммы в миллиметрах, v – масштаб кардиограммы в мм/сек. Последний параметр написан на кардиограмме. На первой кардиограмме ничего не написано, но масштаб, как правило, часто составляет 25 мм/сек. Расчёты частот дискретизации в Excel для наших примеров продемонстрированы на рисунке ниже.



Как сказано выше, вводим в соответствующее поле необходимые значения частот дискретизации для каждого из примеров. Можно вводить даже десятичные доли, всё равно потом произойдёт автоматическое округление до целого.



При нажатии «OK» соглашаемся с тем, что работаем с «Unsigned 8 bit» сэмплами (будет ещё одно окошко), после чего в основном поле звукового редактора развернётся вид волны нашего файла. Заметим, что данный вид будет представлен «вверх ногами», и для полного соответствия с бумажным вариантом следует выполнить инвертирование волны в соответствующем меню. В результате это будет выглядеть так.



Вторая кардиограмма выглядит «потише», так как она изначально была не очень большая по размеру.



К сожалению, не все звуковые карты позволяют воспроизводить аудио на произвольной частоте дискретизации, точнее, подавляющее большинство вовсе не умеет. Для того чтобы корректно воспроизвести файл, необходимо выполнить функцию «Конвертировать тип сэмпла». Будем преобразовывать к ближайшему стандартному значению 8000 Гц, заодно увеличим разрешающую способность по амплитуде до 16 бит. Последнее необходимо для точности на этапе интерполяции при апсэмплинге. Если оставить 8 бит, то оставшаяся область спектра будет заполнена шумом квантования. Кстати говоря, данную процедуру можно было выполнить программно на этапе преобразования BMP-PCM, даже с применением интерполяции. Но одна из целей являлась простота программного кода.

После операции апсэмплинга можно прослушивать и наслаждаться результатом. Можно сохранить результат в стандартный wav или mp3 файл. Звучит ровно так же, как я и предполагал изначально. Ниже представлено видео, звуковой дорожкой которого (после монтажа) как раз и являются те самые аудио, которые были получены из бумажной кардиограммы. Сразу приношу извинение за качество видео и за мерцание, но у меня при текущих условиях не было экранного рекордера и нормального дисплея. Видео хотелось сделать как можно быстрее.



Комментарии (32)


  1. vlreshet
    07.08.2018 16:06
    +4

    Не могли бы куда-нибудь выложить .wav или .mp3? Слушать звук с видео не очень удобно.

    P. S. а преобразовать волну с фотки в звуковую — это круто)


    1. Boomburum
      07.08.2018 16:53
      +1

      Оптимальный вариант — залить аудио на какой-нибудь soundcloud и вставить в пост через oembed (типа как тут).


      1. R3EQ Автор
        07.08.2018 20:51
        +1

        У меня всегда возникал вопрос: существует ли сервис для аудио, который полностью подобен YouTube? Ответ: не существует. Я тоже наткнулся на Soundcloud в своё время, но, если память мне не изменяет, я столкнулся с некоторыми ограничениями.


    1. R3EQ Автор
      07.08.2018 20:53

      Я бы сделал прямую перезапись звука в процессе просмотра видео, или же извлечение звуковой дорожки заранее скаченного видео с ютуб. Звук в видеоролике в нужных местах без редактирования я подложил с оригинала.


    1. FSA
      09.08.2018 20:49

      Где-то была программа специальная чтобы специально сформированные картинки воспроизводить.


      1. R3EQ Автор
        09.08.2018 22:24

        Скорее всего вы имеете ввиду программу PhonoPaper. Она позволяет воспроизводить звук с бумаги, на которой изображён его спектральный вид («водопад»). А в моём случае на бумаге представлен волновой вид.


        1. FSA
          09.08.2018 23:23

          Да. Абсолютно верно. Тут идея, конечно, интересная, только вот вид волны уж очень низкочастотный получается. Чтобы что-то полноценно услышать нужно хотя бы 20 периодов иметь на бумаге и воспроизвести их за 1 секунду. Да и то это будет так себе звук. Если брать частоты повыше, то там портянка будет разрастаться просто в немыслимых масштабах.


          1. R3EQ Автор
            09.08.2018 23:32

            Нужна быстрая скорость воспроизведения. Были такие киноплёнки, на которых нанесена звуковая дорожка как раз по волновому принципу, и считывалась она оптическим способом через фотодатчик. Воспроизведение тем же оптическим способом применялось и для случая, когда звук представлен на носителе в спектральном виде. Как вы наверно знаете, программа PhonoPaper разработана как симулятор такого устройства.


            1. FSA
              10.08.2018 00:00

              Понятно, что звук можно записать на бумаге-плёнке. Вот только вы представляете размер плёнки хотя бы для 1 минутного ролика? В статье же звук пытается автор извлечь из нескольких десятков колебаний. Даже если они попадают в область, которую мы слышим и аппаратура воспроизводит, то длительность этого звука будет ничтожна.


  1. dlinyj
    07.08.2018 16:51
    +1

    У меня ощущение, что я покатался на машине времени. А для чего телик вместо монитора?


    1. kAIST
      07.08.2018 17:07
      +1

      Это даже интереснее самой статьи… БУ lcd монитор можно же в пределах тысячи купить...


      1. dlinyj
        07.08.2018 17:17

        Да, я бы прочитал такую статью


      1. VBKesha
        07.08.2018 21:57

        У меня долгое время был Lacie IV, и пока он не доставлял проблем менять его на абы какой LCD не хотелось, картинку он давал шикарную.


        1. R3EQ Автор
          07.08.2018 22:16

          CRT мониторы мне нравятся больше всего по передаче цвета и гладкости изображения. В ч/б мониторах положительное качество в том, что глаза гораздо меньше устают. Это касается и ТВ, где 50 Гц. но близко сидеть не рекомендуется, как показано на видео.


  1. arteast
    07.08.2018 20:30
    +2

    Тема забавная, но как-то наколеночно сделано…
    1) Зачем Excel, если есть C? Запросить 2 числа (размер в пикселях известен и так) и выдать результат — две строчки
    2) Да и зачем вообще выдавать и копировать из одних полей ввода в другие? Пусть программа сама сделает — писать wav не сильно сложнее, чем PCM. fseek в начале, fseek в конце и fwrite одну структурку, в которой надо вычислить пару-тройку полей (на пять с плюсом — не забывая про big endian машины :)
    3) чем делать бинаризацию руками, ее можно сделать в программе из серой картинки. Для такого характерного сигнала не сложнее, чем прочитать уже бинаризованный — просто найти индекс не элемента с значением 0, а с минимальным значением
    4) можно не требовать высоту именно 256 пикселей, а прочитать фактическую высоту и выравнивать результат под нее.
    4) и вообще, зачем нам серая картинка? Можно же прочитать RGB картинку, а бинаризовать только по красному каналу (в котором миллиметровка вообще практически не видна).
    На это все уйдет максимум час времени, а вот пользоваться станет в сто раз удобнее — останется только вырезать нужный фрагмент картинки (+ мазнуть ластиком по оставшимся надписям), повернуть его и экспортировать в BMP — и загнать в программу. А на выходе будет файл, который можно грузить в любой звуковой редактор без доп. настроек.


    1. R3EQ Автор
      07.08.2018 20:46

      1) Так для новичков будет нагляднее.
      2) Я знаю. Делал такое ранее, даже более сложный вариант для AVI. Но в данном случае так более понятно для некоторых читателей. Разнообразие лишним не бывает. Иначе получится сырое программирование.
      3) Можно, но цель была… читай статью ещё раз.
      4) Можно, только осторожно.
      4) Можно. А можно и не преобразовывать в BMP, а читать JPG. Подумаешь, пара-тройка функций, и готовые библиотеки чтения JPG есть. Получится полноценный продукт для конвертирования нарисованной волны в звук. Вопрос: а зачем он нужен? Кому интересно, те сами напишут, и не хуже. А остальным это не только неинтересно, но и вообще, не будут иметь представления, о чём эта статья.


      1. arteast
        07.08.2018 21:39
        +1

        Читаю заголовок "перевод бумажной кардиограммы в WAV-формат". Читаю теги — "звук, С". Читаю статью — делаем то руками, делаем это руками, делаем wav руками, делаем руками все, что только можно.
        Если рассматривать статью как практическое руководство к действию по переводу одного конкретного взятого бумажного рулончика в файл wav, то вопросов нет, кроме одного — "почему это в хабе C?". Если же считать, что целевую аудиторию интересуют вопросы программирования… связанные со звуком… может быть, с wav… и, может быть, немножко с графикой или базовым CV — то, по-моему, было бы несколько полезнее (особенно для новичков) сделать не, извините, огрызок, а чуть более законченную программу. Или, еще нагляднее и полезнее, показать ручной способ, а показать, как автоматизировать часть шагов.


  1. basilbasilbasil
    07.08.2018 21:03

    И да, это запись электрического импульса, а не самого сердца.


  1. Ryppka
    07.08.2018 22:14

    Оцифровка бумажной ЭКГ — достаточно обычное дело, для этого есть и программы, и в научных работах вопрос многократно рассматривался. А если хочется послушать «мелодию сердца», то лучше использовать модулированный сигнал, как делалось в старых системах записи ЭКГ по телефону.


    1. R3EQ Автор
      07.08.2018 22:29

      Да, есть. И не составит труда разобраться в устройстве специфического формата цифрового ЭКГ. Кажется, там ADPCM применяется. Что касается модулированного сигнала для передачи ЭКГ по телефону — не слышал. Но предполагаю, что это частотная модуляция, и я имею представление, как это бы звучало. Центральная частота, скажем, 1500 Гц и девиация, например, 1000 Гц. Можно даже реализовать такой эффект. Будет мелодично и, возможно ещё интереснее.


  1. svanichkin
    08.08.2018 10:30
    +2

    Заголовок конечно заманчивый, но содержание и подача материала… Долго пытался найти ссылки на wav, но вместо этого нашел странный ролик на youtubе из 90х – камера летает, клацают кнопки, шипит фон, а звука кардиограммы преобразованной в звук не слышно. Автор, зачем так делать?


    1. R3EQ Автор
      08.08.2018 10:35
      -2

      А что вы, собственно говоря, хотите услышать? Если вы не имеете ни малейшего представления, о чём здесь идёт речь. Читайте статью внимательнее. Если действительно вы ничего не слышите, значит низкие у вас фильтруются, или вы пытаетесь слушать на дешёвых компьютерных пищалках, на планшете или ноутбуке. Кому интересно, тот поймёт и услышит.


      1. ruslan_shv
        08.08.2018 11:25
        +1

        есть люди, которым результат важнее действий к нему приводящих и которые думаю примерно так: «если я не слышу, что в итоге получилось, зачем мне читать статью?»


        1. R3EQ Автор
          08.08.2018 11:29

          Согласен с вами. Поэтому читать не нужно.


      1. dlinyj
        08.08.2018 11:28

        Мне интересно, я понимаю, и хочу слышать. Вы писали статью чтобы посамоутверждаться, или зародить интерес? Если второе, то можно хотя бы wav приложить к статье.


        1. R3EQ Автор
          08.08.2018 11:44
          -1

          Кому надо, тот извлечёт нужный фрагмент из звуковой дорожки видео. Там в точности то же самое как и в wav. Давайте я вам пришлю эти вавки, а вы выложите и разместите ссылки.


  1. vvzvlad
    08.08.2018 10:58
    +2

    На втором рисунке изображено сразу несколько кардиограмм.

    Кардиограмма там все-таки одна. Просто несколько отведений.


    1. R3EQ Автор
      08.08.2018 11:27

      Ну да. Даже не думал, что кто-то обратит внимание на эту неточность.


  1. IvUyr
    08.08.2018 13:25

    Ммм… Тёплый ламповый телек вместо холодного транзисторного монитора!


    1. R3EQ Автор
      08.08.2018 13:30

      Транзисторный. Рядом был ламповый телек, он действительно теплее, но там серьёзные искажения растра. Нужно все кондёры менять.


      1. IvUyr
        08.08.2018 21:55

        Технически, всё-таки ламповый, в данном случае. Ведь кинескоп-то — большая радиолампа, а жк-матрицы таки состоят из матрицы транзисторов.


        1. R3EQ Автор
          09.08.2018 22:18

          Ах, точно!