Skip to content

Commit

Permalink
README WIP. mp detection. Detection borders check
Browse files Browse the repository at this point in the history
  • Loading branch information
proshian committed Jun 5, 2022
1 parent 8f09be1 commit 66ad553
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 10 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 proshian
Copyright (c) 2020 proshian

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
# Face-Music-Control
# Face Music Control

Face Music Control is a python program that allows you to control the sound of a musical instrument using facial expression emotion recognition.

[Кликните, чтобы прочитать этот документ на русском](README.ru.md)

## Requirements

An obvious requirement is having a camera on your computer

### Libraries
The command to install all the required libraries:

```bash
pip install -r requirements.txt
```

### Virtual MIDI port driver **(Windows only)**
Windows requires a driver to be installed to create virtual MIDI ports. Possible solutions:
* [LoopBe1](https://www.nerds.de/en/download.html)
<br> Once LoopBe1 is installed a virtual MIDI port will be on your computer until the driver is uninstalled.
* [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)
<br> It is a program that allows manipulating virtualMIDI driver that comes with loopMIDI. If you chose loopMIDI over LoopBe1 for a virtual MIDI port to be on your computer the loopMIDI must be running


**If you use linux or macOS, Face Music Control creates virtual MIDI ports by itself and third-party drivers are not needed**

<!--
## Использование
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
-->
## License
Garri Proshian © [MIT](https://choosealicense.com/licenses/mit/) 2020
34 changes: 34 additions & 0 deletions README.ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Face Music Control

Face Music Control — это python программа, позволяющая управлять звучанием музыкального инструмента с помощью распознавания эмоций по лицеовой экспрессии.

[Click here for this document in English](README.md)


## Запуск и требования для работы программы

Чтобы установить все необходимые библиотеки, необходимо выполнить команду:

```bash
pip install -r requirements.txt
```

Для Windows требуется установить драйвер для создания виртуальных MIDI портов. Возможные решения:
* [LoopBe1](https://www.nerds.de/en/download.html)
* virtualMIDI в составе [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)

**Если вы используете linux или macOS, Face Music COntrol сам создает виртуальные миди порты, и сторонние драйверы не нужны**

## Использование

<!--
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
## License
[MIT](https://choosealicense.com/licenses/mit/)
-->
## Лицензия
Garri Proshian © [MIT](https://choosealicense.com/licenses/mit/) 2020
44 changes: 41 additions & 3 deletions face_detector.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,60 @@
from enum import Enum

import cv2
import numpy as np
import mediapipe as mp

"""
# !!! TODO сделать разделение на методы детекции
"""


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

class FaceDetector:
"""
Отвечает за детекцию лиц, в частности, самого большого лица.
"""
def __init__(self) -> None:
def __init__(self, detection_method: str = 'meadiapipe') -> None:
if detection_method not in self.detection_methods:
method_to_be_used = 'meadiapipe'
print(f"Detection method with name {detection_method} " \
f"is not defined.",
f"{method_to_be_used} is going to be used")
detection_method = method_to_be_used

self._detection_method = detection_method
self._face_detector = cv2.CascadeClassifier(
r'haarcascade_frontalface_default.xml')
mp_face_detection = mp.solutions.face_detection
self.mp_face_detection = mp_face_detection.FaceDetection(
model_selection=0, min_detection_confidence=0.7)

detection_methods = ['meadiapipe', 'haar']

def detect_faces(self, img: np.ndarray) -> list[tuple[int]]:
return self._face_detector.detectMultiScale(img, 1.32, 5)
#haar_detections = self._face_detector.detectMultiScale(img, 1.32, 5)


mp_results = self.mp_face_detection.process(img)
mp_detections = []
if mp_results.detections:
for result in mp_results.detections:
box = result.location_data.relative_bounding_box
mp_detections.append(tuple(map(
int,
[box.xmin * img.shape[1],
box.ymin * img.shape[0],
box.width * img.shape[1],
box.height * img.shape[0]])))
# print(f"{mp_detections = }")
# print(f"{haar_detections = }")

return mp_detections

def _get_rect_area(rect: tuple[int]) -> int:
_,_,w,h = rect
Expand Down
29 changes: 24 additions & 5 deletions fer_sens.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,27 @@ def preprocess(self, cam_img):

nn_input = FerSensor.face_img_to_nn_input(face_img)

viz_w, viz_h = self.resource.get_viz_shape()

s_x, s_y, s_w, s_h = [
round(coord * self.resource._scaling_factor)
for coord in largest_face_rect]

if s_x + s_w > viz_w or s_y + s_h > viz_h:
"""
# ! Это нужно логировать
print("Warning! The face detection bounding box" \
"exceeds the image boundaries!",
"Iteration aborted.",
f"{(viz_w, viz_h) = }",
f"{(s_x, s_y, s_w, s_h) = }",)
"""
self.visualization = FerSensor.get_dark_overlay(
self.resource.get_viz_shape()[::-1])
return None

self.init_viz_with_detection(
self.resource.get_viz_shape()[::-1], largest_face_rect)
self.resource.get_viz_shape()[::-1], largest_face_rect)

return nn_input

Expand Down Expand Up @@ -123,12 +142,12 @@ def init_viz_with_detection(self, img_height_and_width, face_coords):
round(coord * self.resource._scaling_factor)
for coord in face_coords]

# print(f"{face_coords = }")
# print(f"{transparent_img[s_y:s_y+s_h, s_x:s_x+s_w, 3].shape = }")
# print(f"{face_coords = }")
# print(f"{visualisation[s_y:s_y+s_h, s_x:s_x+s_w, 3].shape }"")

# Сделаем участок с лицом прозрачным
visualisation[s_y:s_y+s_h, s_x:s_x+s_w, 3] = np.zeros(
(s_w, s_h), dtype=np.uint8)
(s_h, s_w), dtype=np.uint8)

# Добавим рамку вокруг лица
cv2.rectangle(
Expand Down
2 changes: 2 additions & 0 deletions fmc_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ def _set_fonts(self):
self.max_label_font = QFont("Roboto")
self.max_label_font.setPointSizeF(9.5)
self.max_label_font.setBold(True)


# Хотелось бы, чтобы в режиме настройки окно приложения было выше всех,
# а в режиме игры вело себя как обычное окно.
# Смена флагов приводит к приостанвке рендеринга.
Expand Down

0 comments on commit 66ad553

Please sign in to comment.