[PYTHON] Linebot "Kaongakun" qui lit la musique qui correspond à votre humeur à partir de votre expression et la propose

Contexte de la création de Linebot "Je veux créer quelque chose en utilisant l'IA de reconnaissance d'image ..."

"Je souhaite créer une application de proposition musicale à l'aide de l'API Spotify ..."

"Saya! Créez une application qui suggère une musique intense avec un visage en colère, une musique apaisante acoustique avec un visage triste et une musique POP lumineuse avec un sourire!"

Donc, ce développement a commencé.

Fin de la démonstration

238cahpk.png Il peut être utilisé à partir du QR ci-dessus.

J'ai abusé de cette image dans mon test et je me suis retrouvé avec une icône. Lol IMG_4171.JPG

Cible ・ Les personnes qui souhaitent proposer une musique adaptée à leur humeur ・ Les personnes qui souhaitent ajouter une musique de fond à leurs photos de visage (?)

Environnement de développement Python3.7.5 microsoftFaceAPI SpotifyAPI LineMessagingAPI Heroku

Comment faire

Débit
  1. L'utilisateur envoie une photo de visage à Linebot </ b> (main.py)
  2. Analysez les émotions des photos du visage via Face API </ b> (face_api.py)
  3. Jetez les valeurs d'analyse des émotions dans l ' API Spotify </ b> et renvoyez la musique qui correspond à vos émotions à partir des données musicales à l'utilisateur (spotify_api.py)

1. L'utilisateur envoie une photo de visage à Linebot (main.py) Programme

main.py



app = Flask(__name__)

#Le jeton d'accès des développeurs LINE et le secret de canal sont définis dans la variable d'environnement heroku
#Code à obtenir
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)

header = {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + LINE_CHANNEL_ACCESS_TOKEN
}

#Code pour vérifier si le déploiement sur heroku a réussi
@app.route("/")
def hello_world():
    return "hello world!"


#Spécifiez une URL pour le webhook LINE Developers afin que le webhook envoie des événements à l'URL
@app.route("/callback", methods=['POST'])
def callback():
    #Obtenez la valeur pour la vérification de la signature à partir de l'en-tête de la demande
    signature = request.headers['X-Line-Signature']

    #Obtenir le corps de la demande
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    #Validez la signature et appelez la fonction définie dans le handle s'il n'y a pas de problème
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'


#Ci-dessous décrit comment gérer l'événement envoyé à partir du webhook
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):

    print("C'est une lettre")
    line_bot_api.reply_message(
    event.reply_token,
    TextSendMessage(text="Veuillez m'envoyer une photo de votre visage!"))


#Traitement lorsque le message envoyé est une image
@handler.add(MessageEvent, message=ImageMessage)
def handle_message(event):

    message_id = event.message.id
    print(message_id)

    #face_api.Analyse d'image avec py
    face1 = face_api.FaceApi1(getImageLine(message_id))
    face2 = face_api.FaceApi2(getImageLine(message_id))
    print(face1)
    print(face2)

    text1 = json.dumps(face1[1][0])
    text2 = json.dumps(face1[1][1])
    text3 = json.dumps(face1[1][2])

    line_bot_api.reply_message(
    event.reply_token,
    TextSendMessage(text='Le vôtre maintenant' + 
        str(face1[0][0]) + ':' + str(face1[0][1] * 100) + '%、' + 
        str(face2[0]) + ':' + str(face2[1] * 100) + "%Je me sens comme! Je pense que cette chanson correspond\n\n" + 
        'nom d'artiste:' + text1 + "\n\n" + 'Titre de la chanson:' + text2 + "\n\n" + text3))
    #TextSendMessage(text=spotify_api.SpotifyApi())
    print("C'est une image")

def getImageLine(id):
    #L'url de l'image envoyée
    line_url = 'https://api.line.me/v2/bot/message/' + id + '/content/'

    #Obtenir une image
    result = requests.get(line_url, headers=header)
    print(result)

    #Enregistrer l'image
    im = Image.open(BytesIO(result.content))
    filename = '/tmp/' + id + '.jpg'
    print(filename)
    im.save(filename)

    return filename
#Réglage du numéro de port
if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)

2. Analysez les émotions des photos du visage via FaceAPI (face_api.py) Ensuite, demandez à l'API Face de reconnaître les émotions de l'image envoyée depuis main.py.

face_api.py


#Obtenez les émotions les plus élevées
def FaceApi1(file):

	#URL de l'image
	image_url = file

	faces = CF.face.detect(image_url, face_id=True, landmarks=False, attributes='emotion')
	#Formatez les résultats de sortie pour une visualisation facile
	print(type(faces))
	print (faces[0])

	total = faces[0]
	attr = total['faceAttributes']
	emotion = attr['emotion']
	anger = emotion['anger']
	contempt = emotion['contempt']
	disgust = emotion['disgust']
	fear = emotion['fear']
	happiness = emotion['happiness']
	neutral = emotion['neutral']
	sadness = emotion['sadness']
	surprise = emotion['surprise']

	#Trier par numéro supérieur
	emotion2 = max(emotion.items(), key=lambda x:x[1])
	print(emotion2)

	track_href = spotify_api.SpotifyApi(emotion2)

	return emotion2, track_href

Si vous envoyez cette image, ...

IMG_4171.JPG

'faceAttributes':
 {'emotion': 
{'anger': 0.001, 
'contempt': 0.0,
'disgust': 0.0, 
'fear': 0.0, 
'happiness': 0.0,
'neutral': 0.0, 
'sadness': 0.0, 
'surprise': 0.999}}}

J'ai pu avoir un visage surpris.

3. Analyse des émotions Lancez des valeurs numériques dans API Spotify et renvoyez la musique qui correspond aux émotions des données musicales à l'utilisateur (spotify_api.py)

Tout d'abord, obtenez le classement CSV dans Spotify.

spotify_api.py


songs = pd.read_csv("top100.csv", index_col=0, encoding="utf-8")
print(songs.head(10))

Et nous obtiendrons également des données détaillées sur chaque chanson.

spotify_api.py


	i = 0
	for url in songs["URL"] : 
		df = pd.DataFrame.from_dict(spotify.audio_features(url))
		song_info = song_info.append(df)

		song_info.iat[i, 0] = url
		i += 1

Lorsque vous l'obtenez, vous pouvez voir que l ' API spotify </ b> fournit des informations incomplètes pour chaque chanson sous forme de données.


'danceability': {143: 0.935}, 'energy': {143: 0.454}, 'key': {143: 1.0}, 'loudness': {143: -7.509}, 'mode': {143: 1.0}, 'speechiness': {143: 0.375}, 'acousticness': {143: 0.0194}, 'instrumentalness': {143: 0.0}, 'liveness': {143: 0.0824}, 'valence': {143: 0.357}, 'tempo': {143: 133.073}

Il semble que si la chanson est facile à danser, l'aptitude à danser sera élevée, et si c'est une chanson féroce, le volume sera élevé!

Les détails peuvent être trouvés ici. L'histoire selon laquelle les informations intégrées dans les chansons de Spotify ne sont pas humoristiques

Enfin, sur la base des données d'image , si le bonheur est élevé, la vélance (luminosité de la chanson) est élevée. Si la surprise est élevée, les chansons avec une grande dansabilité seront triées.

spotify_api.py



	if tpl[0] == 'happiness':
		print('happiness')
		ser_abs_diff = (song_info['valence']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url

	elif tpl[0] == 'contempt':
		print('a')		
		ser_abs_diff = (song_info['loudness']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url


	elif tpl[0] == 'disgust' or tpl[0] == 'fear':
		print('a')
		ser_abs_diff = (song_info['energy']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url

	elif tpl[0] == 'anger':
		print('anger')
		ser_abs_diff = (song_info['loudness']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url

	elif tpl[0] == 'neutral':
		print('neutral')

		ser_abs_diff = (song_info['valence']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url


	elif tpl[0] == 'sadness':
		print('sadness')

		ser_abs_diff = (song_info['acousticness']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url

	elif tpl[0] == 'surprise':
		print('surprise')
		ser_abs_diff = (song_info['danceability']-tpl[1]).abs()
		min_val = ser_abs_diff.min()

		ts = song_info[ser_abs_diff == min_val]

		href = ts['URL']
		art = ts['artist']
		name = ts['track']

		d = ts.to_dict()
		print(d)

		d_url = d['URL']
		print(d_url)
		d_art = d['artist']
		print(d_art)
		d_name = d['track']

		return d_art,d_name,d_url

	else:
		print('a')


Je m'inquiète du type de musique à jouer quand il est neutre (visage normal). .. ..

J'attendrai si vous avez une opinion. .. ..

Terminé! Si vous envoyez cette image, ... ![IMG_4171.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643906/0a1ee754-5065-34b0-4db3-a80b3f768e07.jpeg)

Obtenez ce sentiment,

'faceAttributes': {
'emotion': {
'anger': 0.001, 
'contempt': 0.0, 
'disgust': 0.0, 
'fear': 0.0, 
'happiness': 0.0, 
'neutral': 0.0, 
'sadness': 0.0, 
'surprise': 0.999}}

J'ai été surpris, alors quand j'ai tiré de la musique c'était facile à danser

 {'URL': {143: 'https://open.spotify.com/track/4Oun2ylbjFKMPTiaSbbCih'}, 'track': {143: 'WAP (feat. Megan Thee Stallion)'}, 'artist': {143: 'Cardi B'}, 'danceability': {143: 0.935}, 'energy': {143: 0.454}, 'key': {143: 1.0}, 'loudness': {143: -7.509}, 'mode': {143: 1.0}, 'speechiness': {143: 0.375}, 'acousticness': {143: 0.0194}, 'instrumentalness': {143: 0.0}, 'liveness': {143: 0.0824}, 'valence': {143: 0.357}, 'tempo': {143: 133.073}, 'type': {143: 'audio_features'}, 'id': {143: '4Oun2ylbjFKMPTiaSbbCih'}, 'uri': {143: 'spotify:track:4Oun2ylbjFKMPTiaSbbCih'}, 'track_href': {143: 'https://api.spotify.com/v1/tracks/4Oun2ylbjFKMPTiaSbbCih'}, 'analysis_url': {143: 'https://api.spotify.com/v1/audio-analysis/4Oun2ylbjFKMPTiaSbbCih'}, 'duration_ms': {143: 187541.0}, 'time_signature': {143: 4.0}, 'rank': {143: 144}}

Nom de l'artiste: Cardi B Titre de la chanson: WAP (feat. Megan Thee Stallion) https://open.spotify.com/track/4Oun2ylbjFKMPTiaSbbCih

Quand j'ai écouté la musique ci-dessus, j'ai pu obtenir la musique super fluide! !!

Améliorations ・ Il y a des caractères déformés ・ La lecture des informations musicales est lente. ・ Sortie après traitement des données plus

Enfin Quand j'y réfléchis attentivement, je pense que la musique qui correspond à l'expression est ce qu'elle est. J'ai pensé que ce serait intéressant d'avoir BGM sur ma photo de visage, alors je l'ai créée.

Il y a tellement d'informations dans l'API Spotify et l'API Face, J'aimerais refaire quelque chose.