Как использовать группу ЭЭГ и мобильное приложение для доступа к вашему мозгу

Как использовать группу ЭЭГ и мобильное приложение для доступа к вашему мозгу

17 мая 2022 г.


Из этой статьи вы узнаете, как вы можете получить доступ к своему мозгу из своего приложения по цене мобильного телефона среднего уровня, купив группу ЭЭГ и приложение, с помощью которого вы можете получать необработанные данные ЭЭГ из Устройство.


Я проведу вас через разработку приложения, с помощью которого вы сможете обнаруживать моргание с помощью [диапазона ЭЭГ Muse S] (https://choosemuse.com/muse-s/). Мы преобразуем моргание в текст с помощью азбуки Морзе. В результате у нас будет решение, с помощью которого полностью парализованные люди смогут общаться со своими близкими.


Я также продемонстрирую, как можно создать приложение на чистом Python с помощью Kivy, в результате чего получится программа, которую можно упаковать на Android, iOS, Windows и Mac.


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


Предыстория


Мой первый контакт с мозговыми волнами


Вернемся на 30 лет назад во времени.


Я сидел перед своим компьютером Commodore 64 в своей комнате. Мой брат к тому времени уже съехал, но я был не один, со мной был и мой друг Саби.


Я любил компьютерные игры. Игра в такие игры, как Ugh Olympics, Pirates, Defender of The Crown, Boulder Dash, Wizard of Wor, Nebulus и Bruce Lee доставляла мне больше удовольствия, чем что-либо еще в мире.


В то время я играл в недавно открытую игру под названием Бенджи. Я безуспешно пытался понять, как играть в эту игру.


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


Черная фигура парила в воздухе над крышей нашего гаража.


Я чертовски испугался и спросил Саби, видел ли он фигуру или нет.


Нет! Там ничего нет. - он ответил.


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


Помню, они спросили, как меня зовут. Я начал думать, но не мог ответить, так как не мог вспомнить.


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


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


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


Следующее мое воспоминание – это больница. Через несколько часов медсестра провела меня в палату, смазала крохотные штучки охлаждающим гелем, затем надела мне на голову причудливую шапочку. Шляпа была странной, так как из нее выходило много проводов, все они были подключены к машине.


Пришлось лечь и сохранять спокойствие, а потом машина рисовала линии на бумаге.


Как я узнал позже, это были мои мозговые волны, а аппарат был прибором для электроэнцефалографии (ЭЭГ). Я не мог понять диаграмму ЭЭГ, но, судя по тому, что я слышал, тогда они выглядели довольно плохо.


Через пару дней я уже мог ехать домой.


Мне не разрешали играть на компьютере или смотреть телевизор, и я не мог пойти на дискотеку с друзьями.


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


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


Я до сих пор помню запах комнаты, ощущение холодного геля, длинные провода, маленькие диоды, странную шляпу и нарисованные на бумаге кривые ЭЭГ.


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


Мой второй контакт с мозговыми волнами


Год 1994, всего через два года после моего эпилептического припадка. Мои родители записали меня и моего брата Томи на курс Сильва по управлению разумом для детей.


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


Четыре года спустя я посетил тренинг по управлению разумом по методу Сильва вместе с моим другом Эдитом. К тому времени я понял и выучил многие техники, которым там обучали.


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


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


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


Я не мог сказать, действительно ли я был в альфе или нет. Подробнее об этом позже.


Через несколько лет я поступил в Будапештский технологический университет (BME), а через два года стал ученым.


Научный означает, что я не верю ни во что, кроме того, что доказано наукой. Благодаря этому я был уверен, что все методы Сильва были фальшивыми, как и все другие сверхъестественные вещи, о которых я слышал.


Мой третий контакт с мозговыми волнами


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


Я знаю, это звучит смешно, но тогда это была моя реальность.


Мне понадобились два психолога, 2 психотерапевта, тренер RED EQ, поддержка семьи и друзей, но, наконец, мне удалось вернуться.


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


Кроме того, к настоящему времени я стал ученым. Научный означает, что я верю в то, что говорят люди, и пытаюсь проверить это, разговаривая с этим человеком и используя несколько научных методов.


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


Моя Muse S прибыла три недели назад, но до ее прибытия у меня уже возникла идея, в которой я мог бы совместить программирование и свои мозговые волны. Прежде чем я перейду к сути, позвольте мне рассказать вам о том, как я вдохновился на создание своего первого приложения, управляемого разумом.


Вдохновение


Я гуглил различные приложения, разработанные для группы Muse, но понял, что приложений почти нет, или, по крайней мере, их нелегко найти через Google. К счастью, я нашел статью [Ануш Мутьяла] (https://anushmutyala.medium.com/) с заголовком [Muse 101 — Как начать разработку с помощью Muse 2 прямо сейчас] (https://anushmutyala.medium.com). /muse-101-как-начать-разработку-с-muse-2-прямо сейчас-a1b87119be5c).


Ануш разработал слайд-шоу без помощи рук, в котором можно перемещаться с помощью моргания глаз. Он также мог переключать вкладки Chrome, используя моргание и прокрутку, измеряя фокус / концентрацию пользователя, используя только необработанные данные ЭЭГ. Он даже сделал видео, обобщающее решения, основанные на мозговых волнах.


Помимо статьи Ануш, я нашел увлекательный проект. Ученые из Калифорнийского университета в Сан-Франциско (UCSF) [разработали решение] (https://www.bbc.com/news/science-environment-52094111), способное распознавать слова/предложения с точностью 96%.


Есть некоторые недостатки их решения:


  1. Количество распознаваемых предложений ограничено 30-50 предложениями.

  1. Насколько я знаю, их решение не с открытым исходным кодом.

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


Они [опубликовали свою исследовательскую работу] (https://www.nature.com/articles/s41593-020-0608-8.epdf) в журнале Nature Neuroscience.


Итак, в конце концов, эти проекты вдохновили меня начать свое путешествие в области интерфейсов мозг-компьютер (BCI).


Идея


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


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


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


Несмотря на это, проект по-прежнему ценен по следующим причинам.


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

  1. Существует множество различных ЭЭГ-устройств, и моя цель — поддерживать многие из них. Как только вы получаете необработанные данные ЭЭГ, уже не имеет значения, с какого устройства они поступили.

  1. Это проект с открытым исходным кодом, и я надеюсь, что пара энтузиастов внесет свой вклад в проект.

  1. Это мой первый шаг в области интерфейсов мозг-компьютер. Учебный проект, из которого я узнаю о мозговых волнах, Python и фреймворке Kivy.

  1. Я предлагаю решение, с помощью которого могут общаться полностью парализованные люди по цене телефона среднего уровня (400 евро). Мой проект с открытым исходным кодом и бесплатный, но для него требуется браслет Muse (я рекомендую Muse S) и приложение Mind Monitor.

  1. Его можно использовать в полной темноте, так как камера не нужна.

У нас есть вдохновение, идея, так что пора ставить цель.


Цель


В последнее время я обычно устанавливаю для себя цели HSMART, которые являются моим расширением концепции целей SMART. Вот значения букв:


  • Хуманиш: Это должно быть что-то, что делает этот мир немного лучше, и хотя бы небольшая часть человечества может извлечь из этого пользу.

  • Specific: Цель должна быть ясной и конкретной.

  • Мизмеримый: чтобы отслеживать мой прогресс и сохранять мотивацию, прогресс должен быть измеримым.

  • Достижимо: Цель должна быть реалистичной. Нет особого смысла ставить перед собой нереальную цель.

  • Rактуально: цель должна иметь для вас значение. Если вы работаете над чем-то, что не имеет отношения к вашей текущей ситуации, вам будет сложно найти мотивацию.

  • **Привязанность ко времени: без дедлайна вы можете быстро потерять фокус. Закон Паркинсона прямо выражает это: «работа расширяется, чтобы заполнить время, доступное для ее завершения». Из этого легко понять, что если у вас нет дедлайна, вы можете работать вечно без какого-либо реального прогресса в выполнении вашей задачи.

Итак, давайте посмотрим на мою конкретную цель HSMART:


  • Человеческий: Я считаю, что интерфейсы мозг-компьютер (BCI) могут сделать мир лучше, если их использовать во благо. Наличие фреймворка, который можно использовать для разработки приложений на основе BCI, и решения, с помощью которого парализованные люди могут общаться со своими близкими, безусловно, гуманно.

  • Sспецифический: я хочу разработать приложение, с помощью которого полностью парализованные люди смогут общаться с другими. В дополнение к этому я хочу разработать фреймворк, с помощью которого любой разработчик сможет запустить свой мозговой проект.

  • Mизмеримый: я определил несколько этапов для измерения своего прогресса

  1. Получите данные RAW с Muse

  1. Отображение живых мозговых волн

  1. Обнаружение моргания с помощью мозговых волн

  1. Классифицировать обнаруженные моргания по их продолжительности

  1. Преобразуйте моргание в текст с помощью азбуки Морзе.

  1. Дизайн пользовательского интерфейса мобильного приложения

  1. Разработайте приложение

  1. Напишите статью для участия в Hashnode Writeathon

  • Aдостижимая: Учитывая, что у меня есть работа на полный рабочий день и семья, сроки очень жесткие, но все же достижимые. У меня есть время для проекта, когда мой сын спит, что означает \~2 часа утром и 2-3 часа вечером, и 8-10 часов в выходные. В будние дни я всегда провожу \~2 часа с сыном, когда прихожу с работы. В выходные мы делим день на блоки по 1-2 часа. Один блок проводит время вместе, а другой блокирует время для меня. Мы повторяем это с утра до вечера, так что мы проводим много времени вместе, и у каждого есть время, чтобы сосредоточиться на своих делах.

  • Rактуально: я очень заинтересован в том, чтобы заняться интерфейсами мозг-компьютер (BCI). Недавно я посетил курс анализа данных в качестве экстерната в Будапештском университете экономики и технологий (BME). Мы изучаем фундаментальный анализ данных, машинное обучение (ML) и глубокое обучение. Я обязательно применю свои недавно полученные знания на практике в этом проекте.

  • **Время ограничено: с момента получения Interaxon Muse S у меня есть 3 недели.

  • Одна неделя, чтобы узнать о мозговых волнах и разработать структуру.

  • Одна неделя для реализации алгоритма обнаружения моргания.

  • Одна неделя на создание мобильного приложения и написание статьи для участия в Hashnode Writeathon.

У нас есть цель HSMART, поэтому пришло время начать наш проект и выбрать технологии.


Выбор технического стека


Поскольку Python — язык программирования номер один для анализа данных и машинного обучения, выбор был почти очевиден. За исключением нескольких скриптов, я не использовал Python в своей карьере, так что это будет мой первый проект Python. Согласно индексу TIOBE, Python — самый популярный язык программирования, к тому же его легко освоить, поэтому я выбрал Python.


Сначала я хотел разработать веб-приложение и выбрал Anvil Works в качестве основы для разработки, так как с его помощью вы можете создать и разместить веб-приложение в кратчайшие сроки.


Читая руководства, я понял, что мне нужно обмениваться данными с устройством Muse, что может быть проблематично из браузера. Мне понадобится не просто интерфейс, а реализация бэкэнда. Для связи с Muse настоятельно рекомендуется делать это в локальной сети, что означает, что я должен размещать свой бэкэнд локально.


Немного подумав, я понял, что для моей задачи больше подходит мобильное/десктопное приложение. Немного погуглив и сравнив, я решил использовать [Kivy] (https://kivy.org/).


Kivy — это бесплатная кроссплатформенная библиотека Python с открытым исходным кодом для быстрой разработки приложений, использующих инновационные пользовательские интерфейсы, такие как мультитач-приложения, и даже с ускорением на графическом процессоре.


Поскольку у меня не было возможности изучить интерфейсный фреймворк, такой как Angular, за несколько дней, меня озарила идея разработки мобильного приложения на чистом Python.


Однако после поиска в Google я обнаружил, что у Muse есть SDK (одна из основных причин, по которой я заказал Muse). Когда я обратился в службу поддержки Interaxon за ссылкой, мне сказали, что на данный момент SDK в открытом доступе нет, поэтому мне пришлось искать другое решение.


К счастью, я нашел Mind Monitor, который подключается к Muse и получает данные RAW, и он даже может передавать их с помощью [протокола Open Sound Control (OSC)] (https://en.wikipedia.org/wiki/Open_Sound_Control) как UDP-пакеты.


Из-за этого pythonosc был простым выбором для получения данных ЭЭГ в реальном времени.


Этого достаточно из стека технологий. Приступим к реализации решения.


Знакомство с Interaxon Muse S


Muse S — это 4-канальный диапазон, что означает, что вы можете измерять сигналы в 4 разных точках на голове. Это AF7, AF8, TP9 и TP10. AF7 и AF8 расположены на передней части черепа, а TP9 и TP10 — на затылке. Чтобы узнать больше, просто прочитайте [описание системы 10-20 ЭЭГ в Википедии] (https://en.wikipedia.org/wiki/10%E2%80%9320_system_(EEG)).


Вы должны знать, что ученый из Калифорнийского университета в Сан-Франциско использовал 120-200 каналов ЭЭГ, а у нас их всего 4. Но я полностью согласен с этим, так как наличие большего количества каналов поначалу было бы ошеломляющим. Наличие такого лимита вдохновляет меня на творчество, а благодаря цене в 379,99 евро он доступен всем, кто хотел бы начать разработку решений на основе интерфейса мозг-компьютер (BCI).


Тем не менее, я почти уверен, что на какое-то время четырех каналов будет достаточно. Я уже нашел устройство, которое, вероятно, станет следующим устройством ЭЭГ, которое я буду использовать. Это [комплект EPOC Flex Saline Sensor Kit] (https://www.emotiv.com/product/epoc-flex-saline-sensor-kit/), который имеет 32 канала, но стоит в четыре раза дороже, чем Muse S. (1800 долларов).


Скорее всего, я получу это только в том случае, если найду сторонников для этого проекта или в случае, если я выйду за пределы Muse S.


Muse имеет ранее упомянутые 4 канала и 2 усиленных канала Aux в спецификации. Он имеет частоту дискретизации 256 Гц и разрешение 12 бит/выборку, что кажется более чем достаточным, как обычно, нас интересуют только дельта (0,5–4 Гц), тета (4–8 Гц), альфа (8–13 Гц), бета (13–13 Гц). 32 Гц) и гамма (32–100 Гц). Для получения дополнительной информации [проверьте эту страницу] (https://choosemuse.com/blog/a-deep-dive-into-brainwaves-brainwave-frequencies-explained-2/).


Группа ЭЭГ также имеет гироскоп, акселерометр, датчик PPG (который может измерять частоту сердечных сокращений) и термистор.


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


Этого более чем достаточно о группе Muse S, и пришло время замарать руки и написать код.


Реализация


Это мой первый настоящий проект на Python, поэтому я уверен, что мой код довольно беспорядочный, в основном потому, что я сосредоточился на быстрых результатах.


Но вот одно из реальных преимуществ разработки с открытым исходным кодом. Я могу получить отзывы о своем коде и даже предложения по изменению кода в запросах на включение. Так что я уверен, что на это потребуется всего несколько недель, и этот проект станет хорошей отправной точкой, если кто-то захочет внести свой вклад в открытый исходный код, изучить Python или разработать интерфейс мозг-компьютер (BCI). Я лично позабочусь о том, чтобы это было доброе и поддерживающее сообщество.


Однако Python — это язык сценариев, он также поддерживает объектно-ориентированную разработку, поэтому большая часть моего кода объектно-ориентирована, но не весь код. Мне еще нужно найти баланс.


Реализация классов данных


Я создал несколько модулей Python. Одним из них является eeg_commons, который содержит общие данные, которые можно получить из диапазона ЭЭГ. Помимо необработанных данных ЭЭГ, он также поддерживает данные гироскопа и акселерометра, которые можно использовать в других приложениях.


Я также создал класс WindowedSeries и EEGSeries для построения графика данных и получения медианы.


из enum импортировать Enum


из статистики, импортное среднее, медиана


импорт даты и времени


тип данных класса (перечисление):


ЭЭГ = 1


ГИРОСКОП = 2


АКСЕЛЕРОМЕТР = 3


класс EEGChannel (перечисление):


АФ7 = 1


АФ8 = 2


ТР9 = 3


ТР10 = 4


ВСПОМОГАТЕЛЬНЫЙ = 5


класс EEGChannelMapping:


def init(я, *аргументы):


self.index_to_channel = {}


self.channel_to_index = {}


def add_mapping (я, индекс, канал):


self.index_to_channel[index] = канал


self.channel_to_index[канал] = индекс


def get_channel (я, индекс):


вернуть self.index_to_channel[индекс]


def get_index (я, канал):


вернуть self.channel_to_index[канал]


Данные класса (объект):


def init(я, тип_данных):


self.creation_time = datetime.datetime.now()


self.type = тип_данных


класс ЭЭГ (данные):


@классметод


def create_eeg_data_map (cls, channel_mapping, data_tuple):


data_per_channel = {}


для idx данные в enumerate(data_tuple):


data_per_channel[channel_mapping.get_channel(idx)] = данные


вернуть data_per_channel


def init(я, eeg_data_map):


super(EEG, self).init(DataType.EEG)


self.data_per_channel = eeg_data_map


def get_channel_value (я, eeg_channel):


вернуть self.data_per_channel[eeg_channel]


определите канал_счетчик (я):


вернуть len(self.data_per_channel)


защита get_channels (я):


вернуть self.data_per_channel.keys()


класс Гироскоп (данные):


def init(я, *аргументы):


super(гироскоп, сам).init(DataType.GYROSCOPE)


self.x = аргументы [0]


self.y = аргументы [1]


self.z = аргументы [2]


защита get_up_down_location (я):


вернуть себя.x


деф get_tilt (я):


вернуть себя.у


класс Акселерометр (данные):


def init(я, *аргументы):


super(акселерометр, self).init(DataType.ACCELEROMETER)


self.x = аргументы [0]


self.y = аргументы [1]


self.z = аргументы [2]


защита get_left_right_pitch_acc (я):


вернуть себя.x


защита get_up_down_acc (я):


вернуть себя.у


защита get_left_right_acc (я):


вернуть self.z


класс WindowedSeries:


def init(я, размер_окна):


само.элементы = []


self.window_size = размер_окна


def add_element (я, элемент):


self.elements.append(элемент)


если self.window_size == len(self.elements):


дель (сам.элементы[0])


деф get_average (я):


если len(self.elements) == 0:


вернуть 0


возвращаемое значение (self.elements)


защита get_median (я):


если len(self.elements) == 0:


вернуть 0


вернуть медиану (self.elements)


класс EEGSСерия:


def init(self, eeg_channels, series_length):


self.time_series = {}


self.last_stamp = Нет


для канала в eeg_channels:


self.time_series[канал] = WindowedSeries(series_length)


определение добавить (я, eeg_data):


если self.last_stamp не равен None и (eeg_data.creation_time - self.last_stamp).total_seconds() < 0:


print('Данные из прошлого: ' + str((eeg_data.creation_time - self.last_stamp).total_seconds() * 1000))


возврат


еще:


self.last_stamp = eeg_data.creation_time


каналы = eeg_data.get_channels()


для канала в каналах:


self.time_series[канал].add_element(eeg_data.get_channel_value(канал))


def get_median (я, канал):


вернуть self.time_series[канал].get_median()


класс EEGConverter:


def init(я, преобразователь):


self.converter = конвертер


преобразование по определению (я, данные):


convert_data = {}


для канала в data.data_per_channel.keys():


convert_data[канал] = self.converter.apply(data.data_per_channel[канал])


вернуть ЭЭГ (converted_data)


Реализация обработчика Muse Band


Для связи с Muse band я внедрил многопоточность, чтобы основной поток не блокировался при получении данных устройства.


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


После того, как мы запустим плагин Muse, он начнет прослушивать указанный порт UDP, чтобы получить данные из диапазона ЭЭГ через pythonosc.


из диспетчера импорта pythonosc


из pythonosc импортировать osc_server


из eeg_commons.eeg_commons импортировать ЭЭГ, гироскоп, акселерометр, EEGChannelMapping, EEGChannel


из потокового импорта Thread


адреса = []


класс MuseEEGChannelMapping (EEGChannelMapping):


защита init(сам):


супер(MuseEEGChannelMapping, self).init()


self.add_mapping(0, EEGChannel.TP9)


self.add_mapping(1, EEGChannel.AF7)


self.add_mapping(2, EEGChannel.AF8)


self.add_mapping(3, EEGChannel.TP10)


self.add_mapping(4, EEGChannel.AUX)


MUSE_EEG_CHANNEL_MAPPING = MuseEEGChannelMapping()


класс MuseEEG(ЭЭГ):


def init(я, *аргументы):


super(MuseEEG, self).init(EEG.create_eeg_data_map(MUSE_EEG_CHANNEL_MAPPING, args[0]))


класс Муза:


eeg_channels = [EEGChannel.AF7, EEGChannel.TP9, EEGChannel.TP10, EEGChannel.AF8, EEGChannel.AUX]


def init(я, ip, порт):


self.ip = ip


self.port = порт


self.listener_thread = Нет


self.server = Нет


self.listeners = {}


def add_listener (я, data_type, data_arrived_func):


если data_type не в self.listeners.keys():


self.listeners[data_type] = []


self.listeners[data_type].append(data_arrived_func)


def notify_listeners (я, данные):


если data.type в self.listeners.keys():


для обратного вызова в self.listeners[data.type]:


обратный вызов (данные)


обработчик def(self, address: str, *args):


если address.endswith('eeg'):


self.notify_listeners (MuseEEG (аргументы))


если адрес не в адресах:


address.append(адрес)


печать (адрес)


raw_entry = строка (адрес) + ':'


для аргумента в аргументах:


raw_entry += "," + строка (аргумент)


печать (необработанная_запись)


def start_muse_listening (я):


disp = диспетчер.Диспетчер()


disp.map("/*", self.handler)


print("Подключение к " + self.ip + ":" + str(self.port))


self.server = osc_server.ThreadingOSCUDPServer((self.ip, self.port), disp)


распечатать("Подключено")


self.server.serve_forever()


деф старт(сам):


self.listener_thread = Thread (цель = self.start_muse_listening, daemon = True)


self.listener_thread.start()


деф стоп(сам):


print('Выключить сервер OSC')


self.server.shutdown ()


Вот и все. С помощью этих нескольких десятков строк кода мы можем получить все данные из диапазона ЭЭГ Muse.


Давайте поговорим о более интересных вещах.


Обнаружение и классификация морганий


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


Глазное яблоко действует как диполь с положительным полюсом, ориентированным вперед (роговица), и отрицательным полюсом, ориентированным назад (сетчатка). Благодаря этому это сильно влияет на наши данные ЭЭГ.


Вот различные типы моргания и то, как они появляются на нашей диаграмме ЭЭГ. Обычное моргание: ![Обычное моргание]


Короткое моргание: ![Короткое моргание]


Длинное моргание: ![Долгое моргание]


Я даже создал короткое видео, демонстрирующее, как меняются обнаруженные мозговые волны, когда мы двигаем глазами, моргаем и сжимаем челюсти.


https://www.youtube.com/watch?v=VOASXIFvV_o


Алгоритм обнаружения прост. После некоторого наблюдения я понял, что моргание приводит к значительному падению, затем к небольшому подъему сигнала ЭЭГ, а время между падением и подъемом и есть продолжительность моргания.


Вот код обнаружения:


def detect_blink (я, данные):


self.eeg_series_lock.acquire()


base_level = self.eeg_series.get_median(CHANNEL_USED_FOR_DETECTION)


self.eeg_series_lock.release()


channel_value = data.get_channel_value (CHANNEL_USED_FOR_DETECTION)


если значение канала > self.max:


self.max = значение_канала


если (channel_value < base_level - BLINKING_START_FALL) и (self.blinking_start_time равно None):


self.blinking_start_time = datetime.datetime.now()


если self.pause_timer не None:


self.pause_timer.cancel()


если (self.blinking_start_time не равно None) и (channel_value > base_level + BLINKING_STOP_RISE):


blinking_end_time = datetime.datetime.now()


blink_length = (мигание_конец_время - self.мигание_начало_время).Всего_секунд() * 1000


мигание = BlinkDetector.classify_blink(blink_length)


для обратного вызова в self.blink_listener_callbacks:


обратный вызов (мигание, длина мерцания)


если мигать == мигать.VERY_LONG_BLINK:


Сброс конверсии


self.blinks.clear()


еще:


self.blinks.append(мигание)


self.blinking_start_time = Нет


если мигает == Blink.SHORT_BLINK или мигает == Blink.LONG_BLINK:


self.pause_timer = Таймер(1, self.pause_detected, args=['Обнаружена пауза'])


self.pause_timer.start()


После моргания я могу классифицировать их по длине. Я экспериментировал с разной продолжительностью моргания и на основе этого определил пороги.


Есть нормальные мигания, которые очень короткие. Есть короткие моргания, которые немного длиннее, чем естественные моргания.


Затем следует долгое мигание и очень долгое мигание.


Вот код классификации:


определение classify_blink (blink_length):


если blink_length < NORMAL_SHORT_BLINK_BORDER:


мигать = мигать.NORMAL_BLINK


Элиф blink_length < SHORT_LONG_BLINK_BORDER:


мигать = мигать.SHORT_BLINK


Элиф blink_length < LONG_VERY_LONG_BLINK_BORDER:


мигать = мигать.LONG_BLINK


еще:


мигать = мигать.VERY_LONG_BLINK


вернуться мигать


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


У нас есть почти вся логика, и мы можем приступить к реализации нашего мобильного приложения с помощью Kivy. Но перед этим давайте набросаем наш пользовательский интерфейс.


Набросок пользовательского интерфейса


Всякий раз, когда мне нужно нарисовать диаграмму, создать макет пользовательского интерфейса или создать карту разума, мой универсальный инструмент — это [draw.io] (https://draw.io).


Draw.io бесплатен и содержит множество гибких элементов, которые вы можете использовать для создания всего, что захотите.


Итак, вот мой мокап:


Наконец, мы можем начать использовать Kivy для реализации нашего пользовательского интерфейса.


Реализация пользовательского интерфейса с помощью Kivy


В [Kivy макеты] (https://kivy.org/doc/stable/gettingstarted/layouts.html) используются для размещения виджетов внутри компонента. Если вы когда-либо работали с интерфейсным фреймворком, вы, вероятно, уже знаете это.


У меня есть опыт работы с C#, Java Swing и Windows Forms в отношении внешнего интерфейса. Большинство из них уже устарели, но большинство интерфейсных фреймворков имеют сходство.


Разделим основной виджет на верхнюю и нижнюю части с помощью BoxLaxout. Верхняя часть также представляет собой BoxLayout, который будет содержать две метки и TextInputs. Опять же, если вы когда-либо работали с интерфейсным фреймворком, вы уже знакомы с большинством виджетов, которые можно использовать. По крайней мере, я почти уверен, что вы использовали метки и поля ввода текста.


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


Пользовательский интерфейс можно создать с помощью кода Python или [языка дизайна Kivy kv] (https://kivy.org/doc/stable/guide/lang.html).


Я создал свой пользовательский интерфейс, используя код Python. Вот:


класс MainWidget (BoxLayout):


def init(я, **kwargs):


super(MainWidget, self).init(**kwargs)


self.ориентация = 'вертикальный'


self.morse_code = ''


self.converted_text = ''


Окно.clearcolor = (1, 1, 1, 1)


self.top_panel = BoxLayout (ориентация = 'вертикальный', size_hint = (1,0, 0,5))


self.padding = (15, 15, 15, 15)


self.color = (1, 1, 1, 1)


self.ориентация = 'вертикальный'


self.add_widget(self.top_panel)


self.morse_code_label = Метка (текст = 'Азбука Морзе', font_size = NORMAL_FONT_SIZE, size_hint = (Нет, 0,1),


halign='левый', цвет=(0, 0, 0, 1))


self.top_panel.add_widget (self.morse_code_label)


self.current_code = TextInput (многострочный = False, font_size = NORMAL_FONT_SIZE, size_hint = (Нет, 0,1))


self.current_code.readonly = Истина


self.top_panel.add_widget (self.current_code)


self.output_text = Label(text='Текстовый вывод', font_size=NORMAL_FONT_SIZE, size_hint=(Нет, 0,1),


halign='левый', цвет=(0, 0, 0, 1))


self.top_panel.add_widget(self.output_text)


self.text_output = TextInput (многострочный = True, font_size = NORMAL_FONT_SIZE, size_hint = (1,0, 0,7))


self.text_output.readonly = Истина


self.top_panel.add_widget (self.text_output)


self.bottom_panel = GridLayout (size_hint = (1,0, 0,5), столбцы = 6, строки = 6)


self.add_widget (self.bottom_panel)


для имени член в азбуке Морзе.members.items():


если имя.начинается с('N_'):


текст = член.код + ' ' + имя[2:]


еще:


текст = член.код + ' ' + имя


распечатать('текст: ' + текст)


self.bottom_panel.add_widget (Ярлык (текст = текст, font_size = LARGE_FONT_SIZE, цвет = (0, 0, 0, 1)))


И вот результат:


Blinkish to Textish App Kivy Frontend.JPG Это могло бы выглядеть лучше, но моя основная цель создать полезное приложение с открытым исходным кодом, меня это вполне устраивает. Он делает то, что должен делать.


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


Реализация преобразования Eyeblink в текст с помощью азбуки Морзе


Вот перечисление азбуки Морзе:


класс MorseCode (перечисление):


А = ('а', '.-')


В = ('б', '-...')


С = ('с', '-.-.')


Д = ('д', '-..')


Е = ('е', '.')


F = ('f', '..-.')


G = ('г', '--.')


Н = ('ч', '....')


я = ('я', '..')


J = ('j', '.---')


К = ('к', '-.-')


L = ('l', '.-..')


М = ('м', '--')


N = ('n', '--')


О = ('о', '---')


Р = ('р', '.--.')


Q = ('q', '--.-')


R = ('r', '.-.')


S = ('s', '...')


Т = ('т', '-')


У = ('и', '..-')


V = ('v', '...-')


W = ('w', '.--')


Х = ('х', '-..-')


Y = ('y', '-.--')


Z = ('z', '--..')


N_1 = ('1', '.----')


N_2 = ('2', '..---')


N_3 = ('3', '...--')


N_4 = ('4', '....-')


N_5 = ('5', '.....')


N_6 = ('6', '-....')


N_7 = ('7', '--...')


N_8 = ('8', '---..')


N_9 = ('9', '----.')


N_0 = ('0', '-----')


def init(я, символ, код):


self.character = персонаж


селф.код = код


@классметод


def get_character (cls, азбука Морзе):


для имени член в азбуке Морзе.members.items():


если member.code == morse_code:


вернуть член.персонаж


возврат Нет


Преобразование происходит следующим образом:


Если мы обнаруживаем короткое мигание, мы преобразуем его в «.» а если у нас длинное мерцание, мы конвертируем его в символ «-». Как только мы не фиксируем моргание в течение 1 секунды, мы трансформируем наши азбуки Морзе в букву или цифру и отображаем в виджете «Вывод текста».


Если мы обнаруживаем очень долгое мерцание в 1,2 секунды или более, то мы удаляем последний преобразованный символ. Поверьте, при нынешнем состоянии приложения вы будете пользоваться этим довольно часто. 😊


Вот код:


def blink_detected (я, мерцание, мерцание_длины):


print(str(blink) + ' с длиной: ' + str(blink_length))


если мигать == мигать.SHORT_BLINK:


self.morse_code += '.'


Элиф Блинк == Блинк.LONG_BLINK:


self.morse_code += '-'


elif blink == Blink.PAUSE:


пытаться:


символ = код Морзе.get_character(self.код Морзе)


если char не None:


self.converted_text = self.converted_text + символ


print('Преобразование "' + self.morse_code + '" в ' + char + ' полный текст: "' + self.converted_text + '"')


self.morse_code = ''


кроме AttributeError как e:


logging.critical (е, exc_info = True)


print('Неверный код Морзе: ' + self.morse_code)


self.morse_code = ''


Элиф Блинк == Блинк.VERY_LONG_BLINK:


self.morse_code = ''


self.converted_text += 1


Clock.schedule_once(self.update_ui)


Здесь нет никакой магии, разве что в последней строчке. Это необходимо, поскольку пользовательский интерфейс не может быть обновлен из произвольного потока. Наш обработчик ЭЭГ работает в отдельном потоке, поэтому последняя строка планирует вызов нашего обновления пользовательского интерфейса с нулевой задержкой. Как только в очереди не останется других заданий, наш пользовательский интерфейс будет обновлен.


Мы готовы к разработке, так что самое время для демонстрации.


Демо


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


Вот результат 3 недель работы:


https://www.youtube.com/watch?v=6kl2r4RDstA


У нас остался только один шаг — упаковать наше приложение, чтобы оно стало приложением для Android.


Создание нашего приложения для Android


А вот и красота Киви:


Вам нужно написать только одно приложение, и вы можете создать приложение для Android, iOS, macOS и Windows.


Поскольку я разрабатываю для Windows и у меня есть телефон Android, я решил сделать пакет Android (APK).


Есть несколько способов сделать это:


  • Использование Билдозера

  • Упаковка с python-for-android

  • Упаковка вашего приложения для Kivy Launcher

Согласно документации, Buildozer самый простой. Вы можете найти всю информацию об упаковке здесь.


Просто следуйте инструкциям, и вы получите приложение в кратчайшие сроки.


Я включил необходимые шаги в файл Readme.MD проекта.


Вы можете найти проект на моем GitHub.


Хм. Это была неплохая поездка, но у меня есть хорошие новости:


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


Прежде чем мы уйдем, давайте поговорим о моих планах на будущее.


Планы на будущее


Я не слишком задумывался о будущем, поскольку сосредоточился на настоящем, но вот несколько идей, которые пришли мне в голову:


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

  • Сделайте приложение более надежным, отфильтровав такие артефакты, как движение челюсти и движение глаз.

  • Измените pythonosc или внедрите наше решение для получения данных OSC, передаваемых Mind Monitor, для доступа к временным меткам, на основе которых мы можем изменить порядок образцов.

  • Создание более надежного решения путем анализа только соответствующей части частотного спектра с использованием преобразования Фурье.

  • Использование таких данных, как движение глаз, гироскоп и акселерометр, для реализации гораздо более быстрого преобразования мозговой волны в текст.

Вот и все, ребята. Я надеюсь, что вам понравилось.


Я хотел бы услышать от вас. Если вы только думаете о запуске собственного проекта BCI на основе мозговых волн или уже что-то разработали, просто свяжитесь со мной и давайте по-дружески поболтаем. Я почти уверен, что мы оба можем извлечь из этого пользу.


P.S.: Сегодня с тобой случится что-то хорошее!


![](https://img.buymeacoffee.com/button-api/?text=Купи мне кофе&emoji=&slug=theashishmaurya&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff)


Hackernoon взял у меня интервью, поэтому, если вы хотите узнать обо мне больше, просто нажмите здесь и прочитайте!


Стань проворным супергероем!


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


Вы уже можете найти первые видео на моем канале Youtube, в которых я показываю вам, что можно запоминать такие скучные вещи, как расположение кругов.


Не забудьте [прочитать, как вы можете стать гибким супер-учеником, также известным как «Как вы можете стать супер-мыслителем», также известным как «Подтверждение концепции» (POC)] (https://msz.team/3vxmaP8), прежде чем смотреть видео. .


Присоединяйтесь к группе Agileish Superheroes в Facebook, чтобы изучать техники запоминания, техники мышления, ловкости, техники чтения и обучения, а также получать уведомления о новых живых сессиях и видеороликах


Поскольку я сумасшедший, я открыл исходный код своей жизни на GitHub в день дурака.


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


Просто нажмите здесь, чтобы проверить мою жизнь с открытым исходным кодом на Github!


Мое кредо: [Тайна предположительно красного смайлика, также известная как История о том, как я стал детективом-разработчиком программного обеспечения для отладки Интернета] (https://msz.team/3DLOBwk)


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


Если вы не хотите пропустить мои посты, просто подпишитесь на меня здесь, на Hashnode, на LinkedIn, в Twitter, в Medium.com, в dev.to , на Hackernoon и даже в Instagram .


Также опубликовано [здесь] (https://mszeles.com/a-brainwave-based-solution-with-what-completely-paralyzed-people-can-communicate-with-their-loved-ones-using-a-muse -ээг-диапазон)



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE