Преобразуем изображение в звук — что можно услышать?

    Привет Хабр.

    В недавней публикации здесь на сайте описывалось устройство, позволяющее незрячим людям «видеть» изображение, преобразуя его с помощью звуковых волн. С технической точки зрения, в той статье не было никаких деталей вообще (а вдруг украдут идею за миллион), но сама концепция показалась интересной. Имея некоторый опыт обработки сигналов, я решил поэкспериментировать самостоятельно.



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

    Преобразуем 2D в 1D


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

    Она по своей сути похожа на фрактал, и идея в том, что при увеличении разрешения изображения, относительное расположение объектов не меняется (если объект был в верхнем левом углу картинки, то он останется там же). Различные размерности кривых Гильберта могут дать нам разные изображения: 32x32 для N=5, 64x64 для N=6, и так далее. «Обходя» изображение по этой кривой, мы получаем линию, одномерный объект.

    Следующий вопрос это размер картинки. Интуитивно хочется взять изображение побольше, но тут есть большое «но»: даже картинка 512х512, это 262144 точек. Если преобразовать каждую точку в звуковой импульс, то при частоте дискретизации 44100, мы получим последовательность длиной в целых 6 секунд, а это слишком долго — изображения должны обновляться быстро, например с использованием web-камеры. Делать частоту дискретизации выше бесмысленно, мы получим ультразвуковые частоты, неслышимые ухом (хотя для совы или летучей мыши может и пойдет). В итоге методом научного тыка было выбрано разрешение 128х128, которое даст импульсы длиной 0.37c — с одной стороны, это достаточно быстро чтобы ориентироваться в реальном времени, с другой вполне достаточно, чтобы уловить на слух какие-то изменения в форме сигнала.

    Обработка изображения


    Первым шагом мы загружаем изображение, преобразуем его в ч/б и масштабируем до нужного размера. Размер изображения зависит от размерности кривой Гильберта.

    from PIL import Image
    from hilbertcurve.hilbertcurve import HilbertCurve
    import numpy as np
    from scipy.signal import butter, filtfilt
    
    
    # Create Hilbert curve
    dimension = 7
    hilbert = HilbertCurve(dimension, n=2)
    print("Hilbert curve dimension:", dimension)  # Maximum distance along curve
    print("Max_dist:", hilbert.max_h)  # Maximum distance along curve
    print("Max_coord:", hilbert.max_x)  # Maximum coordinate value in any dimension
    
    # Load PIL image
    f_name = "image01.png"
    img = Image.open(f_name)
    width, height = img.size
    out_size = hilbert_curve.max_x + 1
    if width != out_size:
        img = img.resize((out_size, out_size), Image.ANTIALIAS)
    
    # Get image as grayscale numpy array
    img_grayscale = img.convert(mode='L')
    img_data = np.array(img_grayscale)

    Следующим шагом формируем звуковую волну. Тут разумеется, может быть великое множество алгоритмов и ноухау, для теста я просто взял яркостную составляющую. Разумеется, наверняка есть способы лучше.

    width, height = img_grayscale.size
    
    sound_data = np.zeros(width*height)
    for ii in range(width*height):
        coord_x, coord_y = hilbert_curve.coordinates_from_distance(ii)
        pixel_l = img_data[coord_x][coord_y]
    
        # Inverse colors (paper-like, white = 0, black = 255)
        pixel_l = 255 - pixel_l
    
        # Adjust values 0..255 to 0..8192
        ampl = pixel_l*32
    
        sound_data[ii] = ampl

    Из кода, надеюсь, все понятно. Функция coordinates_from_distance делает за нас всю работу по преобразованию координат (х, у) в расстояние на кривой Гильберта, значение яркости L мы инвертируем и преобразуем в цвет.

    Это еще не все. Т.к. на изображении могут быть большие блоки одного цвета, это может привести к появлению в звуке «dc-компоненты» — длинного ряда отличных от нуля значений, например [100,100,100,...]. Чтобы их убрать, применим к нашему массиву high-pass filter (фильтр Баттерворта) с частотой среза 50Гц (совпадение с частотой сети случайно). Синтез фильтров есть в библиотеке scipy, которым мы и воспользуемся.

    def butter_highpass(cutoff, fs, order=5):
        nyq = 0.5 * fs
        normal_cutoff = cutoff / nyq
        b, a = butter(order, normal_cutoff, btype='high', analog=False)
        return b, a
    
    def butter_highpass_filter(data, cutoff, fs, order=5):
        b, a = butter_highpass(cutoff, fs, order)
        y = filtfilt(b, a, data)
        return y
    
    # Apply high pass filter to remove dc component
    
    cutoff_hz = 50
    sample_rate = 44100
    order = 5
    wav_data = butter_highpass_filter(sound_data, cutoff_hz, sample_rate, order)

    Последним шагом сохраним изображение. Т.к. длина одного импульса короткая, мы повторяем его 10 раз, это будет на слух более приближено к реальному повторяющемуся изображению, например с веб-камеры.
    # Clip data to int16 range
    sound_output = np.clip(wav_data, -32000, 32000).astype(np.int16)
    
    # Save
    repeat = 10
    sound_output_ntimes = np.tile(sound_output, repeat)
    wav_name = "ouput.wav"
    scipy.io.wavfile.write(wav_name, sample_rate, sound_output_ntimes)

    Результаты


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

    Тест-1



    Изображению соответствует такой звуковой сигнал:


    WAV: cloud.mail.ru/public/nt2R/2kwBvyRup

    Тест-2



    Идея этого теста — сравнить «звучание» объекта другой формы. Звуковой сигнал:


    WAV: cloud.mail.ru/public/2rLu/4fCNRxCG2

    Можно заметить, что звучание действительно другое, и на слух разница есть.

    Тест-3



    Идея теста — проверить объект меньшего размера. Звуковой сигнал:


    WAV: cloud.mail.ru/public/5GLV/2HoCHvoaY

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

    Правка:

    Как подсказали в комментариях, можно использовать преобразование Фурье для непосредственной конвертации картинки в звук. Сделанный по-быстрому тест показывает такие результаты (картинки те же):
    Тест-1: cloud.mail.ru/public/2C5Z/5MEQ8Swjo
    Тест-2: cloud.mail.ru/public/2dxp/3sz8mjAib
    Тест-3: cloud.mail.ru/public/3NjJ/ZYrfdTYrk

    Тесты звучат интересно, по крайней мере, для маленького и большого квадратов (файлы 1 и 3) разница на слух хорошо ощутима. А вот форма фигур (1 и 2) практически не различается, так что тут тоже есть над чем подумать. Но в целом, звучание полученное с помощью FFT, на слух мне нравится больше.

    Заключение


    Данный тест, разумеется, не диссертация, а просто proof of concept, сделанный за несколько часов свободного времени. Но даже так, оно в принципе работает, и разницу ощущать на слух вполне реально. Я не знаю, можно ли научиться ориентироваться в пространстве по таким звукам, гипотетически наверно можно после некоторой тренировки. Хотя тут огромное поле для улучшений и экспериментов, например, можно использовать стереозвук, что позволит лучше разделять объекты с разных сторон, можно экспериментировать с другими способами конвертации изображения в звук, например, кодировать цвет разными частотами, и пр. И наконец, перспективным тут является использование 3d-камер, способных воспринимать глубину (увы, такой камеры в наличии нет). Кстати, с помощью несложного кода на OpenCV, вышеприведенный алгоритм можно адаптировать к использованию web-камеры, что позволит экспериментировать с динамическими изображениями.

    Ну и как обычно, всем удачных экспериментов.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 30

      +4
      Ожидал услышать подобие симфоний Баха на полноценных фотографиях :)
        +3
        Баха не обещаю, а на фотографии котика я тестировал :)

        Котэ

        WAV: cloud.mail.ru/public/5M3z/2PLtHpk6w

        В принципе, сколько-то похоже ;)

          0

          Кому как, а я разницы во всех трех звуках не услышал. Везде однотипное биение. С картинкой кота появляются ассоциации, что откуда-то выпрыгнет Чужой :)

        +3
        А почему бы хабру не добавить на сайт плеер звука идущий из коробки в html5? Я бы послушал эти изображения, а так лень по ссылкам мататься
          +5

          Как вариант.
            0
            Осталось понять, почему для этого нет соответствующих кнопочек в редакторе, даже само знание о том что можно встраивать вот так медаиконтент и даже javascript+html5 примеры — уже круто. Даже в документации об этом нет!

            По теме — преобразование изображения в звук в статье совершенно не юзабельно!
            Главное — это узнаваемость объектов при их перемещении, повороте и изменении размера. Простой обработкой именно на основе пикселов этого не сделать, хотя можно призвать на помощь генеративные нейронные сети…
              0
              Третья кнопка справа в редакторе)
                +1
                Для этого нужно залить на soundcloud файл, и да, нужно ЗНАТЬ об этой возможности.
                Я например до сих пор не запомнил, куда нужно залить пример html + javascript чтобы интегрировать его в комментарий на тот же тостер
                  0
                  Можно позвать Boomburum)
                  Был отличный пост по разметке, но интеграция с внешними ресурсами действительно упоминалась вскользь.
                    0
                    Вот постик был, кстати )
                      0
                      Да, отличный пост, помню. Но вот именно <oembed_></oembed_> тег там очень вскользь упомянут.
          +1
          Кхм, FFT для этих целей не подходит? Там вроде как даже с нотами мудрить не нужно.
            0
            Уже есть :) Сеанс передачи видео звуком через воду с разоблачением habr.com/ru/post/408871
            0

            Идея интересная, но подход, как мне кажется, не очень удачный. Человек не "слышит" саму по себе звуковую волну, он воспринимает спектр звука в ней. Получается, что когда вы преобразовываете картинку в волну, а ухо воспринимает спектр этой волны, то человек воспринимает Фурье-преобразование картинки (вытянутой в одну длинную полосу), а не саму картинку. Ну а на Фурье-преобразовании почти любая картинка превращается в бессмысленный набор полос (преобразование Фурье хорошо подходит для выделения периодически повторяющихся паттернов).


            Потому, как мне кажется, имеет смысл думать все же над преобразованием картинки в Фурье-спектр звука. Человек также хорошо воспринимает изменения спектра звука, потому он должен быть способен хорошо воспринимать движущееся изображение. Ну и возможно в качестве источника было бы лучше использовать карту глубины, а не обычное изображение.

              0
              Да, согласен, попробовать с Фурье можно. Хотя есть опасение, что на выходе получится ODFM и жужжание как у старого модема, из которого ничего не разобрать. Но может ошибаюсь.

              Карта глубин это в принципе отдельная задача. На данном этапе упрощенно можно считать, что обработанная картинка уже есть.
                0
                Я добавил звуки, сделанные с iFFT:

                Тест-1: cloud.mail.ru/public/2C5Z/5MEQ8Swjo
                Тест-2: cloud.mail.ru/public/2dxp/3sz8mjAib
                Тест-3: cloud.mail.ru/public/3NjJ/ZYrfdTYrk

                В принципе, в этом что-то есть, на слух по крайней мере, звучит приятнее.
                0

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

                • UFO just landed and posted this here
                  +2
                  Мне одному кажется, что идея одномерности звука по отношению к человеческому слуху — неверна? Человек без проблем воспринимает множество звуков одновременно. Я, например, могу безошибочно назвать расположение нот в сложном аккорде на слух, а дирижер оркестра способен услышать, как один из десятков инструментов фальшивит. Уверен, что транслировать изображение в звук можно в реальном времени, то-есть все пиксели изображения могут звучать одновременно, и при этом человек может научиться слышать каждый пиксель индивидуально. Предлагаю следующую схему:
                  1. Чтобы в центре «звуковое зрение» сделать более чётким, чем на периферии, выберем самую комфортную частоту тона для центрального пикселя: пусть это будет 2 КГц. Чем дальше пиксель находится от центра, тем частота его тона ниже.
                  2. Чтобы различать отдалённость от центра по вертикали и горизонтали, придадим звучащим пикселям следующие свойства:
                  а) чем левее пиксель, тем больше он звучит в левом наушнике, чем правее, тем его больше в правом наушнике;
                  б) чем выше пиксель, тем его тембр ближе к звуку «и», чем ниже, тем ближе к носовому звуку «м», в центре пиксели звучат как «а».
                  3. Чтобы различать цвета пикселей, добавим высокочастотный импульсный дребезг (как у звука виолончели): пусть красный дребезжит шумами в районе 7 КГц, зеленый — 8 КГц, синий — 9 Кгц.
                  4. Чтобы чувствовать глубину, можно использовать колебания тона (вибрато, как у оперных певцов): чем пиксель ближе, тем вибрато заметнее.
                  5. Ещё можно использовать имитацию реверберации (восприятие отражений звука), но я пока не придумал для чего.
                  6. Обучать человека можно постепенно: сначала лишь небольшое количество черно-белых звучащих пикселей без глубины (скажем, 4х4=16), дальше постепенно увеличиваем, потом добавляем «цвет», а позже — «глубину».
                    0
                    Зачем верх\низ кодировать конкретными формантами? Это же можно делать фазой и эквалайзером, как давно в звукозаписи делают.
                      0
                      Мне кажется, что кодирование фазой и эквалайзером приведёт к тому, что симметричные по вертикали пиксели будут плохо отличимы на слух. Хотя, я не звукорежиссёр, могу ошибаться. Можете привести пример такого эффекта?
                      Более того, я нашёл печальный изъян в предложенной мною схеме: симметричные по горизонтали пиксели будут сливаться на слух! Эту проблему я предлагаю решить при помощи реверберации (имитации отражения волны от воображаемых стен слева и справа), а также при помощи имитации задержки волны из-за разнесения ушей в пространстве. По-идее, это должно решить проблему.
                        0
                        Тут, конечно, надо думать долго и серьёзно, но, на вскидку, я виже задачу так. Картинку надо однозначно брать с привязкой к карте глубины, временнУю раскладку делать не слева-направо, а от переднего плана к заднему(по карте глубины), «звуки пикселей» в одном плане воспроизводятся одновременно, при этом амплитуда зависит от яркости пикселя из обычной картинки, а частота от цвета(но не факт что это не перегрузит восприятие), лево-право рулится раскладкой по стерео, верх-низ эквализацией.

                        Вертикальная (высотная) локализация
                        Способность опре­делять направление прихода звука в вертикальной плоскости у человека развита значительно слабее, чем в горизонтальной. Она составляет 10-15° (по сравнению с 3° в горизонтальной). Эту способность связывают обычно с ориентацией и формой ушных ра­ковин. Ушная раковина действует как фильтр, внося максимальные искаже­ния в области 6-16 кГц, при­ чем форма этих искажений зависит от того, спереди или сзади находится источник звука и под каким углом подъема он расположен в медианной плоскости.


                        Это всё надо моделировать, делать различные примеры и думать, ну и надо учитывать неплохую гибкость человеческого мозга, если долго тренироваться, то можно научиться слышать очень многое.
                    +1

                    3B1B давно об этом показывал
                    https://youtu.be/3s7h2MHQtxc

                      +1
                      Напомнило вот это: habr.com/ru/post/220061
                      habr.com/ru/company/intel/blog/251701
                      У PhonoPaper есть режим проигрывания всего, что видно на экране.
                        0
                        Кто бы раньше мог подумать, что звуки можно рисовать. Интересно, как бы выглядела какая то композиция в виде набора изображений или же в виде одного изображения.
                          +1
                          Мне кажется, что для этого лучше подойдёт HRTF — естественно уже после того, как программно будет получена полноценная карта глубины с распознанными объектами на ней. Различие от естественного звукового фона будет заключаться в том, что:
                          1) можно фильтровать (вычленять) отдельные звуки и объекты, отделяя значимое от незначимого,
                          2) можно фильтровать реверберацию, улучшая распознавание (как это уже делают при распознавании голоса),
                          3) можно кодировать объекты не просто различными тонами, а непосредственно словами,
                          4) объекты будут не просто озвучиваться — а озвучиваться как минимум с 2D-позиционированием (используя сдвиги фаз в первую очередь),
                          5) можно озвучивать в том числе и объекты сзади,
                          6) можно контролировать количество одновременных аудио-визуализируемых объектов и озвучивать их последовательно, а не одновременно,
                          7) можно использовать данные из ГИС.
                            0
                            3) можно кодировать объекты не просто различными тонами, а непосредственно словами

                            Думаю при таком развитии у подобных устройств есть будущее, потому что кодирование тонами уж очень специфично. Надо обладать хорошим слухом, чтобы различать небольшие изменения тона, плюс пока мозг сообразит за каким тоном что закодировано… Как по мне это долго и для обучения, и для пользования. А вот озвучка словами в реальном времени даст больше развития технологии. Ну или упростит ее явно для потребителя.
                            0
                            Эмм. Я себе это представлял несколько иначе. Быстрее всего там прикручено распознавание образов. Идешь ты такой — а тебе в ухо: «осторожно табуретка», или «аккуратно невысокая ступенька», или «вы подошли к светофору — цвет сигнала красный». Смысл этой системы — помощь в виде ассистента или поводыря. А у вас это будет какофония в виде шума, сменяющегося, к тому же, раз в 0.37 секунды. Ориентироваться в пространстве с помощью данной штуки будет нереально. Уж лучше прикрутить китайский ультразвуковой дальномер за 1.5$ к ардуине за 10$ и преобразовывать показания расстояния в слышимый звук. Так что, скорее всего, у авторов из той статьи все работает именно как я тут описал.
                              0
                              А как мы в повседневной жизни ориентируемся глазами? Это же мешанина цветов, меняющаяся несколько десятков раз в секунду.
                              Но ведь младенцы с течением времени учатся распознавать в этой мешанине отдельные образы и объекты. Так и со звуковым описанием, мозг в итоге научится распознавать отдельные объекты, если в описании будут закономерности.
                              0
                              Присоединюсь к мысли, что перевод в одномерность двумерной (а вообще трехмерной) картинки — абстракция чуждая нашему мозгу. Не спорю, натренироваться можно, но очень это не естественно.

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

                              Дальше можно продвинуться в сторону множества объектов — каждый объект озвучивается независимо и складывается в общею звуковую картинку. Сложный объект обрабатывается как несколько близкорасположеных простых.

                              Наверное так будет проще «услышать» картинку.

                              Only users with full accounts can post comments. Log in, please.