Русский
Русский
English
Статистика
Реклама

Dlib

Управляем звуком ПК от активности пользователя с помощью Python

17.06.2021 14:15:17 | Автор: admin

Настройка программного обеспечения

Без промедления начнём. Нам нужно установить следующее ПО:

  • Windows 10

  • Anaconda 3 (Python 3.8)

  • Visual Studio 2019 (Community) - объясню позже, зачем она понадобится.

Открываем Anaconda Prompt (Anaconda3) и устанавливаем следующие пакеты:

pip install opencv-pythonpip install dlibpip install face_recognition

И уже на этом моменте начнутся проблемы с dlib.

Решаем проблему с dlib

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

Итак, первая же ошибка говорит о том, что у нас не установлен cmake.

ERROR: CMake must be installed to build dlib
ERROR: CMake must be installed to build dlibERROR: CMake must be installed to build dlib

Не закрывая консоль, вводим следующую команду:

pip install cmake
Проблем при установке быть не должно

Пробуем установить пакет той же командой (pip install dlib), но на этот раз получаем новую ошибку:

Отсутствуют элементы Visual Studio

Ошибка явно указывает, что у меня, скорее всего, стоит студия с элементами только для C# - и она оказывается права. Открываем Visual Studio Installer, выбираем "Изменить", в вкладке "Рабочие нагрузки" в разделе "Классические и мобильные приложения" выбираем пункт "Разработка классических приложений на С++":

Пошагово
"Изменить""Изменить"Разработка классических приложений на С++Разработка классических приложений на С++Ждем окончания установкиЖдем окончания установки

Почему важно оставить все галочки, которые предлагает Visual Studio. У меня с интернетом плоховато, поэтому я решил не скачивать пакет SDK для Windows, на что получил следующую ошибку:

Не нашли компилятор

Я начал искать решение этой ошибки, пробовать менять тип компилятора (cmake -G " Visual Studio 16 2019"), но только стоило установить SDK, как все проблемы ушли.

Я пробовал данный метод на двух ПК и отмечу ещё пару подводных камней. Самое главное - Visual Studio должна быть 2019 года. У меня под рукой был офлайн установщик только 2017 - я мигом его поставил, делаю команду на установку пакета и получаю ошибку, что нужна свежая Microsoft Visual C++ версии 14.0. Вторая проблема была связана с тем, что даже установленная студия не могла скомпилировать проект. Помогла дополнительная установка Visual C++ 2015 Build Tools и Microsoft Build Tools 2015.

Открываем вновь Anaconda Prompt, используем ту же самую команду и ждём, когда соберется проект (около 5 минут):

Сборка
Всё прошло успешноВсё прошло успешно

Управляем громкостью

Вариантов оказалось несколько (ссылка), но чем проще - тем лучше. На русском язычном StackOverflow предложили использовать простую библиотеку от Paradoxis - ей и воспользуемся. Чтобы установить её, нам нужно скачать архив, пройти по пути C:\ProgramData\Anaconda3\Lib и перенести файлы keyboard.py, sound.py из архива. Проблем с использованием не возникало, поэтому идём дальше

Собираем события мыши

Самым популярным модулем для автоматизации управления мышью/клавиатурой оказался pynput. Устанавливаем так же через (pip install dlib). У модуля в целом неплохое описание - https://pynput.readthedocs.io/en/latest/mouse.html . Но у меня возникли сложности при получении событий. Я написал простую функцию:

from pynput import mousedef func_mouse():        with mouse.Events() as events:            for event in events:                if event == mouse.Events.Scroll or mouse.Events.Click:                    #print('Переместил мышку/нажал кнопку/скролл колесиком: {}\n'.format(event))                    print('Делаю половину громкости: ', time.ctime())                    Sound.volume_set(volum_half)                    break

Самое интересное, что если раскомментировать самую первую строчку и посмотреть на событие, которое привело выходу из цикла, то там можно увидеть Move. Если вы заметили, в условии if про него не слово. Без разницы, делал я только скролл колесиком или только нажатие любой клавиши мыши - все равно просто движение мыши приводит к выходу из цикла. В целом, мне нужно все действия (Scroll, Click, Move), но такое поведение я объяснить не могу. Возможно я где-то ошибаюсь, поэтому можете поправить.

А что в итоге?

Adam Geitgey, автор библиотеки face recognition, в своём репозитории имеет очень хороший набор примеров, которые многие используют при написании статей: https://github.com/ageitgey/face_recognition/tree/master/examples

Воспользуемся одним из них и получим следующий код, который можно скачать по ссылке: Activity.ipynb, Activity.py

Код
# Подключаем нужные библиотекиimport cv2import face_recognition # Получаем данные с устройства (веб камера у меня всего одна, поэтому в аргументах 0)video_capture = cv2.VideoCapture(0) # Инициализируем переменныеface_locations = []from sound import SoundSound.volume_up() # увеличим громкость на 2 единицыcurrent = Sound.current_volume() # текущая громкость, если кому-то нужноvolum_half=50  # 50% громкостьvolum_full=100 # 100% громкостьSound.volume_max() # выставляем сразу по максимуму# Работа со временем# Подключаем модуль для работы со временемimport time# Подключаем потокиfrom threading import Threadimport threading# Функция для работы с активностью мышиfrom pynput import mousedef func_mouse():        with mouse.Events() as events:            for event in events:                if event == mouse.Events.Scroll or mouse.Events.Click:                    #print('Переместил мышку/нажал кнопку/скролл колесиком: {}\n'.format(event))                    print('Делаю половину громкости: ', time.ctime())                    Sound.volume_set(volum_half)                    break# Делаем отдельную функцию с напоминаниемdef not_find():    #print("Cкрипт на 15 секунд начинается ", time.ctime())    print('Делаю 100% громкости: ', time.ctime())    #Sound.volume_set(volum_full)    Sound.volume_max()        # Секунды на выполнение    #local_time = 15    # Ждём нужное количество секунд, цикл в это время ничего не делает    #time.sleep(local_time)        # Вызываю функцию поиска действий по мышке    func_mouse()    #print("Cкрипт на 15 сек прошел")# А тут уже основная часть кодаwhile True:    ret, frame = video_capture.read()        '''    # Resize frame of video to 1/2 size for faster face recognition processing    small_frame = cv2.resize(frame, (0, 0), fx=0.50, fy=0.50)    rgb_frame = small_frame[:, :, ::-1]    '''    rgb_frame = frame[:, :, ::-1]        face_locations = face_recognition.face_locations(rgb_frame)        number_of_face = len(face_locations)        '''    #print("Я нашел {} лицо(лица) в данном окне".format(number_of_face))    #print("Я нашел {} лицо(лица) в данном окне".format(len(face_locations)))    '''        if number_of_face < 1:        print("Я не нашел лицо/лица в данном окне, начинаю работу:", time.ctime())        '''        th = Thread(target=not_find, args=()) # Создаём новый поток        th.start() # И запускаем его        # Пока работает поток, выведем на экран через 10 секунд, что основной цикл в работе        '''        #time.sleep(5)        print("Поток мыши заработал в основном цикле: ", time.ctime())                #thread = threading.Timer(60, not_find)        #thread.start()                not_find()        '''        thread = threading.Timer(60, func_mouse)        thread.start()        print("Поток мыши заработал.\n")        # Пока работает поток, выведем на экран через 10 секунд, что основной цикл в работе        '''        #time.sleep(10)        print("Пока поток работает, основной цикл поиска лица в работе.\n")    else:        #все хорошо, за ПК кто-то есть        print("Я нашел лицо/лица в данном окне в", time.ctime())        Sound.volume_set(volum_half)            for top, right, bottom, left in face_locations:        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)        cv2.imshow('Video', frame)        if cv2.waitKey(1) & 0xFF == ord('q'):        breakvideo_capture.release()cv2.destroyAllWindows()

Суть кода предельно проста: бегаем в цикле, как только появилось хотя бы одно лицо (а точнее координаты), то звук делаем 50%. Если не нашёл никого поблизости, то запускаем цикл с мышкой.

Тестирование в бою

Ожидание и реальность

Если вы посмотрели видео, то поняли, что результат ещё далёк от реальной эксплуатации.

Признаю честно - до этого момента никогда не сталкивался с многопоточностью на Python, поэтому "с наскоку" тему взять не удалось и результат по видео понятен. Есть неплохая статья на Хабре, описывающая различные методы многопоточности, применяемые в языке. Пока у меня решения нету по этой теме нету - будет повод разобраться лучше и дописать код/статью с учетом этого.

Так же возникает закономерный вопрос - а если вместо живого человека поставить перед монитором картинку? Да, она распознает, что, скорее всего, не совсем верно. Мне попался очень хороший материал по поводу определения живого лица в реальном времени - https://www.machinelearningmastery.ru/real-time-face-liveness-detection-with-python-keras-and-opencv-c35dc70dafd3/ , но это уже немного другой уровень и думаю новичкам это будет посложнее. Но эксперименты с нейронными сетями я чуть позже повторю, чтобы тоже проверить верность и повторяемость данного руководства.

Немаловажным фактором на качество распознавания оказывает получаемое изображение с веб-камеры. Предложение использовать 1/4 изображения (сжатие его) приводит только к ухудшению - моё лицо алгоритм распознать так и не смог. Для повышения качества предлагают использовать MTCNN face detector (пример использования), либо что-нибудь посложнее из абзаца выше.

Другая интересная особенность - таймеры в Питоне. Я, опять же, признаю, что ни разу до этого не было нужды в них, но все статьях сводится к тому, чтобы ставить поток в sleep(кол-во секунд). А если мне нужно сделать так, чтобы основной поток был в работе, а по истечению n-ое количества секунд не было активности, то выполнялась моя функция? Использовать демонов (daemon)? Так это не совсем то, что нужно. Писать отдельную программу, которая взаимодействует с другой? Возможно, но единство программы пропадает.

Заключение

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

P.S. Предлагаю вам, читатели, обсудить в комментариях статью - ваши идеи, замечания, уточнения.

Подробнее..

Как распознать реальное лицо от ложного при распознавании лиц

24.11.2020 16:19:42 | Автор: admin
image

Краткое описание


Распознавание реального лица человека от ложного в камере все еще остается одним из сложных проблем в системах контроля и доступа в помещения. Предлагается алгоритм для обнаружения моргания глаз в реальном времени в видеопоследовательности от стандартной камеры, что дает нам факт что человек в камере является реальным. Последние детекторы наземных ориентиров, обученные на наборах данных в полевых условиях, демонстрируют превосходную устойчивость к ориентации головы относительно камеры, изменяющейся освещенности и выражений лица. Мы показываем, что ориентиры обнаруживаются достаточно точно, чтобы надежно оценить уровень открытия глаза. Таким образом, предложенный алгоритм оценивает положения ориентиров, извлекает одну скалярную величину коэффициент глазного дна (EAR) характеризующую открытие глаза в каждом кадре. Наконец, классификатор SVM обнаруживает мигание глаз как образец значений EAR в коротком временном окне. Простой алгоритм превосходит современные результаты по двум стандартным наборам данных.

Библиотека Dlib


В этой статье я использую индексы лицевых ориентиров для областей лица библиотеки dlib. Детектор лицевого ориентира, реализованный внутри библиотеки dlib, выдает 68 (x, y) -координаты, которые отображаются на конкретные структуры лица. Эти 68 точечных отображений были получены путем обучения предиктора формы на помеченном наборе данных iBUG 300-W.

Ниже мы можем визуализировать то, на что каждая из этих 68 координат отображается:


Рисунок 1 Визуализация каждой из 68 лицевых координатных точек из набора данных iBUG 300-W

Изучив изображение, мы увидим, что к лицевым областям можно получить доступ посредством простой индексации Python (при условии нулевой индексации с помощью Python, поскольку изображение выше одно индексировано):

  • Рот может быть доступен через точки [48, 68].
  • Правая бровь через точки [17, 22].
  • Левая бровь через точки [22, 27].
  • Правый глаз через точки [36, 42].
  • Левый глаз через точки [42, 48].
  • Нос через точки [27, 35].
  • И челюсть через точки [0, 17].

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


Рисунок 2 Обнаружение лицевых ориентиров в картинке в режиме реального времени

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


Рисунок 3- Применение лицевых ориентиров для локализации различных областей лица, именно правый глаз и рот

Обнаружение моргания глаз


С точки зрения обнаружения моргания нас интересуют только два набора структур лица глаза. Каждый глаз представлен 6 (x, y) -координатами, начинающимися в левом углу глаза (как если бы вы смотрели на человека), а затем работающими по часовой стрелке вокруг остальной части области:


Рисунок 4 6 лицевых ориентиров, связанных с глазом

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


Рисунок 5 уравнение пропорции глаза

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

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


Рисунок 6 Визуализация глазных ориентиров

В верхнем левом углу у нас полностью открыт глаз соотношение сторон здесь будет большим и относительно постоянным во времени. Однако, как только человек моргает (вверху справа), соотношение сторон глаза резко уменьшается, приближаясь к нулю. На верхнем рисунке показан график соотношения сторон глаза для видеоклипа. Как мы видим, соотношение сторон глаза постоянное, затем быстро падает близко к нулю, а затем снова увеличивается, что указывает на одно мигание.


Рисунок 7 Обнаружение моргание глаз

Исключения


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

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

Проблемы такого подхода


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

Решение проблем


Здесь показано работа стреопар камер. После того как изображения ректифицированы, выполняют поиск соответствующих пар точек из двух изображении. Самый простой способ проиллюстрирован на картинке 8 и состоит в следующем. Для каждого пикселя левой картинки с координатами (x0, y0) выполняется поиск пикселя на правой картинке. При этом предполагается, что пиксель на правой картинке должен иметь координаты (x0 d, y0), где d величина называемая несоответствие/смещение (disparity). Поиск соответствующего пикселя выполняется путем вычисления максимума функции отклика, в качестве которой может выступать, например, корреляция окрестностей пикселей.


Рисунок 8 Вычисления карты глубины
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru