Skip to content

Commit 545ece3

Browse files
committed
update face recognition
1 parent 7610fa2 commit 545ece3

File tree

7 files changed

+217
-53
lines changed

7 files changed

+217
-53
lines changed

.github/workflows/gh-pages.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: gh-pages
22
on:
33
workflow_dispatch:
4-
push:
5-
branches:
6-
- main
4+
# push:
5+
# branches:
6+
# - main
77

88
jobs:
99
release:

dslclib/src/body_controller.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from dataclasses import dataclass
3-
from typing import Optional
3+
from typing import Literal, Optional
44

55
from dslclib.src.base import BaseClient
66

@@ -26,13 +26,13 @@ class MotionType:
2626
righthandbaseposition
2727
"""
2828

29-
Default: str = "DefaultMotion"
30-
Greeting: str = "greeting"
31-
Nono: str = "nono"
32-
NodDeep: str = "nod_deep"
33-
Nod: str = "nod"
34-
RightHandBasePosition: str = "righthandbaseposition"
35-
LeftHandBasePositin: str = "lefthandbaseposition"
29+
Default: Literal["DefaultMotion"] = "DefaultMotion"
30+
Greeting: Literal["greeting"] = "greeting"
31+
Nono: Literal["nono"] = "nono"
32+
NodDeep: Literal["nod_deep"] = "nod_deep"
33+
Nod: Literal["nod"] = "nod"
34+
RightHandBasePosition: Literal["righthandbaseposition"] = "righthandbaseposition"
35+
LeftHandBasePositin: Literal["lefthandbaseposition"] = "lefthandbaseposition"
3636

3737

3838
"""
@@ -96,9 +96,9 @@ class GazeObject:
9696
Sofa
9797
"""
9898

99-
Monitor: str = "monitor"
100-
Desk: str = "desk"
101-
Sofa: str = "Sofa"
99+
Monitor: Literal["monitor"] = "monitor"
100+
Desk: Literal["desk"] = "desk"
101+
Sofa: Literal["Sofa"] = "Sofa"
102102

103103

104104
"""
@@ -129,8 +129,8 @@ class ControllerType:
129129
HeadController
130130
"""
131131

132-
Eye: str = "EyeController"
133-
Head: str = "HeadController"
132+
Eye: Literal["EyeController"] = "EyeController"
133+
Head: Literal["HeadController"] = "HeadController"
134134

135135

136136
"""

dslclib/src/expression_controller.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import dataclass
2-
from typing import Optional
2+
from typing import Literal, Optional
33

44
from dslclib.src.base import BaseClient
55

@@ -12,20 +12,20 @@ class ExpressionType:
1212
ExpressionType()とインスタンス化する必要はない.
1313
"""
1414

15-
MouthA: str = "mouth-a"
16-
MouthI: str = "mouth-i"
17-
MouthU: str = "mouth-u"
18-
MouthE: str = "mouth-e"
19-
MouthO: str = "mouth-o"
20-
Normal: str = "normal"
21-
FullSmile: str = "fullsmile"
22-
Smile: str = "smile"
23-
Bad: str = "bad"
24-
Angry: str = "angry"
25-
EyeClose: str = "eye-close"
26-
EyeOpen: str = "eye-open"
27-
EyeUp: str = "eye-up"
28-
EyeDown: str = "eye-down"
15+
MouthA: Literal["mouth-a"] = "mouth-a"
16+
MouthI: Literal["mouth-i"] = "mouth-i"
17+
MouthU: Literal["mouth-u"] = "mouth-u"
18+
MouthE: Literal["mouth-e"] = "mouth-e"
19+
MouthO: Literal["mouth-o"] = "mouth-o"
20+
Normal: Literal["normal"] = "normal"
21+
FullSmile: Literal["fullsmile"] = "fullsmile"
22+
Smile: Literal["smile"] = "smile"
23+
Bad: Literal["bad"] = "bad"
24+
Angry: Literal["angry"] = "angry"
25+
EyeClose: Literal["eye-close"] = "eye-close"
26+
EyeOpen: Literal["eye-open"] = "eye-open"
27+
EyeUp: Literal["eye-up"] = "eye-up"
28+
EyeDown: Literal["eye-down"] = "eye-down"
2929

3030

3131
"""

dslclib/src/face_recognition.py

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,47 @@
77
from dslclib.src.base import BaseClient
88

99

10+
@dataclass
11+
class Rotation:
12+
"""Rotation
13+
ユーザの顔の向きを示すデータクラス"""
14+
15+
pitch: float
16+
roll: float
17+
yaw: float
18+
19+
20+
@dataclass
21+
class OutputForFaceRecognition:
22+
"""OutputForFaceRecognition
23+
感情認識サーバのクライアントが出力するデータクラス"""
24+
25+
summarized: bool
26+
timestamp: float
27+
emotion: str
28+
emotion_score: float
29+
rotations: list[Rotation]
30+
age: Optional[int] = None
31+
gender: Optional[Literal["Man", "Woman"]] = None
32+
gender_score: Optional[float] = None
33+
34+
def __getitem__(self, key):
35+
return getattr(self, key)
36+
37+
1038
@dataclass
1139
class EmotionType:
1240
"""EmotionType
1341
感情認識サーバが出力する感情値を定義したデータクラス
1442
"""
1543

16-
Neutral: str = "neutral"
17-
Happiness: str = "happiness"
18-
Surprise: str = "surprise"
19-
Sadness: str = "sadness"
20-
Anger: str = "anger"
21-
Disgust: str = "disgust"
22-
fear: str = "fear"
44+
Neutral: Literal["neutral"] = "neutral"
45+
Happiness: Literal["happiness"] = "happiness"
46+
Surprise: Literal["surprise"] = "surprise"
47+
Sadness: Literal["sadness"] = "sadness"
48+
Anger: Literal["anger"] = "anger"
49+
Disgust: Literal["disgust"] = "disgust"
50+
Fear: Literal["fear"] = "fear"
2351

2452

2553
class FaceRecognitionClient(BaseClient):
@@ -58,6 +86,14 @@ def __init__(self, ip: Optional[str] = None, port: int = 4500) -> None:
5886
>>>
5987
"""
6088
super().__init__(ip, port)
89+
self.__age: Optional[int] = None
90+
self.__gender: Optional[Literal["Man", "Woman"]] = None
91+
self.__gender_score: Optional[float] = None
92+
93+
def get_user_info(
94+
self,
95+
) -> tuple[Optional[int], Optional[Literal["Man", "Woman"]], Optional[float]]:
96+
return self.__age, self.__gender, self.__gender_score
6197

6298
def receive_line(self) -> str:
6399
"""
@@ -168,9 +204,7 @@ def summarize_timestamps(
168204

169205
return True, timestamp, emotion, score
170206

171-
def listen(
172-
self, func: Optional[Callable] = None
173-
) -> tuple[Optional[float], str, Optional[float]]:
207+
def listen(self, func: Optional[Callable] = None) -> OutputForFaceRecognition:
174208
"""
175209
感情認識サーバとのソケット通信をするメソッド
176210
@@ -195,27 +229,60 @@ def listen(
195229
196230
Returns
197231
-------
198-
tuple[Optional[float], str, Optional[float]]
232+
OutputForFaceRecognition
199233
"""
200234
do_return: bool = False
201235
pool: list[tuple[float, str, float]] = []
236+
rotations: list[Rotation] = []
202237
while True:
203238
received = self.receive_line()
204239
if not re.search(r"^\{[^\n]+\}\n", received):
205240
continue
206241

207242
data = json.loads(received)
243+
timestamp: float = data["timestamp"]
244+
emotion: str = data["emotion_class"]
245+
score: float = data["emotion_score"]
246+
rot = data["rotation"]
247+
rotations.append(
248+
Rotation(pitch=rot["pitch"], roll=rot["roll"], yaw=rot["yaw"])
249+
)
250+
# user info
251+
if "age" in list(data.keys()):
252+
self.__age = data["age"]
253+
self.__gender = data["gender_class"]
254+
self.__gender_score = data["gender_score"]
255+
256+
age, gender, gender_score = self.get_user_info()
208257
if func is None:
209-
return data["timestamp"], data["emotion_class"], data["emotion_score"]
210-
211-
pool.append(tuple(data.values()))
258+
return OutputForFaceRecognition(
259+
summarized=True,
260+
timestamp=timestamp,
261+
emotion=emotion,
262+
emotion_score=score,
263+
rotations=rotations,
264+
age=age,
265+
gender=gender,
266+
gender_score=gender_score,
267+
)
268+
269+
pool.append((timestamp, emotion, score))
212270
do_return, timestamp, emotion, score = func(data=pool)
213271
if do_return:
214272
if not isinstance(emotion, str):
215273
raise TypeError(
216274
f"出力する感情クラスは`str`のみですが、{type(str)}があたえられています。`func`を要件を満たすように設計してください。"
217275
)
218-
return timestamp, emotion, score
276+
return OutputForFaceRecognition(
277+
summarized=True,
278+
timestamp=timestamp,
279+
emotion=emotion,
280+
emotion_score=score,
281+
rotations=rotations,
282+
age=age,
283+
gender=gender,
284+
gender_score=gender_score,
285+
)
219286

220287

221288
if __name__ == "__main__":

dslclib/src/speech_recognition.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
import re
22
from dataclasses import dataclass
3-
from typing import Optional
3+
from typing import Literal, Optional
44

55
from dslclib.src.base import BaseClient
66

77

88
@dataclass
99
class STTRecognitionType:
10-
InterimResult = "interimresult"
11-
Result = "result"
10+
InterimResult: Literal["interimresult"] = "interimresult"
11+
Result: Literal["result"] = "result"
12+
13+
14+
@dataclass
15+
class OutputForSTTRecognition:
16+
type: Literal["interimresult", "result"]
17+
result: str
18+
19+
def __getitem__(self, key):
20+
return getattr(self, key)
1221

1322

1423
class SpeechRecognitionClient(BaseClient):
@@ -67,7 +76,7 @@ def receive_line(self) -> str:
6776
received = str(self.sock.recv(4096).decode())
6877
return received
6978

70-
def listen(self, interim: bool = True) -> tuple[str, str]:
79+
def listen(self, interim: bool = True) -> OutputForSTTRecognition:
7180
"""
7281
データがたまってからデータを出力するメソッド.
7382
@@ -96,11 +105,17 @@ def listen(self, interim: bool = True) -> tuple[str, str]:
96105
if interim: # 発話中でも出力するかどうか
97106
matching_result = re.search(r"^interimresult:([^\n]+)\n", received)
98107
if matching_result is not None:
99-
return STTRecognitionType.InterimResult, matching_result.group(1)
108+
return OutputForSTTRecognition(
109+
type=STTRecognitionType.InterimResult,
110+
result=matching_result.group(1),
111+
)
100112

101113
matching_result = re.search(r"^result:([^\n]+)\n", received)
102114
if matching_result is not None:
103-
return STTRecognitionType.Result, matching_result.group(1)
115+
return OutputForSTTRecognition(
116+
type=STTRecognitionType.Result,
117+
result=matching_result.group(1),
118+
)
104119

105120

106121
if __name__ == "__main__":

0 commit comments

Comments
 (0)