feat: implemented emotion recognition functionality in AgentSpeak
ref: N25B-393
This commit is contained in:
@@ -22,6 +22,7 @@ from control_backend.schemas.program import (
|
||||
BaseGoal,
|
||||
BasicNorm,
|
||||
ConditionalNorm,
|
||||
EmotionBelief,
|
||||
GestureAction,
|
||||
Goal,
|
||||
InferredBelief,
|
||||
@@ -459,6 +460,10 @@ class AgentSpeakGenerator:
|
||||
@_astify.register
|
||||
def _(self, sb: SemanticBelief) -> AstExpression:
|
||||
return AstLiteral(self.slugify(sb))
|
||||
|
||||
@_astify.register
|
||||
def _(self, eb: EmotionBelief) -> AstExpression:
|
||||
return AstLiteral("emotion_detected", [AstAtom(eb.emotion)])
|
||||
|
||||
@_astify.register
|
||||
def _(self, ib: InferredBelief) -> AstExpression:
|
||||
|
||||
@@ -47,7 +47,7 @@ class VisualEmotionRecognitionAgent(BaseAgent):
|
||||
"""
|
||||
Retrieve a video frame from the input socket.
|
||||
"""
|
||||
window_duration = 1 # seconds
|
||||
window_duration = 5 # seconds
|
||||
next_window_time = time.time() + window_duration
|
||||
|
||||
# To detect false positives
|
||||
@@ -82,7 +82,7 @@ class VisualEmotionRecognitionAgent(BaseAgent):
|
||||
|
||||
# If window duration has passed, process the collected stats
|
||||
if time.time() >= next_window_time:
|
||||
|
||||
print(face_stats)
|
||||
window_dominant_emotions = set()
|
||||
# Determine dominant emotion for each face in the window
|
||||
for _, counter in face_stats.items():
|
||||
@@ -116,7 +116,7 @@ class VisualEmotionRecognitionAgent(BaseAgent):
|
||||
for emotion in emotions_to_remove:
|
||||
self.logger.info(f"Emotion '{emotion}' has disappeared.")
|
||||
try:
|
||||
emotion_beliefs_remove.append(Belief(name="emotion", arguments=[emotion], remove=True))
|
||||
emotion_beliefs_remove.append(Belief(name="emotion_detected", arguments=[emotion], remove=True))
|
||||
except ValidationError:
|
||||
self.logger.warning("Invalid belief for emotion removal: %s", emotion)
|
||||
|
||||
@@ -125,7 +125,7 @@ class VisualEmotionRecognitionAgent(BaseAgent):
|
||||
for emotion in emotions_to_add:
|
||||
self.logger.info(f"New emotion detected: '{emotion}'")
|
||||
try:
|
||||
emotion_beliefs_add.append(Belief(name="emotion", arguments=[emotion]))
|
||||
emotion_beliefs_add.append(Belief(name="emotion_detected", arguments=[emotion]))
|
||||
except ValidationError:
|
||||
self.logger.warning("Invalid belief for new emotion: %s", emotion)
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ class DeepFaceEmotionRecognizer(VisualEmotionRecognizer):
|
||||
# Sort faces by x coordinate to maintain left-to-right order
|
||||
analysis.sort(key=lambda face: face['region']['x'])
|
||||
|
||||
# Fear op 0, boost 0.2 aan happy, sad -0.1, neutral +0.1
|
||||
|
||||
analysis = [face for face in analysis if face['face_confidence'] >= 0.90]
|
||||
|
||||
dominant_emotions = [face['dominant_emotion'] for face in analysis]
|
||||
|
||||
@@ -28,8 +28,8 @@ class LogicalOperator(Enum):
|
||||
OR = "OR"
|
||||
|
||||
|
||||
type Belief = KeywordBelief | SemanticBelief | InferredBelief
|
||||
type BasicBelief = KeywordBelief | SemanticBelief
|
||||
type Belief = KeywordBelief | SemanticBelief | InferredBelief | EmotionBelief
|
||||
type BasicBelief = KeywordBelief | SemanticBelief | EmotionBelief
|
||||
|
||||
|
||||
class KeywordBelief(ProgramElement):
|
||||
@@ -69,6 +69,15 @@ class InferredBelief(ProgramElement):
|
||||
left: Belief
|
||||
right: Belief
|
||||
|
||||
class EmotionBelief(ProgramElement):
|
||||
"""
|
||||
Represents a belief that is set when a certain emotion is detected.
|
||||
|
||||
:ivar emotion: The emotion on which this belief gets set.
|
||||
"""
|
||||
|
||||
name: str = ""
|
||||
emotion: str
|
||||
|
||||
class Norm(ProgramElement):
|
||||
"""
|
||||
@@ -226,3 +235,9 @@ class Program(BaseModel):
|
||||
"""
|
||||
|
||||
phases: list[Phase]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
input = input("Enter program JSON: ")
|
||||
program = Program.model_validate_json(input)
|
||||
print(program)
|
||||
Reference in New Issue
Block a user