[PYTHON] Linebot "Kaongakun", der Musik liest, die Ihrer Stimmung entspricht, und sie vorschlägt

Hintergrund der Erstellung von Linebot "Ich möchte etwas mit Bilderkennungs-KI machen ..."

"Ich möchte eine Musikvorschlags-App mit der Spotify-API erstellen ..."

"Saya! Mach eine App, die intensive Musik mit einem wütenden Gesicht, akustisch beruhigende Musik mit einem traurigen Gesicht und POP helle Musik mit einem Lächeln vorschlägt!"

Diese Entwicklung hat also begonnen.

Abschlussdemo

238cahpk.png Es kann aus dem obigen QR verwendet werden.

Ich habe dieses Bild in meinem Test überbeansprucht und am Ende ein Symbol erhalten. Lol IMG_4171.JPG

Ziel ・ Leute, die Musik vorschlagen möchten, die zu ihrer Stimmung passt ・ Personen, die BGM zu ihren Gesichtsfotos hinzufügen möchten (?)

Entwicklungsumgebung Python3.7.5 microsoftFaceAPI SpotifyAPI LineMessagingAPI Heroku

Wie mache ich ?

Durchfluss
  1. Benutzer sendet Gesichtsfoto an Linebot </ b> (main.py)
  2. Analysieren Sie die Emotionen von Gesichtsfotos mithilfe der Face API </ b> (face_api.py).
  3. Werfen Sie Emotionsanalysenummern in die Spotify-API </ b> und geben Sie Musik, die Ihren Emotionen entspricht, aus den Musikdaten an den Benutzer zurück (spotify_api.py).

1. Der Benutzer sendet ein Gesichtsfoto an Linebot (main.py)
Programm

main.py



app = Flask(__name__)

#LINE Entwickler greifen auf Token und Channel Secret zu, die in der Heroku-Umgebungsvariablen festgelegt sind
#Code zu bekommen
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, um zu überprüfen, ob die Bereitstellung für Heroku erfolgreich war
@app.route("/")
def hello_world():
    return "hello world!"


#Geben Sie eine URL für den Webhook von LINE Developers an, damit der Webhook ein Ereignis an die URL sendet
@app.route("/callback", methods=['POST'])
def callback():
    #Rufen Sie den Wert für die Signaturüberprüfung aus dem Anforderungsheader ab
    signature = request.headers['X-Line-Signature']

    #Anfragetext abrufen
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    #Überprüfen Sie die Signatur und rufen Sie die im Handle definierte Funktion auf, wenn kein Problem vorliegt
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'


#Im Folgenden wird beschrieben, wie das vom Webhook gesendete Ereignis behandelt wird
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):

    print("Es ist ein Brief")
    line_bot_api.reply_message(
    event.reply_token,
    TextSendMessage(text="Bitte senden Sie mir ein Foto von Ihrem Gesicht!"))


#Verarbeitung, wenn die gesendete Nachricht ein Bild ist
@handler.add(MessageEvent, message=ImageMessage)
def handle_message(event):

    message_id = event.message.id
    print(message_id)

    #face_api.Bildanalyse mit 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='Dein jetzt' + 
        str(face1[0][0]) + ':' + str(face1[0][1] * 100) + '%、' + 
        str(face2[0]) + ':' + str(face2[1] * 100) + "%Ich fühle mich wie! Ich denke, dieses Lied passt\n\n" + 
        'Künstlername:' + text1 + "\n\n" + 'Song Titel:' + text2 + "\n\n" + text3))
    #TextSendMessage(text=spotify_api.SpotifyApi())
    print("Es ist ein Bild")

def getImageLine(id):
    #Die URL des gesendeten Bildes
    line_url = 'https://api.line.me/v2/bot/message/' + id + '/content/'

    #Holen Sie sich ein Bild
    result = requests.get(line_url, headers=header)
    print(result)

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

    return filename
#Einstellung der Portnummer
if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)

2. Analysieren Sie die Emotionen von Gesichtsfotos mit FaceAPI (face_api.py) Lassen Sie als Nächstes die Gesichts-API die Emotionen des von main.py gesendeten Bildes erkennen.

face_api.py


#Holen Sie sich die höchsten Emotionen
def FaceApi1(file):

	#Bild URL
	image_url = file

	faces = CF.face.detect(image_url, face_id=True, landmarks=False, attributes='emotion')
	#Formatieren Sie die Ausgabeergebnisse für eine einfache Anzeige
	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']

	#Nach höherer Nummer sortieren
	emotion2 = max(emotion.items(), key=lambda x:x[1])
	print(emotion2)

	track_href = spotify_api.SpotifyApi(emotion2)

	return emotion2, track_href

Wenn Sie dieses Bild senden, ...

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}}}

Ich konnte ein überraschtes Gesicht bekommen.

3. Emotionsanalyse Werfen Sie numerische Werte in die Spotify-API und geben Sie Musik, die den Emotionen aus Musikdaten entspricht, an den Benutzer zurück (spotify_api.py).

Holen Sie sich zuerst die Rangliste CSV in spotify.

spotify_api.py


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

Außerdem erhalten wir detaillierte Daten zu jedem Song.

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

Wenn Sie es erhalten, können Sie sehen, dass die spotify API </ b> unvollständige Informationen für jedes Lied als Daten bereitstellt.


'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}

Es scheint, dass wenn das Lied leicht zu tanzen ist, die Tanzbarkeit hoch sein wird, und wenn es ein heftiges Lied ist, wird die Lautstärke hoch sein!

Details finden Sie hier. Die Geschichte, dass die in Spotifys Songs eingebetteten Informationen nicht humorvoll sind

Basierend auf den Bilddaten ist schließlich die Geschwindigkeit (Liedhelligkeit) hoch, wenn das Glück hoch ist. Wenn die Überraschung hoch ist, werden Songs mit hoher Tanzbarkeit sortiert.

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')


Ich mache mir Sorgen darüber, welche Art von Musik ich spielen soll, wenn ich neutral bin (normales Gesicht). .. ..

Ich werde warten, wenn Sie eine Meinung haben. .. ..

Abgeschlossen! Wenn Sie dieses Bild senden, ... ![IMG_4171.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643906/0a1ee754-5065-34b0-4db3-a80b3f768e07.jpeg)

Holen Sie sich dieses Gefühl,

'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}}

Ich war überrascht, als ich Musik zog, die leicht zu tanzen war

 {'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}}

Künstlername: Cardi B. Songtitel: WAP (feat. Megan Thee Stallion) https://open.spotify.com/track/4Oun2ylbjFKMPTiaSbbCih

Als ich die obige Musik hörte, konnte ich die superweiche Musik bekommen! !!

Verbesserungen ・ Es gibt einige verstümmelte Charaktere ・ Das Lesen von Musikinformationen ist langsam. ・ Ausgabe nach Verarbeitung der Daten mehr

Endlich Wenn ich sorgfältig darüber nachdenke, denke ich, dass Musik, die zum Ausdruck passt, das ist, was sie ist. Ich dachte, es wäre interessant, BGM auf meinem Gesichtsfoto zu haben, also habe ich es erstellt.

Es gibt so viele Informationen sowohl in der Spotify-API als auch in der Face-API. Ich würde gerne wieder etwas machen.