diff --git a/README.md b/README.md index 253e30b6f18ac5d80cf590169370078ebbde0d89..dfe5104fc5e24aead696b77c708c96a1e75e232a 100644 --- a/README.md +++ b/README.md @@ -1 +1,41 @@ -Information about the Emotion recognition package for the SOCRATES Creative Workshop project. \ No newline at end of file +Information about the Emotion recognition package for the SOCRATES Creative +Workshop project. + +The emotion_detection.py file will publish the probability over a set of +emotions to the topic /emotions every second. + +The emotions are in the format of a Float32MultiArray, such that: + +layout: + dim: + - + label: Anger + size: 0 + stride: 0 + - + label: Happiness + size: 0 + stride: 0 + - + label: Neutral + size: 0 + stride: 0 + - + label: Sadness + size: 0 + stride: 0 + - + label: Surprise + size: 0 + stride: 0 + - + label: None + size: 0 + stride: 0 + data_offset: 0 +data: [ X X X X X X] + + +where X is some decimal number representing the probability for a corresponding +emotion and labels cohere to the sequence in the data i.e. data[0] is for Anger +etc.. \ No newline at end of file diff --git a/emotion_detection.py b/emotion_detection.py new file mode 100755 index 0000000000000000000000000000000000000000..c50608682ce0730061493325f70ea37e29b3373f --- /dev/null +++ b/emotion_detection.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Revision $Id$ + +# Modified by Alexander Sutherland 09-10-2017 + +import rospy +from genEmotions import get_emotion +from std_msgs.msg import String, Float32MultiArray, MultiArrayLayout, MultiArrayDimension +import numpy as np + +def emotion_detection(): + pub = rospy.Publisher('emotions', Float32MultiArray, queue_size=10) + + rospy.init_node('emotion_detection', anonymous=False) + rate = rospy.Rate(1) + + while not rospy.is_shutdown(): + message = Float32MultiArray(data=get_emotion()) + message.layout.dim.append(MultiArrayDimension(label="Anger")) + message.layout.dim.append(MultiArrayDimension(label="Happiness")) + message.layout.dim.append(MultiArrayDimension(label="Neutral")) + message.layout.dim.append(MultiArrayDimension(label="Sadness")) + message.layout.dim.append(MultiArrayDimension(label="Surprise")) + message.layout.dim.append(MultiArrayDimension(label="None")) + + rospy.loginfo(message) + pub.publish(message) + + rate.sleep() + +if __name__ == '__main__': + try: + emotion_detection() + except rospy.ROSInterruptException: + pass diff --git a/genEmotions.py b/genEmotions.py new file mode 100644 index 0000000000000000000000000000000000000000..71f358d351281a68b427f5ecc4ffb4a91371f47d --- /dev/null +++ b/genEmotions.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +""" +Author: Henrique C. Siqueira +Modified by: Alexander Sutherland 9/10/2017 +Version: 1.0.0 + +Creative Workshop - Barcelona +Description: +Emotion recognition based on facial expressions. +Output categories: anger, happiness, neutral, sadness, surprise, and no emotion/face found (None) + +Place holder emotion detector that generates a probabilities for emotions +""" + +import numpy as np + + +def get_emotion(): + to_return = '' + emotions = ['Anger', 'Happiness', 'Neutral', 'Sadness', 'Surprise', 'None'] + probabilities = np.random.rand(6) + probabilities = np.exp(probabilities - np.max(probabilities)) + probabilities = (probabilities / probabilities.sum()) + + for i in range(6): + to_return += (emotions[i] + '-%.2f;' % (probabilities[i])) + + return probabilities + +print(get_emotion()) \ No newline at end of file diff --git a/genEmotions.pyc b/genEmotions.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0750a50090a2fb605d21cf7d135ced3a73ddcdc0 Binary files /dev/null and b/genEmotions.pyc differ diff --git a/listener.py b/listener.py new file mode 100755 index 0000000000000000000000000000000000000000..36157be96f7b81b5cf6bd3980f478a4815c1983f --- /dev/null +++ b/listener.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Revision $Id$ + +## Simple talker demo that listens to std_msgs/Strings published +## to the 'chatter' topic + +import rospy +from std_msgs.msg import String + +def callback(data): + rospy.loginfo(rospy.get_caller_id() + 'I heard %s', data.data) + +def listener(): + + # In ROS, nodes are uniquely named. If two nodes with the same + # name are launched, the previous one is kicked off. The + # anonymous=True flag means that rospy will choose a unique + # name for our 'listener' node so that multiple listeners can + # run simultaneously. + rospy.init_node('listener', anonymous=True) + + rospy.Subscriber('emotions', String, callback) + + # spin() simply keeps python from exiting until this node is stopped + rospy.spin() + +if __name__ == '__main__': + listener()