mirror of
https://git.roussel.pro/telecom-paris/pact.git
synced 2026-02-09 10:30:17 +01:00
preparation intégration reconaissance vocale
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
FROM python:3.8-slim
|
FROM python:3.8
|
||||||
|
|
||||||
#Ne pas créer les fichiers .pyc
|
#Ne pas créer les fichiers .pyc
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
@@ -7,7 +7,7 @@ ENV PYTHONUNBUFFERED=1
|
|||||||
|
|
||||||
#Installation des dépendances de opencv
|
#Installation des dépendances de opencv
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install ffmpeg libsm6 libxext6 -y
|
RUN apt-get install ffmpeg libsm6 libxext6 portaudio19-dev python3-pyaudio -y
|
||||||
|
|
||||||
# Installation des dépendances python
|
# Installation des dépendances python
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import math
|
|||||||
from scipy.io import wavfile
|
from scipy.io import wavfile
|
||||||
import wave
|
import wave
|
||||||
from scipy.fftpack import fft,dct
|
from scipy.fftpack import fft,dct
|
||||||
|
import time
|
||||||
|
|
||||||
from matplotlib.patches import ConnectionPatch
|
from matplotlib.patches import ConnectionPatch
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
@@ -170,31 +171,38 @@ def record_audio(filename, duration, sr):
|
|||||||
print(f"Fichier enregistré sous {filename}")
|
print(f"Fichier enregistré sous {filename}")
|
||||||
|
|
||||||
def coupe_silence(signal):
|
def coupe_silence(signal):
|
||||||
|
|
||||||
t = 0
|
t = 0
|
||||||
|
|
||||||
if signal[t] == 0 :
|
if signal[t] == 0 :
|
||||||
|
|
||||||
p = 0
|
p = 0
|
||||||
|
|
||||||
while signal[t+p] == 0 :
|
while signal[t+p] == 0 :
|
||||||
|
|
||||||
if p == 88 :
|
if p == 88 :
|
||||||
|
|
||||||
signal = signal[:t] + signal[t+p:]
|
signal = signal[:t] + signal[t+p:]
|
||||||
|
|
||||||
coupe_silence(signal)
|
coupe_silence(signal)
|
||||||
|
|
||||||
else :
|
else :
|
||||||
|
|
||||||
p = p+1
|
p = p+1
|
||||||
sr = 44100 # fréquence d'échantillonnage
|
|
||||||
duration = 6 # durée d'enregistrement en secondes
|
|
||||||
filename = "audio_query" # nom du fichier à enregistrer
|
|
||||||
|
|
||||||
record_audio(filename, duration, sr)
|
#Todo : detecte si pas de note donnée
|
||||||
audio_query, sr = librosa.load('C:\\Users\\HP\\audio_query.wav', sr=sr)
|
def get_grade():
|
||||||
coupe_silence(audio_query)
|
######## TEST DEBUG ########
|
||||||
audio_train_list = [librosa.load('C:\\Users\\HP\\Documents\\cool.wav', sr=sr)[0], librosa.load('C:\\Users\\HP\\Documents\\formidable.wav', sr=sr)[0], librosa.load('C:\\Users\\HP\\Documents\\cest mauvais.wav', sr=sr)[0] , librosa.load('C:\\Users\\HP\\Documents\\un.wav', sr=sr)[0], librosa.load('C:\\Users\\HP\\Documents\\parfait.wav', sr=sr)[0]]
|
time.sleep(6)
|
||||||
recognized_word_index = recognize_speech(audio_query, audio_train_list, sr)
|
return 5
|
||||||
print(f'Recognized word: {recognized_word_index}')
|
|
||||||
|
|
||||||
|
sr = 44100 # fréquence d'échantillonnage
|
||||||
|
duration = 6 # durée d'enregistrement en secondes
|
||||||
|
filename = "recording" # nom du fichier à enregistrer
|
||||||
|
data_dir = "audio_data/"
|
||||||
|
record_audio(filename, duration, sr)
|
||||||
|
audio_query, sr = librosa.load(f'{filename}.wav', sr=sr)
|
||||||
|
coupe_silence(audio_query)
|
||||||
|
training_file_names = []
|
||||||
|
for path in os.listdir(data_dir):
|
||||||
|
if os.path.isfile(os.path.join(data_dir, path)):
|
||||||
|
training_file_names.append(data_dir + path)
|
||||||
|
print(training_file_names)
|
||||||
|
audio_train_list = [librosa.load(file, sr=sr)[0] for file in training_file_names]
|
||||||
|
recognized_word_index = recognize_speech(audio_query, audio_train_list, sr)
|
||||||
|
print(f'Recognized word: {recognized_word_index}')
|
||||||
|
return recognized_word_index
|
||||||
|
|
||||||
|
print(get_grade())
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
from hand_detector import HandDetector
|
from hand_detector import HandDetector
|
||||||
|
from audio_detector import get_grade
|
||||||
from network import WebsocketServer
|
from network import WebsocketServer
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -6,11 +7,13 @@ import time
|
|||||||
class Manager():
|
class Manager():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.state = 0
|
self.state = 0
|
||||||
self.avis = {
|
self.defualtAvis = {
|
||||||
"note": None,
|
"note": None,
|
||||||
"commentaire": None,
|
"commentaire": None,
|
||||||
"notes_autres": {}
|
"notes_autres": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.avis = self.defualtAvis
|
||||||
self.server = WebsocketServer(None)
|
self.server = WebsocketServer(None)
|
||||||
self.server.start()
|
self.server.start()
|
||||||
self.handDetector = HandDetector()
|
self.handDetector = HandDetector()
|
||||||
@@ -23,16 +26,30 @@ class Manager():
|
|||||||
self.sleep()
|
self.sleep()
|
||||||
if(self.state == 1):
|
if(self.state == 1):
|
||||||
self.camera()
|
self.camera()
|
||||||
|
if(self.state == 2):
|
||||||
|
self.audio()
|
||||||
|
if(self.state == 3):
|
||||||
|
self.thankYou()
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
#Fonction qui est executée pendant que la borne est en veille, reveille la borne si une main est detectée
|
#Fonction qui est executée pendant que la borne est en veille, reveille la borne si une main est detectée
|
||||||
def sleep(self):
|
def sleep(self):
|
||||||
res = self.handDetector.detect()
|
res = self.handDetector.detect()
|
||||||
|
print(res)
|
||||||
if(res != False):
|
if(res != False):
|
||||||
self.state = 1
|
self.state = 1
|
||||||
self.server.sendMessage({"type": "state", "state": 1})
|
self.server.sendMessage({"type": "state", "state": 1})
|
||||||
|
|
||||||
|
def audio(self):
|
||||||
|
grade = get_grade()
|
||||||
|
if(grade != False):
|
||||||
|
self.server.sendMessage({"type":"new_grade","grade":grade})
|
||||||
|
self.avis["notes_autres"]["test"] = grade
|
||||||
|
time.sleep(3)
|
||||||
|
self.state = 2
|
||||||
|
self.server.sendMessage({"type": "state", "state": 3})
|
||||||
|
|
||||||
|
|
||||||
#Envoie la position de la main a l'écran et passe a l'étape suivante si une main est detectée pendant assez longtemps
|
#Envoie la position de la main a l'écran et passe a l'étape suivante si une main est detectée pendant assez longtemps
|
||||||
def camera(self):
|
def camera(self):
|
||||||
res = self.handDetector.detect()
|
res = self.handDetector.detect()
|
||||||
@@ -44,5 +61,10 @@ class Manager():
|
|||||||
self.state = 2
|
self.state = 2
|
||||||
self.server.sendMessage({"type": "state", "state": 2})
|
self.server.sendMessage({"type": "state", "state": 2})
|
||||||
|
|
||||||
|
def thankYou(self):
|
||||||
|
time.sleep(10)
|
||||||
|
self.state = 0
|
||||||
|
self.server.sendMessage({"type": "state", "state": 0})
|
||||||
|
self.sendReview()
|
||||||
|
self.avis = self.defualtAvis
|
||||||
|
|
||||||
|
|||||||
@@ -29,3 +29,9 @@ class WebsocketServer(threading.Thread):
|
|||||||
|
|
||||||
def sendMessage(self,message):
|
def sendMessage(self,message):
|
||||||
self.messageQueue.append(message)
|
self.messageQueue.append(message)
|
||||||
|
|
||||||
|
class ApiClient():
|
||||||
|
def __init__(self, host=os.getenv("API_HOST"), port=os.getenv("API_PORT")):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
|
||||||
BIN
code/backend_reconnaissance/recording.wav
Normal file
BIN
code/backend_reconnaissance/recording.wav
Normal file
Binary file not shown.
@@ -3,3 +3,6 @@ requests
|
|||||||
opencv-python
|
opencv-python
|
||||||
mediapipe
|
mediapipe
|
||||||
numpy
|
numpy
|
||||||
|
pyaudio
|
||||||
|
librosa
|
||||||
|
scipy
|
||||||
@@ -39,6 +39,8 @@ services:
|
|||||||
#API de gestion des avis, permet d'ajouter ou de récuperer des avis ou les stats sur les avis par des requêtes HTTP
|
#API de gestion des avis, permet d'ajouter ou de récuperer des avis ou les stats sur les avis par des requêtes HTTP
|
||||||
reviews_api:
|
reviews_api:
|
||||||
container_name: reviews_api
|
container_name: reviews_api
|
||||||
|
expose:
|
||||||
|
- 8080
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
environment:
|
environment:
|
||||||
@@ -73,11 +75,11 @@ services:
|
|||||||
- 800:80
|
- 800:80
|
||||||
|
|
||||||
#Formulaire de retour d'avis
|
#Formulaire de retour d'avis
|
||||||
Formulaire:
|
formulaire:
|
||||||
image: httpd:latest
|
image: httpd:latest
|
||||||
volumes:
|
volumes:
|
||||||
- ./Formulaire:/usr/local/apache2/htdocs/
|
- ./formulaire:/usr/local/apache2/htdocs/
|
||||||
container_name: Formulaire
|
container_name: formulaire
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
# #Backend de la borne : scripts pythons de reconnaissances video et audio
|
# #Backend de la borne : scripts pythons de reconnaissances video et audio
|
||||||
@@ -92,6 +94,8 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- PORT=5000
|
- PORT=5000
|
||||||
- HOST=backend_reconnaissance
|
- HOST=backend_reconnaissance
|
||||||
|
- API_HOST=reviews_api
|
||||||
|
- API_PORT=8080
|
||||||
ports:
|
ports:
|
||||||
#Ce container est le serveur websocker dont le client est l'interface de la borne qui tourne dans le navigateur
|
#Ce container est le serveur websocker dont le client est l'interface de la borne qui tourne dans le navigateur
|
||||||
- 5000:5000
|
- 5000:5000
|
||||||
|
|||||||
@@ -49,3 +49,8 @@ html, body {
|
|||||||
.instructions > .title {
|
.instructions > .title {
|
||||||
border-bottom: 3px #6B8000 solid;
|
border-bottom: 3px #6B8000 solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instructions > table, .instructions > th,.instructions > td {
|
||||||
|
border: 1px solid #6B8000;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
@@ -8,4 +8,10 @@ class AudioPage {
|
|||||||
this.isEnabled = isEnabled;
|
this.isEnabled = isEnabled;
|
||||||
this.DOMElement.style.display = isEnabled ? "block" : "none";
|
this.DOMElement.style.display = isEnabled ? "block" : "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setGrade(grade) {
|
||||||
|
if(this.isEnabled) {
|
||||||
|
this.DOMElement.getElementById("grade").innerHTML = grade.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
class WebsocketClient {
|
class WebsocketClient {
|
||||||
constructor(onNewEffects, onNewGrade, onNewState) {
|
constructor(onNewEffects, onNewState, onNewGrade) {
|
||||||
this.socket = new WebSocket("ws://localhost:5000");
|
this.socket = new WebSocket("ws://localhost:5000");
|
||||||
this.socket.addEventListener("open", (event) => {
|
this.socket.addEventListener("open", (event) => {
|
||||||
this.socket.send("connected");
|
this.socket.send("connected");
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ class StateManager {
|
|||||||
this.setState(STATE.video);
|
this.setState(STATE.video);
|
||||||
this._cameraPage.setEffects(effects)
|
this._cameraPage.setEffects(effects)
|
||||||
},
|
},
|
||||||
(state) => this.setState(state)
|
(state) => this.setState(state),
|
||||||
|
(grade) => this._audioPage.setGrade(grade)
|
||||||
);
|
);
|
||||||
|
|
||||||
this._sleepingPage.enabled = true;
|
this._sleepingPage.enabled = true;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<h1>Enregistrement audio blabal</h1>
|
<h1>Enregistrement audio blabal</h1>
|
||||||
</div>
|
</div>
|
||||||
<p>Prononcez à voix haute les notes correspondant aux critères suivants dans l'ordre</p>
|
<p>Donnez une note sur 10 au critère suivant</p>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Critère</td>
|
<th>Critère</td>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Calme</td>
|
<td>Calme</td>
|
||||||
<td> /10</td>
|
<td> <span id="grade"></span>/10</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
BIN
pyzo.exe.lnk
BIN
pyzo.exe.lnk
Binary file not shown.
Reference in New Issue
Block a user